Coverage Report

Created: 2025-08-29 07:13

/src/cpython3/Modules/posixmodule.c
Line
Count
Source (jump to first uncovered line)
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.23k
#  define STAT stat
406
0
#  define LSTAT lstat
407
0
#  define FSTAT fstat
408
2.23k
#  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
693
void
694
PyOS_AfterFork_Child(void)
695
0
{
696
0
    PyStatus status;
697
0
    _PyRuntimeState *runtime = &_PyRuntime;
698
699
    // re-creates runtime->interpreters.mutex (HEAD_UNLOCK)
700
0
    status = _PyRuntimeState_ReInitThreads(runtime);
701
0
    if (_PyStatus_EXCEPTION(status)) {
702
0
        goto fatal_error;
703
0
    }
704
705
0
    PyThreadState *tstate = _PyThreadState_GET();
706
0
    _Py_EnsureTstateNotNULL(tstate);
707
708
0
    assert(tstate->thread_id == PyThread_get_thread_ident());
709
0
#ifdef PY_HAVE_THREAD_NATIVE_ID
710
0
    tstate->native_thread_id = PyThread_get_thread_native_id();
711
0
#endif
712
713
#ifdef Py_GIL_DISABLED
714
    _Py_brc_after_fork(tstate->interp);
715
    _Py_qsbr_after_fork((_PyThreadStateImpl *)tstate);
716
#endif
717
718
    // Ideally we could guarantee tstate is running main.
719
0
    _PyInterpreterState_ReinitRunningMain(tstate);
720
721
0
    status = _PyEval_ReInitThreads(tstate);
722
0
    if (_PyStatus_EXCEPTION(status)) {
723
0
        goto fatal_error;
724
0
    }
725
726
0
    reset_remotedebug_data(tstate);
727
728
    // Remove the dead thread states. We "start the world" once we are the only
729
    // thread state left to undo the stop the world call in `PyOS_BeforeFork`.
730
    // That needs to happen before `_PyThreadState_DeleteList`, because that
731
    // may call destructors.
732
0
    PyThreadState *list = _PyThreadState_RemoveExcept(tstate);
733
0
    _PyEval_StartTheWorldAll(&_PyRuntime);
734
0
    _PyThreadState_DeleteList(list, /*is_after_fork=*/1);
735
736
0
    _PyImport_ReInitLock(tstate->interp);
737
0
    _PyImport_ReleaseLock(tstate->interp);
738
739
0
    _PySignal_AfterFork();
740
741
0
    status = _PyInterpreterState_DeleteExceptMain(runtime);
742
0
    if (_PyStatus_EXCEPTION(status)) {
743
0
        goto fatal_error;
744
0
    }
745
0
    assert(_PyThreadState_GET() == tstate);
746
747
0
    status = _PyPerfTrampoline_AfterFork_Child();
748
0
    if (_PyStatus_EXCEPTION(status)) {
749
0
        goto fatal_error;
750
0
    }
751
752
0
    run_at_forkers(tstate->interp->after_forkers_child, 0);
753
0
    return;
754
755
0
fatal_error:
756
0
    Py_ExitStatusException(status);
757
0
}
758
759
static int
760
register_at_forker(PyObject **lst, PyObject *func)
761
0
{
762
0
    if (func == NULL)  /* nothing to register? do nothing. */
763
0
        return 0;
764
0
    if (*lst == NULL) {
765
0
        *lst = PyList_New(0);
766
0
        if (*lst == NULL)
767
0
            return -1;
768
0
    }
769
0
    return PyList_Append(*lst, func);
770
0
}
771
#endif  /* HAVE_FORK */
772
773
774
/* Legacy wrapper */
775
void
776
PyOS_AfterFork(void)
777
0
{
778
0
#ifdef HAVE_FORK
779
0
    PyOS_AfterFork_Child();
780
0
#endif
781
0
}
782
783
784
#ifdef MS_WINDOWS
785
/* defined in fileutils.c */
786
void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
787
void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *, ULONG,
788
                                FILE_BASIC_INFO *, FILE_ID_INFO *,
789
                                struct _Py_stat_struct *);
790
void _Py_stat_basic_info_to_stat(FILE_STAT_BASIC_INFORMATION *,
791
                                 struct _Py_stat_struct *);
792
#endif
793
794
795
#ifndef MS_WINDOWS
796
PyObject *
797
_PyLong_FromUid(uid_t uid)
798
2.04k
{
799
2.04k
    if (uid == (uid_t)-1)
800
0
        return PyLong_FromLong(-1);
801
2.04k
    return PyLong_FromUnsignedLong(uid);
802
2.04k
}
803
804
PyObject *
805
_PyLong_FromGid(gid_t gid)
806
2.04k
{
807
2.04k
    if (gid == (gid_t)-1)
808
0
        return PyLong_FromLong(-1);
809
2.04k
    return PyLong_FromUnsignedLong(gid);
810
2.04k
}
811
812
int
813
_Py_Uid_Converter(PyObject *obj, uid_t *p)
814
0
{
815
0
    uid_t uid;
816
0
    PyObject *index;
817
0
    int overflow;
818
0
    long result;
819
0
    unsigned long uresult;
820
821
0
    index = _PyNumber_Index(obj);
822
0
    if (index == NULL) {
823
0
        PyErr_Format(PyExc_TypeError,
824
0
                     "uid should be integer, not %.200s",
825
0
                     _PyType_Name(Py_TYPE(obj)));
826
0
        return 0;
827
0
    }
828
829
    /*
830
     * Handling uid_t is complicated for two reasons:
831
     *  * Although uid_t is (always?) unsigned, it still
832
     *    accepts -1.
833
     *  * We don't know its size in advance--it may be
834
     *    bigger than an int, or it may be smaller than
835
     *    a long.
836
     *
837
     * So a bit of defensive programming is in order.
838
     * Start with interpreting the value passed
839
     * in as a signed long and see if it works.
840
     */
841
842
0
    result = PyLong_AsLongAndOverflow(index, &overflow);
843
844
0
    if (!overflow) {
845
0
        uid = (uid_t)result;
846
847
0
        if (result == -1) {
848
0
            if (PyErr_Occurred())
849
0
                goto fail;
850
            /* It's a legitimate -1, we're done. */
851
0
            goto success;
852
0
        }
853
854
        /* Any other negative number is disallowed. */
855
0
        if (result < 0)
856
0
            goto underflow;
857
858
        /* Ensure the value wasn't truncated. */
859
0
        if (sizeof(uid_t) < sizeof(long) &&
860
0
            (long)uid != result)
861
0
            goto underflow;
862
0
        goto success;
863
0
    }
864
865
0
    if (overflow < 0)
866
0
        goto underflow;
867
868
    /*
869
     * Okay, the value overflowed a signed long.  If it
870
     * fits in an *unsigned* long, it may still be okay,
871
     * as uid_t may be unsigned long on this platform.
872
     */
873
0
    uresult = PyLong_AsUnsignedLong(index);
874
0
    if (PyErr_Occurred()) {
875
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError))
876
0
            goto overflow;
877
0
        goto fail;
878
0
    }
879
880
0
    uid = (uid_t)uresult;
881
882
    /*
883
     * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
884
     * but this value would get interpreted as (uid_t)-1  by chown
885
     * and its siblings.   That's not what the user meant!  So we
886
     * throw an overflow exception instead.   (We already
887
     * handled a real -1 with PyLong_AsLongAndOverflow() above.)
888
     */
889
0
    if (uid == (uid_t)-1)
890
0
        goto overflow;
891
892
    /* Ensure the value wasn't truncated. */
893
0
    if (sizeof(uid_t) < sizeof(long) &&
894
0
        (unsigned long)uid != uresult)
895
0
        goto overflow;
896
    /* fallthrough */
897
898
0
success:
899
0
    Py_DECREF(index);
900
0
    *p = uid;
901
0
    return 1;
902
903
0
underflow:
904
0
    PyErr_SetString(PyExc_OverflowError,
905
0
                    "uid is less than minimum");
906
0
    goto fail;
907
908
0
overflow:
909
0
    PyErr_SetString(PyExc_OverflowError,
910
0
                    "uid is greater than maximum");
911
    /* fallthrough */
912
913
0
fail:
914
0
    Py_DECREF(index);
915
0
    return 0;
916
0
}
917
918
int
919
_Py_Gid_Converter(PyObject *obj, gid_t *p)
920
0
{
921
0
    gid_t gid;
922
0
    PyObject *index;
923
0
    int overflow;
924
0
    long result;
925
0
    unsigned long uresult;
926
927
0
    index = _PyNumber_Index(obj);
928
0
    if (index == NULL) {
929
0
        PyErr_Format(PyExc_TypeError,
930
0
                     "gid should be integer, not %.200s",
931
0
                     _PyType_Name(Py_TYPE(obj)));
932
0
        return 0;
933
0
    }
934
935
    /*
936
     * Handling gid_t is complicated for two reasons:
937
     *  * Although gid_t is (always?) unsigned, it still
938
     *    accepts -1.
939
     *  * We don't know its size in advance--it may be
940
     *    bigger than an int, or it may be smaller than
941
     *    a long.
942
     *
943
     * So a bit of defensive programming is in order.
944
     * Start with interpreting the value passed
945
     * in as a signed long and see if it works.
946
     */
947
948
0
    result = PyLong_AsLongAndOverflow(index, &overflow);
949
950
0
    if (!overflow) {
951
0
        gid = (gid_t)result;
952
953
0
        if (result == -1) {
954
0
            if (PyErr_Occurred())
955
0
                goto fail;
956
            /* It's a legitimate -1, we're done. */
957
0
            goto success;
958
0
        }
959
960
        /* Any other negative number is disallowed. */
961
0
        if (result < 0) {
962
0
            goto underflow;
963
0
        }
964
965
        /* Ensure the value wasn't truncated. */
966
0
        if (sizeof(gid_t) < sizeof(long) &&
967
0
            (long)gid != result)
968
0
            goto underflow;
969
0
        goto success;
970
0
    }
971
972
0
    if (overflow < 0)
973
0
        goto underflow;
974
975
    /*
976
     * Okay, the value overflowed a signed long.  If it
977
     * fits in an *unsigned* long, it may still be okay,
978
     * as gid_t may be unsigned long on this platform.
979
     */
980
0
    uresult = PyLong_AsUnsignedLong(index);
981
0
    if (PyErr_Occurred()) {
982
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError))
983
0
            goto overflow;
984
0
        goto fail;
985
0
    }
986
987
0
    gid = (gid_t)uresult;
988
989
    /*
990
     * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
991
     * but this value would get interpreted as (gid_t)-1  by chown
992
     * and its siblings.   That's not what the user meant!  So we
993
     * throw an overflow exception instead.   (We already
994
     * handled a real -1 with PyLong_AsLongAndOverflow() above.)
995
     */
996
0
    if (gid == (gid_t)-1)
997
0
        goto overflow;
998
999
    /* Ensure the value wasn't truncated. */
1000
0
    if (sizeof(gid_t) < sizeof(long) &&
1001
0
        (unsigned long)gid != uresult)
1002
0
        goto overflow;
1003
    /* fallthrough */
1004
1005
0
success:
1006
0
    Py_DECREF(index);
1007
0
    *p = gid;
1008
0
    return 1;
1009
1010
0
underflow:
1011
0
    PyErr_SetString(PyExc_OverflowError,
1012
0
                    "gid is less than minimum");
1013
0
    goto fail;
1014
1015
0
overflow:
1016
0
    PyErr_SetString(PyExc_OverflowError,
1017
0
                    "gid is greater than maximum");
1018
    /* fallthrough */
1019
1020
0
fail:
1021
0
    Py_DECREF(index);
1022
0
    return 0;
1023
0
}
1024
#endif /* MS_WINDOWS */
1025
1026
1027
static PyObject *
1028
_PyLong_FromDev(dev_t dev)
1029
2.00k
{
1030
2.00k
#ifdef NODEV
1031
2.00k
    if (dev == NODEV) {
1032
0
        return PyLong_FromLongLong((long long)dev);
1033
0
    }
1034
2.00k
#endif
1035
2.00k
    return PyLong_FromUnsignedLongLong((unsigned long long)dev);
1036
2.00k
}
1037
1038
1039
#if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS)
1040
static int
1041
_Py_Dev_Converter(PyObject *obj, void *p)
1042
0
{
1043
0
    if (!PyLong_Check(obj)) {
1044
0
        obj = _PyNumber_Index(obj);
1045
0
        if (obj == NULL) {
1046
0
            return 0;
1047
0
        }
1048
0
    }
1049
0
    else {
1050
0
        Py_INCREF(obj);
1051
0
    }
1052
0
    assert(PyLong_Check(obj));
1053
0
#ifdef NODEV
1054
0
    if (_PyLong_IsNegative((PyLongObject *)obj)) {
1055
0
        int overflow;
1056
0
        long long result = PyLong_AsLongLongAndOverflow(obj, &overflow);
1057
0
        if (result == -1 && PyErr_Occurred()) {
1058
0
            Py_DECREF(obj);
1059
0
            return 0;
1060
0
        }
1061
0
        if (!overflow && result == (long long)NODEV) {
1062
0
            *((dev_t *)p) = NODEV;
1063
0
            Py_DECREF(obj);
1064
0
            return 1;
1065
0
        }
1066
0
    }
1067
0
#endif
1068
1069
0
    unsigned long long result = PyLong_AsUnsignedLongLong(obj);
1070
0
    Py_DECREF(obj);
1071
0
    if (result == (unsigned long long)-1 && PyErr_Occurred()) {
1072
0
        return 0;
1073
0
    }
1074
0
    if ((unsigned long long)(dev_t)result != result) {
1075
0
        PyErr_SetString(PyExc_OverflowError,
1076
0
                        "Python int too large to convert to C dev_t");
1077
0
        return 0;
1078
0
    }
1079
0
    *((dev_t *)p) = (dev_t)result;
1080
0
    return 1;
1081
0
}
1082
#endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */
1083
1084
1085
#ifdef AT_FDCWD
1086
/*
1087
 * Why the (int) cast?  Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
1088
 * without the int cast, the value gets interpreted as uint (4291925331),
1089
 * which doesn't play nicely with all the initializer lines in this file that
1090
 * look like this:
1091
 *      int dir_fd = DEFAULT_DIR_FD;
1092
 */
1093
9.03k
#define DEFAULT_DIR_FD (int)AT_FDCWD
1094
#else
1095
#define DEFAULT_DIR_FD (-100)
1096
#endif
1097
1098
static int
1099
_fd_converter(PyObject *o, int *p)
1100
0
{
1101
0
    int overflow;
1102
0
    long long_value;
1103
1104
0
    if (PyBool_Check(o)) {
1105
0
        if (PyErr_WarnEx(PyExc_RuntimeWarning,
1106
0
                "bool is used as a file descriptor", 1))
1107
0
        {
1108
0
            return 0;
1109
0
        }
1110
0
    }
1111
0
    PyObject *index = _PyNumber_Index(o);
1112
0
    if (index == NULL) {
1113
0
        return 0;
1114
0
    }
1115
1116
0
    assert(PyLong_Check(index));
1117
0
    long_value = PyLong_AsLongAndOverflow(index, &overflow);
1118
0
    Py_DECREF(index);
1119
0
    assert(!PyErr_Occurred());
1120
0
    if (overflow > 0 || long_value > INT_MAX) {
1121
0
        PyErr_SetString(PyExc_OverflowError,
1122
0
                        "fd is greater than maximum");
1123
0
        return 0;
1124
0
    }
1125
0
    if (overflow < 0 || long_value < INT_MIN) {
1126
0
        PyErr_SetString(PyExc_OverflowError,
1127
0
                        "fd is less than minimum");
1128
0
        return 0;
1129
0
    }
1130
1131
0
    *p = (int)long_value;
1132
0
    return 1;
1133
0
}
1134
1135
static int
1136
dir_fd_converter(PyObject *o, void *p)
1137
44
{
1138
44
    if (o == Py_None) {
1139
44
        *(int *)p = DEFAULT_DIR_FD;
1140
44
        return 1;
1141
44
    }
1142
0
    else if (PyIndex_Check(o)) {
1143
0
        return _fd_converter(o, (int *)p);
1144
0
    }
1145
0
    else {
1146
0
        PyErr_Format(PyExc_TypeError,
1147
0
                     "argument should be integer or None, not %.200s",
1148
0
                     _PyType_Name(Py_TYPE(o)));
1149
0
        return 0;
1150
0
    }
1151
44
}
1152
1153
typedef struct {
1154
    PyObject *billion;
1155
    PyObject *DirEntryType;
1156
    PyObject *ScandirIteratorType;
1157
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
1158
    PyObject *SchedParamType;
1159
#endif
1160
    newfunc statresult_new_orig;
1161
    PyObject *StatResultType;
1162
    PyObject *StatVFSResultType;
1163
    PyObject *TerminalSizeType;
1164
    PyObject *TimesResultType;
1165
    PyObject *UnameResultType;
1166
#if defined(HAVE_WAITID)
1167
    PyObject *WaitidResultType;
1168
#endif
1169
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
1170
    PyObject *struct_rusage;
1171
#endif
1172
    PyObject *st_mode;
1173
#ifndef MS_WINDOWS
1174
    // times() clock frequency in hertz; used by os.times()
1175
    long ticks_per_second;
1176
#endif
1177
} _posixstate;
1178
1179
1180
static inline _posixstate*
1181
get_posix_state(PyObject *module)
1182
14.7k
{
1183
14.7k
    void *state = _PyModule_GetState(module);
1184
14.7k
    assert(state != NULL);
1185
14.7k
    return (_posixstate *)state;
1186
14.7k
}
1187
1188
/*
1189
 * A PyArg_ParseTuple "converter" function
1190
 * that handles filesystem paths in the manner
1191
 * preferred by the os module.
1192
 *
1193
 * path_converter accepts (Unicode) strings and their
1194
 * subclasses, and bytes and their subclasses.  What
1195
 * it does with the argument depends on path.make_wide:
1196
 *
1197
 *   * If path.make_wide is nonzero, if we get a (Unicode)
1198
 *     string we extract the wchar_t * and return it; if we
1199
 *     get bytes we decode to wchar_t * and return that.
1200
 *
1201
 *   * If path.make_wide is zero, if we get bytes we extract
1202
 *     the char_t * and return it; if we get a (Unicode)
1203
 *     string we encode to char_t * and return that.
1204
 *
1205
 * path_converter also optionally accepts signed
1206
 * integers (representing open file descriptors) instead
1207
 * of path strings.
1208
 *
1209
 * Input fields:
1210
 *   path.nullable
1211
 *     If nonzero, the path is permitted to be None.
1212
 *   path.nonstrict
1213
 *     If nonzero, the path is permitted to contain
1214
 *     embedded null characters and have any length.
1215
 *   path.make_wide
1216
 *     If nonzero, the converter always uses wide, decoding if necessary, else
1217
 *     it always uses narrow, encoding if necessary. The default value is
1218
 *     nonzero on Windows, else zero.
1219
 *   path.suppress_value_error
1220
 *     If nonzero, raising ValueError is suppressed.
1221
 *   path.allow_fd
1222
 *     If nonzero, the path is permitted to be a file handle
1223
 *     (a signed int) instead of a string.
1224
 *   path.function_name
1225
 *     If non-NULL, path_converter will use that as the name
1226
 *     of the function in error messages.
1227
 *     (If path.function_name is NULL it omits the function name.)
1228
 *   path.argument_name
1229
 *     If non-NULL, path_converter will use that as the name
1230
 *     of the parameter in error messages.
1231
 *     (If path.argument_name is NULL it uses "path".)
1232
 *
1233
 * Output fields:
1234
 *   path.wide
1235
 *     Points to the path if it was expressed as Unicode
1236
 *     or if it was bytes and decoded to Unicode.
1237
 *   path.narrow
1238
 *     Points to the path if it was expressed as bytes,
1239
 *     or if it was Unicode and encoded to bytes.
1240
 *   path.fd
1241
 *     Contains a file descriptor if path.accept_fd was true
1242
 *     and the caller provided a signed integer instead of any
1243
 *     sort of string.
1244
 *
1245
 *     WARNING: if your "path" parameter is optional, and is
1246
 *     unspecified, path_converter will never get called.
1247
 *     So if you set allow_fd, you *MUST* initialize path.fd = -1
1248
 *     yourself!
1249
 *   path.value_error
1250
 *     If nonzero, then suppress_value_error was specified and a ValueError
1251
 *     occurred.
1252
 *   path.length
1253
 *     The length of the path in characters, if specified as
1254
 *     a string.
1255
 *   path.object
1256
 *     The original object passed in (if get a PathLike object,
1257
 *     the result of PyOS_FSPath() is treated as the original object).
1258
 *     Own a reference to the object.
1259
 *   path.cleanup
1260
 *     For internal use only.  May point to a temporary object.
1261
 *     (Pay no attention to the man behind the curtain.)
1262
 *
1263
 *   At most one of path.wide or path.narrow will be non-NULL.
1264
 *   If path was None and path.nullable was set,
1265
 *     or if path was an integer and path.allow_fd was set,
1266
 *     both path.wide and path.narrow will be NULL
1267
 *     and path.length will be 0.
1268
 *
1269
 *   path_converter takes care to not write to the path_t
1270
 *   unless it's successful.  However it must reset the
1271
 *   "cleanup" field each time it's called.
1272
 *
1273
 * Use as follows:
1274
 *      path_t path;
1275
 *      memset(&path, 0, sizeof(path));
1276
 *      PyArg_ParseTuple(args, "O&", path_converter, &path);
1277
 *      // ... use values from path ...
1278
 *      path_cleanup(&path);
1279
 *
1280
 * (Note that if PyArg_Parse fails you don't need to call
1281
 * path_cleanup().  However it is safe to do so.)
1282
 */
1283
typedef struct {
1284
    // Input fields
1285
    const char *function_name;
1286
    const char *argument_name;
1287
    int nullable;
1288
    int nonstrict;
1289
    int make_wide;
1290
    int suppress_value_error;
1291
    int allow_fd;
1292
    // Output fields
1293
    const wchar_t *wide;
1294
    const char *narrow;
1295
    int fd;
1296
    int value_error;
1297
    Py_ssize_t length;
1298
    PyObject *object;
1299
    PyObject *cleanup;
1300
} path_t;
1301
1302
#define PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, \
1303
                          make_wide, suppress_value_error, allow_fd) \
1304
2.46k
    {function_name, argument_name, nullable, nonstrict, make_wide, \
1305
2.46k
     suppress_value_error, allow_fd, NULL, NULL, -1, 0, 0, NULL, NULL}
1306
#ifdef MS_WINDOWS
1307
#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1308
                            nonstrict, suppress_value_error, allow_fd) \
1309
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 1, \
1310
                      suppress_value_error, allow_fd)
1311
#else
1312
#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1313
                            nonstrict, suppress_value_error, allow_fd) \
1314
2.35k
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 0, \
1315
2.35k
                      suppress_value_error, allow_fd)
1316
#endif
1317
1318
static void
1319
path_cleanup(path_t *path)
1320
2.46k
{
1321
2.46k
    wchar_t *wide = (wchar_t *)path->wide;
1322
2.46k
    path->wide = NULL;
1323
2.46k
    PyMem_Free(wide);
1324
2.46k
    Py_CLEAR(path->object);
1325
2.46k
    Py_CLEAR(path->cleanup);
1326
2.46k
}
1327
1328
static int
1329
path_converter(PyObject *o, void *p)
1330
2.46k
{
1331
2.46k
    path_t *path = (path_t *)p;
1332
2.46k
    PyObject *bytes = NULL;
1333
2.46k
    Py_ssize_t length = 0;
1334
2.46k
    int is_index, is_bytes, is_unicode;
1335
2.46k
    const char *narrow;
1336
2.46k
    PyObject *wo = NULL;
1337
2.46k
    wchar_t *wide = NULL;
1338
1339
2.46k
#define FORMAT_EXCEPTION(exc, fmt) \
1340
2.46k
    PyErr_Format(exc, "%s%s" fmt, \
1341
0
        path->function_name ? path->function_name : "", \
1342
0
        path->function_name ? ": "                : "", \
1343
0
        path->argument_name ? path->argument_name : "path")
1344
1345
    /* Py_CLEANUP_SUPPORTED support */
1346
2.46k
    if (o == NULL) {
1347
0
        path_cleanup(path);
1348
0
        return 1;
1349
0
    }
1350
1351
    /* Ensure it's always safe to call path_cleanup(). */
1352
2.46k
    path->object = path->cleanup = NULL;
1353
    /* path->object owns a reference to the original object */
1354
2.46k
    Py_INCREF(o);
1355
1356
2.46k
    if ((o == Py_None) && path->nullable) {
1357
0
        path->wide = NULL;
1358
0
        path->narrow = NULL;
1359
0
        path->fd = -1;
1360
0
        goto success_exit;
1361
0
    }
1362
1363
    /* Only call this here so that we don't treat the return value of
1364
       os.fspath() as an fd or buffer. */
1365
2.46k
    is_index = path->allow_fd && PyIndex_Check(o);
1366
2.46k
    is_bytes = PyBytes_Check(o);
1367
2.46k
    is_unicode = PyUnicode_Check(o);
1368
1369
2.46k
    if (!is_index && !is_unicode && !is_bytes) {
1370
        /* Inline PyOS_FSPath() for better error messages. */
1371
0
        PyObject *func, *res;
1372
1373
0
        func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__));
1374
0
        if ((NULL == func) || (func == Py_None)) {
1375
0
            goto error_format;
1376
0
        }
1377
0
        res = _PyObject_CallNoArgs(func);
1378
0
        Py_DECREF(func);
1379
0
        if (NULL == res) {
1380
0
            goto error_exit;
1381
0
        }
1382
0
        else if (PyUnicode_Check(res)) {
1383
0
            is_unicode = 1;
1384
0
        }
1385
0
        else if (PyBytes_Check(res)) {
1386
0
            is_bytes = 1;
1387
0
        }
1388
0
        else {
1389
0
            PyErr_Format(PyExc_TypeError,
1390
0
                 "expected %.200s.__fspath__() to return str or bytes, "
1391
0
                 "not %.200s", _PyType_Name(Py_TYPE(o)),
1392
0
                 _PyType_Name(Py_TYPE(res)));
1393
0
            Py_DECREF(res);
1394
0
            goto error_exit;
1395
0
        }
1396
1397
        /* still owns a reference to the original object */
1398
0
        Py_SETREF(o, res);
1399
0
    }
1400
1401
2.46k
    if (is_unicode) {
1402
2.46k
        if (path->make_wide) {
1403
110
            wide = PyUnicode_AsWideCharString(o, &length);
1404
110
            if (!wide) {
1405
0
                goto error_exit;
1406
0
            }
1407
#ifdef MS_WINDOWS
1408
            if (!path->nonstrict && length > 32767) {
1409
                FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1410
                goto error_exit;
1411
            }
1412
#endif
1413
110
            if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1414
0
                FORMAT_EXCEPTION(PyExc_ValueError,
1415
0
                                 "embedded null character in %s");
1416
0
                goto error_exit;
1417
0
            }
1418
1419
110
            path->wide = wide;
1420
110
            path->narrow = NULL;
1421
110
            path->fd = -1;
1422
110
            wide = NULL;
1423
110
            goto success_exit;
1424
110
        }
1425
2.35k
        bytes = PyUnicode_EncodeFSDefault(o);
1426
2.35k
        if (!bytes) {
1427
0
            goto error_exit;
1428
0
        }
1429
2.35k
    }
1430
0
    else if (is_bytes) {
1431
0
        bytes = Py_NewRef(o);
1432
0
    }
1433
0
    else if (is_index) {
1434
0
        if (!_fd_converter(o, &path->fd)) {
1435
0
            goto error_exit;
1436
0
        }
1437
0
        path->wide = NULL;
1438
0
        path->narrow = NULL;
1439
0
        goto success_exit;
1440
0
    }
1441
0
    else {
1442
0
 error_format:
1443
0
        PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1444
0
            path->function_name ? path->function_name : "",
1445
0
            path->function_name ? ": "                : "",
1446
0
            path->argument_name ? path->argument_name : "path",
1447
0
            path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1448
0
                                               "integer or None" :
1449
0
            path->allow_fd ? "string, bytes, os.PathLike or integer" :
1450
0
            path->nullable ? "string, bytes, os.PathLike or None" :
1451
0
                             "string, bytes or os.PathLike",
1452
0
            _PyType_Name(Py_TYPE(o)));
1453
0
        goto error_exit;
1454
0
    }
1455
1456
2.35k
    length = PyBytes_GET_SIZE(bytes);
1457
2.35k
    narrow = PyBytes_AS_STRING(bytes);
1458
2.35k
    if (!path->nonstrict && strlen(narrow) != (size_t)length) {
1459
0
        FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1460
0
        goto error_exit;
1461
0
    }
1462
1463
2.35k
    if (path->make_wide) {
1464
0
        wo = PyUnicode_DecodeFSDefaultAndSize(narrow, length);
1465
0
        if (!wo) {
1466
0
            goto error_exit;
1467
0
        }
1468
1469
0
        wide = PyUnicode_AsWideCharString(wo, &length);
1470
0
        Py_DECREF(wo);
1471
0
        if (!wide) {
1472
0
            goto error_exit;
1473
0
        }
1474
#ifdef MS_WINDOWS
1475
        if (!path->nonstrict && length > 32767) {
1476
            FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1477
            goto error_exit;
1478
        }
1479
#endif
1480
0
        if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1481
0
            FORMAT_EXCEPTION(PyExc_ValueError,
1482
0
                             "embedded null character in %s");
1483
0
            goto error_exit;
1484
0
        }
1485
0
        path->wide = wide;
1486
0
        path->narrow = NULL;
1487
0
        Py_DECREF(bytes);
1488
0
        wide = NULL;
1489
0
    }
1490
2.35k
    else {
1491
2.35k
        path->wide = NULL;
1492
2.35k
        path->narrow = narrow;
1493
2.35k
        if (bytes == o) {
1494
            /* Still a reference owned by path->object, don't have to
1495
            worry about path->narrow is used after free. */
1496
0
            Py_DECREF(bytes);
1497
0
        }
1498
2.35k
        else {
1499
2.35k
            path->cleanup = bytes;
1500
2.35k
        }
1501
2.35k
    }
1502
2.35k
    path->fd = -1;
1503
1504
2.46k
 success_exit:
1505
2.46k
    path->value_error = 0;
1506
2.46k
    path->length = length;
1507
2.46k
    path->object = o;
1508
2.46k
    return Py_CLEANUP_SUPPORTED;
1509
1510
0
 error_exit:
1511
0
    Py_XDECREF(o);
1512
0
    Py_XDECREF(bytes);
1513
0
    PyMem_Free(wide);
1514
0
    if (!path->suppress_value_error ||
1515
0
        !PyErr_ExceptionMatches(PyExc_ValueError))
1516
0
    {
1517
0
        return 0;
1518
0
    }
1519
0
    PyErr_Clear();
1520
0
    path->wide = NULL;
1521
0
    path->narrow = NULL;
1522
0
    path->fd = -1;
1523
0
    path->value_error = 1;
1524
0
    path->length = 0;
1525
0
    path->object = NULL;
1526
0
    return Py_CLEANUP_SUPPORTED;
1527
0
}
1528
1529
static void
1530
argument_unavailable_error(const char *function_name, const char *argument_name)
1531
0
{
1532
0
    PyErr_Format(PyExc_NotImplementedError,
1533
0
        "%s%s%s unavailable on this platform",
1534
0
        (function_name != NULL) ? function_name : "",
1535
0
        (function_name != NULL) ? ": ": "",
1536
0
        argument_name);
1537
0
}
1538
1539
static int
1540
dir_fd_unavailable(PyObject *o, void *p)
1541
22
{
1542
22
    int dir_fd;
1543
22
    if (!dir_fd_converter(o, &dir_fd))
1544
0
        return 0;
1545
22
    if (dir_fd != DEFAULT_DIR_FD) {
1546
0
        argument_unavailable_error(NULL, "dir_fd");
1547
0
        return 0;
1548
0
    }
1549
22
    *(int *)p = dir_fd;
1550
22
    return 1;
1551
22
}
1552
1553
static int
1554
fd_specified(const char *function_name, int fd)
1555
22
{
1556
22
    if (fd == -1)
1557
22
        return 0;
1558
1559
0
    argument_unavailable_error(function_name, "fd");
1560
0
    return 1;
1561
22
}
1562
1563
static int
1564
follow_symlinks_specified(const char *function_name, int follow_symlinks)
1565
22
{
1566
22
    if (follow_symlinks)
1567
22
        return 0;
1568
1569
0
    argument_unavailable_error(function_name, "follow_symlinks");
1570
0
    return 1;
1571
22
}
1572
1573
static int
1574
path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1575
2.23k
{
1576
2.23k
    if (!path->wide && (dir_fd != DEFAULT_DIR_FD) && !path->narrow) {
1577
0
        PyErr_Format(PyExc_ValueError,
1578
0
                     "%s: can't specify dir_fd without matching path",
1579
0
                     function_name);
1580
0
        return 1;
1581
0
    }
1582
2.23k
    return 0;
1583
2.23k
}
1584
1585
static int
1586
dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1587
2.23k
{
1588
2.23k
    if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1589
0
        PyErr_Format(PyExc_ValueError,
1590
0
                     "%s: can't specify both dir_fd and fd",
1591
0
                     function_name);
1592
0
        return 1;
1593
0
    }
1594
2.23k
    return 0;
1595
2.23k
}
1596
1597
static int
1598
fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1599
                               int follow_symlinks)
1600
2.23k
{
1601
2.23k
    if ((fd > 0) && (!follow_symlinks)) {
1602
0
        PyErr_Format(PyExc_ValueError,
1603
0
                     "%s: cannot use fd and follow_symlinks together",
1604
0
                     function_name);
1605
0
        return 1;
1606
0
    }
1607
2.23k
    return 0;
1608
2.23k
}
1609
1610
static int
1611
dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1612
                                   int follow_symlinks)
1613
22
{
1614
22
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1615
0
        PyErr_Format(PyExc_ValueError,
1616
0
                     "%s: cannot use dir_fd and follow_symlinks together",
1617
0
                     function_name);
1618
0
        return 1;
1619
0
    }
1620
22
    return 0;
1621
22
}
1622
1623
#if defined(HAVE_WAITID)
1624
static int
1625
idtype_t_converter(PyObject *arg, void *addr)
1626
0
{
1627
0
    int value = PyLong_AsInt(arg);
1628
0
    if (value == -1 && PyErr_Occurred()) {
1629
0
        return 0;
1630
0
    }
1631
0
    *((idtype_t *)addr) = (idtype_t)(value);
1632
0
    return 1;
1633
0
}
1634
#endif
1635
1636
#ifdef MS_WINDOWS
1637
    typedef long long Py_off_t;
1638
#else
1639
    typedef off_t Py_off_t;
1640
#endif
1641
1642
static int
1643
Py_off_t_converter(PyObject *arg, void *addr)
1644
0
{
1645
#ifdef HAVE_LARGEFILE_SUPPORT
1646
    *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1647
#else
1648
0
    *((Py_off_t *)addr) = PyLong_AsLong(arg);
1649
0
#endif
1650
0
    if (PyErr_Occurred())
1651
0
        return 0;
1652
0
    return 1;
1653
0
}
1654
1655
static PyObject *
1656
PyLong_FromPy_off_t(Py_off_t offset)
1657
0
{
1658
#ifdef HAVE_LARGEFILE_SUPPORT
1659
    return PyLong_FromLongLong(offset);
1660
#else
1661
0
    return PyLong_FromLong(offset);
1662
0
#endif
1663
0
}
1664
1665
#ifdef HAVE_SIGSET_T
1666
/* Convert an iterable of integers to a sigset.
1667
   Return 1 on success, return 0 and raise an exception on error. */
1668
int
1669
_Py_Sigset_Converter(PyObject *obj, void *addr)
1670
0
{
1671
0
    sigset_t *mask = (sigset_t *)addr;
1672
0
    PyObject *iterator, *item;
1673
0
    long signum;
1674
0
    int overflow;
1675
1676
    // The extra parens suppress the unreachable-code warning with clang on MacOS
1677
0
    if (sigemptyset(mask) < (0)) {
1678
        /* Probably only if mask == NULL. */
1679
0
        PyErr_SetFromErrno(PyExc_OSError);
1680
0
        return 0;
1681
0
    }
1682
1683
0
    iterator = PyObject_GetIter(obj);
1684
0
    if (iterator == NULL) {
1685
0
        return 0;
1686
0
    }
1687
1688
0
    while ((item = PyIter_Next(iterator)) != NULL) {
1689
0
        signum = PyLong_AsLongAndOverflow(item, &overflow);
1690
0
        Py_DECREF(item);
1691
0
        if (signum <= 0 || signum >= Py_NSIG) {
1692
0
            if (overflow || signum != -1 || !PyErr_Occurred()) {
1693
0
                PyErr_Format(PyExc_ValueError,
1694
0
                             "signal number %ld out of range [1; %i]",
1695
0
                             signum, Py_NSIG - 1);
1696
0
            }
1697
0
            goto error;
1698
0
        }
1699
0
        if (sigaddset(mask, (int)signum)) {
1700
0
            if (errno != EINVAL) {
1701
                /* Probably impossible */
1702
0
                PyErr_SetFromErrno(PyExc_OSError);
1703
0
                goto error;
1704
0
            }
1705
            /* For backwards compatibility, allow idioms such as
1706
             * `range(1, NSIG)` but warn about invalid signal numbers
1707
             */
1708
0
            const char msg[] =
1709
0
                "invalid signal number %ld, please use valid_signals()";
1710
0
            if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1711
0
                goto error;
1712
0
            }
1713
0
        }
1714
0
    }
1715
0
    if (!PyErr_Occurred()) {
1716
0
        Py_DECREF(iterator);
1717
0
        return 1;
1718
0
    }
1719
1720
0
error:
1721
0
    Py_DECREF(iterator);
1722
0
    return 0;
1723
0
}
1724
#endif /* HAVE_SIGSET_T */
1725
1726
/* Return a dictionary corresponding to the POSIX environment table */
1727
#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1728
/* On Darwin/MacOSX a shared library or framework has no access to
1729
** environ directly, we must obtain it with _NSGetEnviron(). See also
1730
** man environ(7).
1731
*/
1732
#include <crt_externs.h>
1733
#define USE_DARWIN_NS_GET_ENVIRON 1
1734
#elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1735
extern char **environ;
1736
#endif /* !_MSC_VER */
1737
1738
static PyObject *
1739
convertenviron(void)
1740
22
{
1741
22
    PyObject *d;
1742
#ifdef MS_WINDOWS
1743
    wchar_t **e;
1744
#else
1745
22
    char **e;
1746
22
#endif
1747
1748
22
    d = PyDict_New();
1749
22
    if (d == NULL)
1750
0
        return NULL;
1751
#ifdef MS_WINDOWS
1752
    /* _wenviron must be initialized in this way if the program is started
1753
       through main() instead of wmain(). */
1754
    (void)_wgetenv(L"");
1755
    e = _wenviron;
1756
#elif defined(USE_DARWIN_NS_GET_ENVIRON)
1757
    /* environ is not accessible as an extern in a shared object on OSX; use
1758
       _NSGetEnviron to resolve it. The value changes if you add environment
1759
       variables between calls to Py_Initialize, so don't cache the value. */
1760
    e = *_NSGetEnviron();
1761
#else
1762
22
    e = environ;
1763
22
#endif
1764
22
    if (e == NULL)
1765
0
        return d;
1766
814
    for (; *e != NULL; e++) {
1767
792
        PyObject *k;
1768
792
        PyObject *v;
1769
#ifdef MS_WINDOWS
1770
        const wchar_t *p = wcschr(*e, L'=');
1771
#else
1772
792
        const char *p = strchr(*e, '=');
1773
792
#endif
1774
792
        if (p == NULL)
1775
0
            continue;
1776
#ifdef MS_WINDOWS
1777
        k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1778
#else
1779
792
        k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1780
792
#endif
1781
792
        if (k == NULL) {
1782
0
            Py_DECREF(d);
1783
0
            return NULL;
1784
0
        }
1785
#ifdef MS_WINDOWS
1786
        v = PyUnicode_FromWideChar(p+1, -1);
1787
#else
1788
792
        v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1789
792
#endif
1790
792
        if (v == NULL) {
1791
0
            Py_DECREF(k);
1792
0
            Py_DECREF(d);
1793
0
            return NULL;
1794
0
        }
1795
792
        if (PyDict_SetDefaultRef(d, k, v, NULL) < 0) {
1796
0
            Py_DECREF(v);
1797
0
            Py_DECREF(k);
1798
0
            Py_DECREF(d);
1799
0
            return NULL;
1800
0
        }
1801
792
        Py_DECREF(k);
1802
792
        Py_DECREF(v);
1803
792
    }
1804
22
    return d;
1805
22
}
1806
1807
/* Set a POSIX-specific error from errno, and return NULL */
1808
1809
static PyObject *
1810
posix_error(void)
1811
0
{
1812
0
    return PyErr_SetFromErrno(PyExc_OSError);
1813
0
}
1814
1815
#ifdef MS_WINDOWS
1816
static PyObject *
1817
win32_error(const char* function, const char* filename)
1818
{
1819
    /* XXX We should pass the function name along in the future.
1820
       (winreg.c also wants to pass the function name.)
1821
       This would however require an additional param to the
1822
       Windows error object, which is non-trivial.
1823
    */
1824
    errno = GetLastError();
1825
    if (filename)
1826
        return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1827
    else
1828
        return PyErr_SetFromWindowsErr(errno);
1829
}
1830
1831
static PyObject *
1832
win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1833
{
1834
    /* XXX - see win32_error for comments on 'function' */
1835
    if (filename)
1836
        return PyErr_SetExcFromWindowsErrWithFilenameObject(
1837
                    PyExc_OSError,
1838
                    err,
1839
                    filename);
1840
    else
1841
        return PyErr_SetFromWindowsErr(err);
1842
}
1843
1844
static PyObject *
1845
win32_error_object(const char* function, PyObject* filename)
1846
{
1847
    errno = GetLastError();
1848
    return win32_error_object_err(function, filename, errno);
1849
}
1850
1851
#endif /* MS_WINDOWS */
1852
1853
static PyObject *
1854
posix_path_object_error(PyObject *path)
1855
227
{
1856
227
    return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1857
227
}
1858
1859
static PyObject *
1860
path_object_error(PyObject *path)
1861
227
{
1862
#ifdef MS_WINDOWS
1863
    return PyErr_SetExcFromWindowsErrWithFilenameObject(
1864
                PyExc_OSError, 0, path);
1865
#else
1866
227
    return posix_path_object_error(path);
1867
227
#endif
1868
227
}
1869
1870
static PyObject *
1871
path_object_error2(PyObject *path, PyObject *path2)
1872
0
{
1873
#ifdef MS_WINDOWS
1874
    return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1875
                PyExc_OSError, 0, path, path2);
1876
#else
1877
0
    return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1878
0
#endif
1879
0
}
1880
1881
static PyObject *
1882
path_error(path_t *path)
1883
227
{
1884
227
    return path_object_error(path->object);
1885
227
}
1886
1887
static PyObject *
1888
posix_path_error(path_t *path)
1889
0
{
1890
0
    return posix_path_object_error(path->object);
1891
0
}
1892
1893
static PyObject *
1894
path_error2(path_t *path, path_t *path2)
1895
0
{
1896
0
    return path_object_error2(path->object, path2->object);
1897
0
}
1898
1899
1900
/* POSIX generic methods */
1901
1902
static PyObject *
1903
posix_fildes_fd(int fd, int (*func)(int))
1904
0
{
1905
0
    int res;
1906
0
    int async_err = 0;
1907
1908
0
    do {
1909
0
        Py_BEGIN_ALLOW_THREADS
1910
0
        _Py_BEGIN_SUPPRESS_IPH
1911
0
        res = (*func)(fd);
1912
0
        _Py_END_SUPPRESS_IPH
1913
0
        Py_END_ALLOW_THREADS
1914
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1915
0
    if (res != 0)
1916
0
        return (!async_err) ? posix_error() : NULL;
1917
0
    Py_RETURN_NONE;
1918
0
}
1919
1920
1921
#ifdef MS_WINDOWS
1922
/* This is a reimplementation of the C library's chdir function,
1923
   but one that produces Win32 errors instead of DOS error codes.
1924
   chdir is essentially a wrapper around SetCurrentDirectory; however,
1925
   it also needs to set "magic" environment variables indicating
1926
   the per-drive current directory, which are of the form =<drive>: */
1927
static BOOL __stdcall
1928
win32_wchdir(LPCWSTR path)
1929
{
1930
    wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1931
    int result;
1932
    wchar_t env[4] = L"=x:";
1933
1934
    if(!SetCurrentDirectoryW(path))
1935
        return FALSE;
1936
    result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1937
    if (!result)
1938
        return FALSE;
1939
    if (result > Py_ARRAY_LENGTH(path_buf)) {
1940
        new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1941
        if (!new_path) {
1942
            SetLastError(ERROR_OUTOFMEMORY);
1943
            return FALSE;
1944
        }
1945
        result = GetCurrentDirectoryW(result, new_path);
1946
        if (!result) {
1947
            PyMem_RawFree(new_path);
1948
            return FALSE;
1949
        }
1950
    }
1951
    int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1952
                            wcsncmp(new_path, L"//", 2) == 0);
1953
    if (!is_unc_like_path) {
1954
        env[1] = new_path[0];
1955
        result = SetEnvironmentVariableW(env, new_path);
1956
    }
1957
    if (new_path != path_buf)
1958
        PyMem_RawFree(new_path);
1959
    return result ? TRUE : FALSE;
1960
}
1961
#endif
1962
1963
#ifdef MS_WINDOWS
1964
/* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1965
   - time stamps are restricted to second resolution
1966
   - file modification times suffer from forth-and-back conversions between
1967
     UTC and local time
1968
   Therefore, we implement our own stat, based on the Win32 API directly.
1969
*/
1970
#define HAVE_STAT_NSEC 1
1971
#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
1972
#define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
1973
1974
static void
1975
find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
1976
                       BY_HANDLE_FILE_INFORMATION *info,
1977
                       ULONG *reparse_tag)
1978
{
1979
    memset(info, 0, sizeof(*info));
1980
    info->dwFileAttributes = pFileData->dwFileAttributes;
1981
    info->ftCreationTime   = pFileData->ftCreationTime;
1982
    info->ftLastAccessTime = pFileData->ftLastAccessTime;
1983
    info->ftLastWriteTime  = pFileData->ftLastWriteTime;
1984
    info->nFileSizeHigh    = pFileData->nFileSizeHigh;
1985
    info->nFileSizeLow     = pFileData->nFileSizeLow;
1986
/*  info->nNumberOfLinks   = 1; */
1987
    if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1988
        *reparse_tag = pFileData->dwReserved0;
1989
    else
1990
        *reparse_tag = 0;
1991
}
1992
1993
static BOOL
1994
attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1995
{
1996
    HANDLE hFindFile;
1997
    WIN32_FIND_DATAW FileData;
1998
    LPCWSTR filename = pszFile;
1999
    size_t n = wcslen(pszFile);
2000
    if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
2001
        // cannot use PyMem_Malloc here because we do not hold the GIL
2002
        filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
2003
        if(!filename) {
2004
            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2005
            return FALSE;
2006
        }
2007
        wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
2008
        while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
2009
            ((LPWSTR)filename)[n] = L'\0';
2010
        }
2011
        if (!n || (n == 1 && filename[1] == L':')) {
2012
            // Nothing left to query
2013
            free((void *)filename);
2014
            return FALSE;
2015
        }
2016
    }
2017
    hFindFile = FindFirstFileW(filename, &FileData);
2018
    if (pszFile != filename) {
2019
        free((void *)filename);
2020
    }
2021
    if (hFindFile == INVALID_HANDLE_VALUE) {
2022
        return FALSE;
2023
    }
2024
    FindClose(hFindFile);
2025
    find_data_to_file_info(&FileData, info, reparse_tag);
2026
    return TRUE;
2027
}
2028
2029
2030
static void
2031
update_st_mode_from_path(const wchar_t *path, DWORD attr,
2032
                         struct _Py_stat_struct *result)
2033
{
2034
    if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
2035
        /* Fix the file execute permissions. This hack sets S_IEXEC if
2036
           the filename has an extension that is commonly used by files
2037
           that CreateProcessW can execute. A real implementation calls
2038
           GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
2039
           AccessCheck to check for generic read, write, and execute
2040
           access. */
2041
        const wchar_t *fileExtension = wcsrchr(path, '.');
2042
        if (fileExtension) {
2043
            if (_wcsicmp(fileExtension, L".exe") == 0 ||
2044
                _wcsicmp(fileExtension, L".bat") == 0 ||
2045
                _wcsicmp(fileExtension, L".cmd") == 0 ||
2046
                _wcsicmp(fileExtension, L".com") == 0) {
2047
                result->st_mode |= 0111;
2048
            }
2049
        }
2050
    }
2051
}
2052
2053
2054
static int
2055
win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result,
2056
                      BOOL traverse)
2057
{
2058
    HANDLE hFile;
2059
    BY_HANDLE_FILE_INFORMATION fileInfo;
2060
    FILE_BASIC_INFO basicInfo;
2061
    FILE_BASIC_INFO *pBasicInfo = NULL;
2062
    FILE_ID_INFO idInfo;
2063
    FILE_ID_INFO *pIdInfo = NULL;
2064
    FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
2065
    DWORD fileType, error;
2066
    BOOL isUnhandledTag = FALSE;
2067
    int retval = 0;
2068
2069
    DWORD access = FILE_READ_ATTRIBUTES;
2070
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
2071
    if (!traverse) {
2072
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
2073
    }
2074
2075
    hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
2076
    if (hFile == INVALID_HANDLE_VALUE) {
2077
        /* Either the path doesn't exist, or the caller lacks access. */
2078
        error = GetLastError();
2079
        switch (error) {
2080
        case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
2081
        case ERROR_SHARING_VIOLATION: /* It's a paging file. */
2082
            /* Try reading the parent directory. */
2083
            if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
2084
                /* Cannot read the parent directory. */
2085
                switch (GetLastError()) {
2086
                case ERROR_FILE_NOT_FOUND: /* File cannot be found */
2087
                case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */
2088
                case ERROR_NOT_READY: /* Drive exists but unavailable */
2089
                case ERROR_BAD_NET_NAME: /* Remote drive unavailable */
2090
                    break;
2091
                /* Restore the error from CreateFileW(). */
2092
                default:
2093
                    SetLastError(error);
2094
                }
2095
2096
                return -1;
2097
            }
2098
            if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
2099
                if (traverse ||
2100
                    !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2101
                    /* The stat call has to traverse but cannot, so fail. */
2102
                    SetLastError(error);
2103
                    return -1;
2104
                }
2105
            }
2106
            break;
2107
2108
        case ERROR_INVALID_PARAMETER:
2109
            /* \\.\con requires read or write access. */
2110
            hFile = CreateFileW(path, access | GENERIC_READ,
2111
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
2112
                        OPEN_EXISTING, flags, NULL);
2113
            if (hFile == INVALID_HANDLE_VALUE) {
2114
                SetLastError(error);
2115
                return -1;
2116
            }
2117
            break;
2118
2119
        case ERROR_CANT_ACCESS_FILE:
2120
            /* bpo37834: open unhandled reparse points if traverse fails. */
2121
            if (traverse) {
2122
                traverse = FALSE;
2123
                isUnhandledTag = TRUE;
2124
                hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
2125
                            flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
2126
            }
2127
            if (hFile == INVALID_HANDLE_VALUE) {
2128
                SetLastError(error);
2129
                return -1;
2130
            }
2131
            break;
2132
2133
        default:
2134
            return -1;
2135
        }
2136
    }
2137
2138
    if (hFile != INVALID_HANDLE_VALUE) {
2139
        /* Handle types other than files on disk. */
2140
        fileType = GetFileType(hFile);
2141
        if (fileType != FILE_TYPE_DISK) {
2142
            if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
2143
                retval = -1;
2144
                goto cleanup;
2145
            }
2146
            DWORD fileAttributes = GetFileAttributesW(path);
2147
            memset(result, 0, sizeof(*result));
2148
            if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
2149
                fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
2150
                /* \\.\pipe\ or \\.\mailslot\ */
2151
                result->st_mode = _S_IFDIR;
2152
            } else if (fileType == FILE_TYPE_CHAR) {
2153
                /* \\.\nul */
2154
                result->st_mode = _S_IFCHR;
2155
            } else if (fileType == FILE_TYPE_PIPE) {
2156
                /* \\.\pipe\spam */
2157
                result->st_mode = _S_IFIFO;
2158
            }
2159
            /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
2160
            goto cleanup;
2161
        }
2162
2163
        /* Query the reparse tag, and traverse a non-link. */
2164
        if (!traverse) {
2165
            if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
2166
                    &tagInfo, sizeof(tagInfo))) {
2167
                /* Allow devices that do not support FileAttributeTagInfo. */
2168
                switch (GetLastError()) {
2169
                case ERROR_INVALID_PARAMETER:
2170
                case ERROR_INVALID_FUNCTION:
2171
                case ERROR_NOT_SUPPORTED:
2172
                    tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
2173
                    tagInfo.ReparseTag = 0;
2174
                    break;
2175
                default:
2176
                    retval = -1;
2177
                    goto cleanup;
2178
                }
2179
            } else if (tagInfo.FileAttributes &
2180
                         FILE_ATTRIBUTE_REPARSE_POINT) {
2181
                if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2182
                    if (isUnhandledTag) {
2183
                        /* Traversing previously failed for either this link
2184
                           or its target. */
2185
                        SetLastError(ERROR_CANT_ACCESS_FILE);
2186
                        retval = -1;
2187
                        goto cleanup;
2188
                    }
2189
                /* Traverse a non-link, but not if traversing already failed
2190
                   for an unhandled tag. */
2191
                } else if (!isUnhandledTag) {
2192
                    CloseHandle(hFile);
2193
                    return win32_xstat_slow_impl(path, result, TRUE);
2194
                }
2195
            }
2196
        }
2197
2198
        if (!GetFileInformationByHandle(hFile, &fileInfo) ||
2199
            !GetFileInformationByHandleEx(hFile, FileBasicInfo,
2200
                                          &basicInfo, sizeof(basicInfo))) {
2201
            switch (GetLastError()) {
2202
            case ERROR_INVALID_PARAMETER:
2203
            case ERROR_INVALID_FUNCTION:
2204
            case ERROR_NOT_SUPPORTED:
2205
                /* Volumes and physical disks are block devices, e.g.
2206
                   \\.\C: and \\.\PhysicalDrive0. */
2207
                memset(result, 0, sizeof(*result));
2208
                result->st_mode = 0x6000; /* S_IFBLK */
2209
                goto cleanup;
2210
            }
2211
            retval = -1;
2212
            goto cleanup;
2213
        }
2214
2215
        /* Successfully got FileBasicInfo, so we'll pass it along */
2216
        pBasicInfo = &basicInfo;
2217
2218
        if (GetFileInformationByHandleEx(hFile, FileIdInfo, &idInfo, sizeof(idInfo))) {
2219
            /* Successfully got FileIdInfo, so pass it along */
2220
            pIdInfo = &idInfo;
2221
        }
2222
    }
2223
2224
    _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, pBasicInfo, pIdInfo, result);
2225
    update_st_mode_from_path(path, fileInfo.dwFileAttributes, result);
2226
2227
cleanup:
2228
    if (hFile != INVALID_HANDLE_VALUE) {
2229
        /* Preserve last error if we are failing */
2230
        error = retval ? GetLastError() : 0;
2231
        if (!CloseHandle(hFile)) {
2232
            retval = -1;
2233
        } else if (retval) {
2234
            /* Restore last error */
2235
            SetLastError(error);
2236
        }
2237
    }
2238
2239
    return retval;
2240
}
2241
2242
static int
2243
win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
2244
                 BOOL traverse)
2245
{
2246
    FILE_STAT_BASIC_INFORMATION statInfo;
2247
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo,
2248
                                     &statInfo, sizeof(statInfo))) {
2249
        if (// Cannot use fast path for reparse points ...
2250
            !(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2251
            // ... unless it's a name surrogate (symlink) and we're not following
2252
            || (!traverse && IsReparseTagNameSurrogate(statInfo.ReparseTag))
2253
        ) {
2254
            _Py_stat_basic_info_to_stat(&statInfo, result);
2255
            update_st_mode_from_path(path, statInfo.FileAttributes, result);
2256
            return 0;
2257
        }
2258
    } else {
2259
        switch(GetLastError()) {
2260
        case ERROR_FILE_NOT_FOUND:
2261
        case ERROR_PATH_NOT_FOUND:
2262
        case ERROR_NOT_READY:
2263
        case ERROR_BAD_NET_NAME:
2264
            /* These errors aren't worth retrying with the slow path */
2265
            return -1;
2266
        case ERROR_NOT_SUPPORTED:
2267
            /* indicates the API couldn't be loaded */
2268
            break;
2269
        }
2270
    }
2271
2272
    return win32_xstat_slow_impl(path, result, traverse);
2273
}
2274
2275
static int
2276
win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2277
{
2278
    /* Protocol violation: we explicitly clear errno, instead of
2279
       setting it to a POSIX error. Callers should use GetLastError. */
2280
    int code = win32_xstat_impl(path, result, traverse);
2281
    errno = 0;
2282
2283
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
2284
    result->st_ctime = result->st_birthtime;
2285
    result->st_ctime_nsec = result->st_birthtime_nsec;
2286
    return code;
2287
}
2288
/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2289
2290
   In Posix, stat automatically traverses symlinks and returns the stat
2291
   structure for the target.  In Windows, the equivalent GetFileAttributes by
2292
   default does not traverse symlinks and instead returns attributes for
2293
   the symlink.
2294
2295
   Instead, we will open the file (which *does* traverse symlinks by default)
2296
   and GetFileInformationByHandle(). */
2297
2298
static int
2299
win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2300
{
2301
    return win32_xstat(path, result, FALSE);
2302
}
2303
2304
static int
2305
win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2306
{
2307
    return win32_xstat(path, result, TRUE);
2308
}
2309
2310
#endif /* MS_WINDOWS */
2311
2312
PyDoc_STRVAR(stat_result__doc__,
2313
"stat_result: Result from stat, fstat, or lstat.\n\n\
2314
This object may be accessed either as a tuple of\n\
2315
  (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2316
or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2317
\n\
2318
Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2319
or st_flags, they are available as attributes only.\n\
2320
\n\
2321
See os.stat for more information.");
2322
2323
static PyStructSequence_Field stat_result_fields[] = {
2324
    {"st_mode",    "protection bits"},
2325
    {"st_ino",     "inode"},
2326
    {"st_dev",     "device"},
2327
    {"st_nlink",   "number of hard links"},
2328
    {"st_uid",     "user ID of owner"},
2329
    {"st_gid",     "group ID of owner"},
2330
    {"st_size",    "total size, in bytes"},
2331
    /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2332
    {NULL,   "integer time of last access"},
2333
    {NULL,   "integer time of last modification"},
2334
    {NULL,   "integer time of last change"},
2335
    {"st_atime",   "time of last access"},
2336
    {"st_mtime",   "time of last modification"},
2337
    {"st_ctime",   "time of last change"},
2338
    {"st_atime_ns",   "time of last access in nanoseconds"},
2339
    {"st_mtime_ns",   "time of last modification in nanoseconds"},
2340
    {"st_ctime_ns",   "time of last change in nanoseconds"},
2341
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2342
    {"st_blksize", "blocksize for filesystem I/O"},
2343
#endif
2344
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2345
    {"st_blocks",  "number of blocks allocated"},
2346
#endif
2347
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2348
    {"st_rdev",    "device type (if inode device)"},
2349
#endif
2350
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2351
    {"st_flags",   "user defined flags for file"},
2352
#endif
2353
#ifdef HAVE_STRUCT_STAT_ST_GEN
2354
    {"st_gen",    "generation number"},
2355
#endif
2356
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2357
    {"st_birthtime",   "time of creation"},
2358
#endif
2359
#ifdef MS_WINDOWS
2360
    {"st_birthtime_ns", "time of creation in nanoseconds"},
2361
#endif
2362
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2363
    {"st_file_attributes", "Windows file attribute bits"},
2364
#endif
2365
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2366
    {"st_fstype",  "Type of filesystem"},
2367
#endif
2368
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2369
    {"st_reparse_tag", "Windows reparse tag"},
2370
#endif
2371
    {0}
2372
};
2373
2374
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2375
#define ST_BLKSIZE_IDX 16
2376
#else
2377
#define ST_BLKSIZE_IDX 15
2378
#endif
2379
2380
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2381
#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2382
#else
2383
#define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2384
#endif
2385
2386
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2387
#define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2388
#else
2389
#define ST_RDEV_IDX ST_BLOCKS_IDX
2390
#endif
2391
2392
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2393
#define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2394
#else
2395
#define ST_FLAGS_IDX ST_RDEV_IDX
2396
#endif
2397
2398
#ifdef HAVE_STRUCT_STAT_ST_GEN
2399
#define ST_GEN_IDX (ST_FLAGS_IDX+1)
2400
#else
2401
#define ST_GEN_IDX ST_FLAGS_IDX
2402
#endif
2403
2404
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2405
#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2406
#else
2407
#define ST_BIRTHTIME_IDX ST_GEN_IDX
2408
#endif
2409
2410
#ifdef MS_WINDOWS
2411
#define ST_BIRTHTIME_NS_IDX (ST_BIRTHTIME_IDX+1)
2412
#else
2413
#define ST_BIRTHTIME_NS_IDX ST_BIRTHTIME_IDX
2414
#endif
2415
2416
#if defined(HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES) || defined(MS_WINDOWS)
2417
#define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_NS_IDX+1)
2418
#else
2419
#define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_NS_IDX
2420
#endif
2421
2422
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2423
#define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2424
#else
2425
#define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2426
#endif
2427
2428
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2429
#define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2430
#else
2431
#define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2432
#endif
2433
2434
static PyStructSequence_Desc stat_result_desc = {
2435
    "stat_result", /* name */
2436
    stat_result__doc__, /* doc */
2437
    stat_result_fields,
2438
    10
2439
};
2440
2441
PyDoc_STRVAR(statvfs_result__doc__,
2442
"statvfs_result: Result from statvfs or fstatvfs.\n\n\
2443
This object may be accessed either as a tuple of\n\
2444
  (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2445
or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2446
\n\
2447
See os.statvfs for more information.");
2448
2449
static PyStructSequence_Field statvfs_result_fields[] = {
2450
    {"f_bsize",  },
2451
    {"f_frsize", },
2452
    {"f_blocks", },
2453
    {"f_bfree",  },
2454
    {"f_bavail", },
2455
    {"f_files",  },
2456
    {"f_ffree",  },
2457
    {"f_favail", },
2458
    {"f_flag",   },
2459
    {"f_namemax",},
2460
    {"f_fsid",   },
2461
    {0}
2462
};
2463
2464
static PyStructSequence_Desc statvfs_result_desc = {
2465
    "statvfs_result", /* name */
2466
    statvfs_result__doc__, /* doc */
2467
    statvfs_result_fields,
2468
    10
2469
};
2470
2471
#if defined(HAVE_WAITID)
2472
PyDoc_STRVAR(waitid_result__doc__,
2473
"waitid_result: Result from waitid.\n\n\
2474
This object may be accessed either as a tuple of\n\
2475
  (si_pid, si_uid, si_signo, si_status, si_code),\n\
2476
or via the attributes si_pid, si_uid, and so on.\n\
2477
\n\
2478
See os.waitid for more information.");
2479
2480
static PyStructSequence_Field waitid_result_fields[] = {
2481
    {"si_pid",  },
2482
    {"si_uid", },
2483
    {"si_signo", },
2484
    {"si_status",  },
2485
    {"si_code", },
2486
    {0}
2487
};
2488
2489
static PyStructSequence_Desc waitid_result_desc = {
2490
    "waitid_result", /* name */
2491
    waitid_result__doc__, /* doc */
2492
    waitid_result_fields,
2493
    5
2494
};
2495
#endif
2496
2497
static PyObject *
2498
statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2499
0
{
2500
0
    PyStructSequence *result;
2501
0
    int i;
2502
2503
    // ht_module doesn't get set in PyStructSequence_NewType(),
2504
    // so we can't use PyType_GetModule().
2505
0
    PyObject *mod = PyImport_GetModule(MODNAME_OBJ);
2506
0
    if (mod == NULL) {
2507
0
        return NULL;
2508
0
    }
2509
0
    _posixstate *state = get_posix_state(mod);
2510
0
    Py_DECREF(mod);
2511
0
    if (state == NULL) {
2512
0
        return NULL;
2513
0
    }
2514
0
#define structseq_new state->statresult_new_orig
2515
2516
0
    result = (PyStructSequence*)structseq_new(type, args, kwds);
2517
0
    if (!result)
2518
0
        return NULL;
2519
    /* If we have been initialized from a tuple,
2520
       st_?time might be set to None. Initialize it
2521
       from the int slots.  */
2522
0
    for (i = 7; i <= 9; i++) {
2523
0
        if (result->ob_item[i+3] == Py_None) {
2524
0
            Py_DECREF(Py_None);
2525
0
            result->ob_item[i+3] = Py_NewRef(result->ob_item[i]);
2526
0
        }
2527
0
    }
2528
0
    return (PyObject*)result;
2529
0
}
2530
2531
static int
2532
_posix_clear(PyObject *module)
2533
0
{
2534
0
    _posixstate *state = get_posix_state(module);
2535
0
    Py_CLEAR(state->billion);
2536
0
    Py_CLEAR(state->DirEntryType);
2537
0
    Py_CLEAR(state->ScandirIteratorType);
2538
0
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2539
0
    Py_CLEAR(state->SchedParamType);
2540
0
#endif
2541
0
    Py_CLEAR(state->StatResultType);
2542
0
    Py_CLEAR(state->StatVFSResultType);
2543
0
    Py_CLEAR(state->TerminalSizeType);
2544
0
    Py_CLEAR(state->TimesResultType);
2545
0
    Py_CLEAR(state->UnameResultType);
2546
0
#if defined(HAVE_WAITID)
2547
0
    Py_CLEAR(state->WaitidResultType);
2548
0
#endif
2549
0
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2550
0
    Py_CLEAR(state->struct_rusage);
2551
0
#endif
2552
0
    Py_CLEAR(state->st_mode);
2553
0
    return 0;
2554
0
}
2555
2556
static int
2557
_posix_traverse(PyObject *module, visitproc visit, void *arg)
2558
6.67k
{
2559
6.67k
    _posixstate *state = get_posix_state(module);
2560
6.67k
    Py_VISIT(state->billion);
2561
6.67k
    Py_VISIT(state->DirEntryType);
2562
6.67k
    Py_VISIT(state->ScandirIteratorType);
2563
6.67k
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2564
6.67k
    Py_VISIT(state->SchedParamType);
2565
6.67k
#endif
2566
6.67k
    Py_VISIT(state->StatResultType);
2567
6.67k
    Py_VISIT(state->StatVFSResultType);
2568
6.67k
    Py_VISIT(state->TerminalSizeType);
2569
6.67k
    Py_VISIT(state->TimesResultType);
2570
6.67k
    Py_VISIT(state->UnameResultType);
2571
6.67k
#if defined(HAVE_WAITID)
2572
6.67k
    Py_VISIT(state->WaitidResultType);
2573
6.67k
#endif
2574
6.67k
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2575
6.67k
    Py_VISIT(state->struct_rusage);
2576
6.67k
#endif
2577
6.67k
    Py_VISIT(state->st_mode);
2578
6.67k
    return 0;
2579
6.67k
}
2580
2581
static void
2582
_posix_free(void *module)
2583
0
{
2584
0
   _posix_clear((PyObject *)module);
2585
0
}
2586
2587
static int
2588
fill_time(PyObject *module, PyObject *v, int s_index, int f_index, int ns_index, time_t sec, unsigned long nsec)
2589
6.01k
{
2590
6.01k
    assert(!PyErr_Occurred());
2591
2592
6.01k
    int res = -1;
2593
6.01k
    PyObject *s_in_ns = NULL;
2594
6.01k
    PyObject *ns_total = NULL;
2595
6.01k
    PyObject *float_s = NULL;
2596
2597
6.01k
    PyObject *s = _PyLong_FromTime_t(sec);
2598
6.01k
    PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2599
6.01k
    if (!(s && ns_fractional)) {
2600
0
        goto exit;
2601
0
    }
2602
2603
6.01k
    s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
2604
6.01k
    if (!s_in_ns) {
2605
0
        goto exit;
2606
0
    }
2607
2608
6.01k
    ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2609
6.01k
    if (!ns_total)
2610
0
        goto exit;
2611
2612
6.01k
    float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2613
6.01k
    if (!float_s) {
2614
0
        goto exit;
2615
0
    }
2616
2617
6.01k
    if (s_index >= 0) {
2618
6.01k
        PyStructSequence_SET_ITEM(v, s_index, s);
2619
6.01k
        s = NULL;
2620
6.01k
    }
2621
6.01k
    if (f_index >= 0) {
2622
6.01k
        PyStructSequence_SET_ITEM(v, f_index, float_s);
2623
6.01k
        float_s = NULL;
2624
6.01k
    }
2625
6.01k
    if (ns_index >= 0) {
2626
6.01k
        PyStructSequence_SET_ITEM(v, ns_index, ns_total);
2627
6.01k
        ns_total = NULL;
2628
6.01k
    }
2629
2630
6.01k
    assert(!PyErr_Occurred());
2631
6.01k
    res = 0;
2632
2633
6.01k
exit:
2634
6.01k
    Py_XDECREF(s);
2635
6.01k
    Py_XDECREF(ns_fractional);
2636
6.01k
    Py_XDECREF(s_in_ns);
2637
6.01k
    Py_XDECREF(ns_total);
2638
6.01k
    Py_XDECREF(float_s);
2639
6.01k
    return res;
2640
6.01k
}
2641
2642
#ifdef MS_WINDOWS
2643
static PyObject*
2644
_pystat_l128_from_l64_l64(uint64_t low, uint64_t high)
2645
{
2646
    PyObject *o_low = PyLong_FromUnsignedLongLong(low);
2647
    if (!o_low || !high) {
2648
        return o_low;
2649
    }
2650
    PyObject *o_high = PyLong_FromUnsignedLongLong(high);
2651
    PyObject *l64 = o_high ? PyLong_FromLong(64) : NULL;
2652
    if (!l64) {
2653
        Py_XDECREF(o_high);
2654
        Py_DECREF(o_low);
2655
        return NULL;
2656
    }
2657
    Py_SETREF(o_high, PyNumber_Lshift(o_high, l64));
2658
    Py_DECREF(l64);
2659
    if (!o_high) {
2660
        Py_DECREF(o_low);
2661
        return NULL;
2662
    }
2663
    Py_SETREF(o_low, PyNumber_Add(o_low, o_high));
2664
    Py_DECREF(o_high);
2665
    return o_low;
2666
}
2667
#endif
2668
2669
/* pack a system stat C structure into the Python stat tuple
2670
   (used by posix_stat() and posix_fstat()) */
2671
static PyObject*
2672
_pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2673
2.00k
{
2674
2.00k
    assert(!PyErr_Occurred());
2675
2676
2.00k
    PyObject *StatResultType = get_posix_state(module)->StatResultType;
2677
2.00k
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2678
2.00k
    if (v == NULL) {
2679
0
        return NULL;
2680
0
    }
2681
2682
2.00k
#define SET_ITEM(pos, expr) \
2683
20.0k
    do { \
2684
20.0k
        PyObject *obj = (expr); \
2685
20.0k
        if (obj == NULL) { \
2686
0
            goto error; \
2687
0
        } \
2688
20.0k
        PyStructSequence_SET_ITEM(v, (pos), obj); \
2689
20.0k
    } while (0)
2690
2691
2.00k
    SET_ITEM(0, PyLong_FromLong((long)st->st_mode));
2692
#ifdef MS_WINDOWS
2693
    SET_ITEM(1, _pystat_l128_from_l64_l64(st->st_ino, st->st_ino_high));
2694
    SET_ITEM(2, PyLong_FromUnsignedLongLong(st->st_dev));
2695
#else
2696
2.00k
    static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2697
2.00k
                  "stat.st_ino is larger than unsigned long long");
2698
2.00k
    SET_ITEM(1, PyLong_FromUnsignedLongLong(st->st_ino));
2699
2.00k
    SET_ITEM(2, _PyLong_FromDev(st->st_dev));
2700
2.00k
#endif
2701
2.00k
    SET_ITEM(3, PyLong_FromLong((long)st->st_nlink));
2702
#if defined(MS_WINDOWS)
2703
    SET_ITEM(4, PyLong_FromLong(0));
2704
    SET_ITEM(5, PyLong_FromLong(0));
2705
#else
2706
2.00k
    SET_ITEM(4, _PyLong_FromUid(st->st_uid));
2707
2.00k
    SET_ITEM(5, _PyLong_FromGid(st->st_gid));
2708
2.00k
#endif
2709
2.00k
    static_assert(sizeof(long long) >= sizeof(st->st_size),
2710
2.00k
                  "stat.st_size is larger than long long");
2711
2.00k
    SET_ITEM(6, PyLong_FromLongLong(st->st_size));
2712
2713
    // Set st_atime, st_mtime and st_ctime
2714
2.00k
    unsigned long ansec, mnsec, cnsec;
2715
2.00k
#if defined(HAVE_STAT_TV_NSEC)
2716
2.00k
    ansec = st->st_atim.tv_nsec;
2717
2.00k
    mnsec = st->st_mtim.tv_nsec;
2718
2.00k
    cnsec = st->st_ctim.tv_nsec;
2719
#elif defined(HAVE_STAT_TV_NSEC2)
2720
    ansec = st->st_atimespec.tv_nsec;
2721
    mnsec = st->st_mtimespec.tv_nsec;
2722
    cnsec = st->st_ctimespec.tv_nsec;
2723
#elif defined(HAVE_STAT_NSEC)
2724
    ansec = st->st_atime_nsec;
2725
    mnsec = st->st_mtime_nsec;
2726
    cnsec = st->st_ctime_nsec;
2727
#else
2728
    ansec = mnsec = cnsec = 0;
2729
#endif
2730
2.00k
    if (fill_time(module, v, 7, 10, 13, st->st_atime, ansec) < 0) {
2731
0
        goto error;
2732
0
    }
2733
2.00k
    if (fill_time(module, v, 8, 11, 14, st->st_mtime, mnsec) < 0) {
2734
0
        goto error;
2735
0
    }
2736
2.00k
    if (fill_time(module, v, 9, 12, 15, st->st_ctime, cnsec) < 0) {
2737
0
        goto error;
2738
0
    }
2739
2740
2.00k
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2741
2.00k
    SET_ITEM(ST_BLKSIZE_IDX, PyLong_FromLong((long)st->st_blksize));
2742
2.00k
#endif
2743
2.00k
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2744
2.00k
    SET_ITEM(ST_BLOCKS_IDX, PyLong_FromLong((long)st->st_blocks));
2745
2.00k
#endif
2746
2.00k
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2747
2.00k
    SET_ITEM(ST_RDEV_IDX, PyLong_FromLong((long)st->st_rdev));
2748
2.00k
#endif
2749
#ifdef HAVE_STRUCT_STAT_ST_GEN
2750
    SET_ITEM(ST_GEN_IDX, PyLong_FromLong((long)st->st_gen));
2751
#endif
2752
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
2753
    {
2754
      unsigned long bsec, bnsec;
2755
      bsec = (long)st->st_birthtime;
2756
#ifdef HAVE_STAT_TV_NSEC2
2757
      bnsec = st->st_birthtimespec.tv_nsec;
2758
#else
2759
      bnsec = 0;
2760
#endif
2761
      SET_ITEM(ST_BIRTHTIME_IDX, PyFloat_FromDouble(bsec + bnsec * 1e-9));
2762
    }
2763
#elif defined(MS_WINDOWS)
2764
    if (fill_time(module, v, -1, ST_BIRTHTIME_IDX, ST_BIRTHTIME_NS_IDX,
2765
                  st->st_birthtime, st->st_birthtime_nsec) < 0) {
2766
        goto error;
2767
    }
2768
#endif
2769
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2770
    SET_ITEM(ST_FLAGS_IDX, PyLong_FromLong((long)st->st_flags));
2771
#endif
2772
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2773
    SET_ITEM(ST_FILE_ATTRIBUTES_IDX,
2774
             PyLong_FromUnsignedLong(st->st_file_attributes));
2775
#endif
2776
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2777
   SET_ITEM(ST_FSTYPE_IDX, PyUnicode_FromString(st->st_fstype));
2778
#endif
2779
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2780
    SET_ITEM(ST_REPARSE_TAG_IDX, PyLong_FromUnsignedLong(st->st_reparse_tag));
2781
#endif
2782
2783
2.00k
    assert(!PyErr_Occurred());
2784
2.00k
    return v;
2785
2786
0
error:
2787
0
    Py_DECREF(v);
2788
0
    return NULL;
2789
2790
2.00k
#undef SET_ITEM
2791
2.00k
}
2792
2793
/* POSIX methods */
2794
2795
2796
static PyObject *
2797
posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2798
              int dir_fd, int follow_symlinks)
2799
2.23k
{
2800
2.23k
    STRUCT_STAT st;
2801
2.23k
    int result;
2802
2803
2.23k
#ifdef HAVE_FSTATAT
2804
2.23k
    int fstatat_unavailable = 0;
2805
2.23k
#endif
2806
2807
#if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2808
    if (follow_symlinks_specified(function_name, follow_symlinks))
2809
        return NULL;
2810
#endif
2811
2812
2.23k
    if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2813
2.23k
        dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2814
2.23k
        fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2815
0
        return NULL;
2816
2817
2.23k
    Py_BEGIN_ALLOW_THREADS
2818
2.23k
    if (path->fd != -1)
2819
0
        result = FSTAT(path->fd, &st);
2820
#ifdef MS_WINDOWS
2821
    else if (follow_symlinks)
2822
        result = win32_stat(path->wide, &st);
2823
    else
2824
        result = win32_lstat(path->wide, &st);
2825
#else
2826
2.23k
    else
2827
2.23k
#if defined(HAVE_LSTAT)
2828
2.23k
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2829
0
        result = LSTAT(path->narrow, &st);
2830
2.23k
    else
2831
2.23k
#endif /* HAVE_LSTAT */
2832
2.23k
#ifdef HAVE_FSTATAT
2833
2.23k
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2834
0
        if (HAVE_FSTATAT_RUNTIME) {
2835
0
            result = fstatat(dir_fd, path->narrow, &st,
2836
0
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2837
2838
0
        } else {
2839
0
            fstatat_unavailable = 1;
2840
0
        }
2841
0
    } else
2842
2.23k
#endif /* HAVE_FSTATAT */
2843
2.23k
        result = STAT(path->narrow, &st);
2844
2.23k
#endif /* MS_WINDOWS */
2845
2.23k
    Py_END_ALLOW_THREADS
2846
2847
2.23k
#ifdef HAVE_FSTATAT
2848
2.23k
    if (fstatat_unavailable) {
2849
0
        argument_unavailable_error("stat", "dir_fd");
2850
0
        return NULL;
2851
0
    }
2852
2.23k
#endif
2853
2854
2.23k
    if (result != 0) {
2855
227
        return path_error(path);
2856
227
    }
2857
2858
2.00k
    return _pystat_fromstructstat(module, &st);
2859
2.23k
}
2860
2861
/*[python input]
2862
2863
for s in """
2864
2865
FACCESSAT
2866
FCHMODAT
2867
FCHOWNAT
2868
FSTATAT
2869
LINKAT
2870
MKDIRAT
2871
MKFIFOAT
2872
MKNODAT
2873
OPENAT
2874
READLINKAT
2875
SYMLINKAT
2876
UNLINKAT
2877
2878
""".strip().split():
2879
    s = s.strip()
2880
    print("""
2881
#ifdef HAVE_{s}
2882
    #define {s}_DIR_FD_CONVERTER dir_fd_converter
2883
#else
2884
    #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2885
#endif
2886
""".rstrip().format(s=s))
2887
2888
for s in """
2889
2890
FCHDIR
2891
FCHMOD
2892
FCHOWN
2893
FDOPENDIR
2894
FEXECVE
2895
FPATHCONF
2896
FSTATVFS
2897
FTRUNCATE
2898
2899
""".strip().split():
2900
    s = s.strip()
2901
    print("""
2902
#ifdef HAVE_{s}
2903
    #define PATH_HAVE_{s} 1
2904
#else
2905
    #define PATH_HAVE_{s} 0
2906
#endif
2907
2908
""".rstrip().format(s=s))
2909
[python start generated code]*/
2910
2911
#ifdef HAVE_FACCESSAT
2912
0
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2913
#else
2914
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2915
#endif
2916
2917
#ifdef HAVE_FCHMODAT
2918
0
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2919
#else
2920
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2921
#endif
2922
2923
#ifdef HAVE_FCHOWNAT
2924
0
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2925
#else
2926
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2927
#endif
2928
2929
#ifdef HAVE_FSTATAT
2930
0
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2931
#else
2932
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2933
#endif
2934
2935
#ifdef HAVE_LINKAT
2936
    #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2937
#else
2938
    #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2939
#endif
2940
2941
#ifdef HAVE_MKDIRAT
2942
0
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
2943
#else
2944
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
2945
#endif
2946
2947
#ifdef HAVE_MKFIFOAT
2948
0
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
2949
#else
2950
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
2951
#endif
2952
2953
#ifdef HAVE_MKNODAT
2954
0
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
2955
#else
2956
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
2957
#endif
2958
2959
#ifdef HAVE_OPENAT
2960
0
    #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
2961
#else
2962
    #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
2963
#endif
2964
2965
#ifdef HAVE_READLINKAT
2966
0
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
2967
#else
2968
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2969
#endif
2970
2971
#ifdef HAVE_SYMLINKAT
2972
0
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
2973
#else
2974
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2975
#endif
2976
2977
#ifdef HAVE_UNLINKAT
2978
0
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
2979
#else
2980
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2981
#endif
2982
2983
#ifdef HAVE_FCHDIR
2984
    #define PATH_HAVE_FCHDIR 1
2985
#else
2986
    #define PATH_HAVE_FCHDIR 0
2987
#endif
2988
2989
#ifdef HAVE_FCHMOD
2990
    #define PATH_HAVE_FCHMOD 1
2991
#else
2992
    #define PATH_HAVE_FCHMOD 0
2993
#endif
2994
2995
#ifdef HAVE_FCHOWN
2996
    #define PATH_HAVE_FCHOWN 1
2997
#else
2998
    #define PATH_HAVE_FCHOWN 0
2999
#endif
3000
3001
#ifdef HAVE_FDOPENDIR
3002
    #define PATH_HAVE_FDOPENDIR 1
3003
#else
3004
    #define PATH_HAVE_FDOPENDIR 0
3005
#endif
3006
3007
#ifdef HAVE_FEXECVE
3008
    #define PATH_HAVE_FEXECVE 1
3009
#else
3010
    #define PATH_HAVE_FEXECVE 0
3011
#endif
3012
3013
#ifdef HAVE_FPATHCONF
3014
    #define PATH_HAVE_FPATHCONF 1
3015
#else
3016
    #define PATH_HAVE_FPATHCONF 0
3017
#endif
3018
3019
#ifdef HAVE_FSTATVFS
3020
    #define PATH_HAVE_FSTATVFS 1
3021
#else
3022
    #define PATH_HAVE_FSTATVFS 0
3023
#endif
3024
3025
#ifdef HAVE_FTRUNCATE
3026
    #define PATH_HAVE_FTRUNCATE 1
3027
#else
3028
    #define PATH_HAVE_FTRUNCATE 0
3029
#endif
3030
/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
3031
3032
#ifdef MS_WINDOWS
3033
    #undef PATH_HAVE_FTRUNCATE
3034
    #define PATH_HAVE_FTRUNCATE 1
3035
    #undef PATH_HAVE_FCHMOD
3036
    #define PATH_HAVE_FCHMOD 1
3037
#endif
3038
3039
/*[python input]
3040
3041
class path_t_converter(CConverter):
3042
3043
    type = "path_t"
3044
    impl_by_reference = True
3045
    parse_by_reference = True
3046
3047
    converter = 'path_converter'
3048
3049
    def converter_init(self, *, allow_fd=False, make_wide=None,
3050
                       nonstrict=False, nullable=False,
3051
                       suppress_value_error=False):
3052
        # right now path_t doesn't support default values.
3053
        # to support a default value, you'll need to override initialize().
3054
        if self.default not in (unspecified, None):
3055
            fail("Can't specify a default to the path_t converter!")
3056
3057
        if self.c_default not in (None, 'Py_None'):
3058
            raise RuntimeError("Can't specify a c_default to the path_t converter!")
3059
3060
        self.nullable = nullable
3061
        self.nonstrict = nonstrict
3062
        self.make_wide = make_wide
3063
        self.suppress_value_error = suppress_value_error
3064
        self.allow_fd = allow_fd
3065
3066
    def pre_render(self):
3067
        def strify(value):
3068
            if isinstance(value, str):
3069
                return value
3070
            return str(int(bool(value)))
3071
3072
        # add self.py_name here when merging with posixmodule conversion
3073
        if self.make_wide is None:
3074
            self.c_default = 'PATH_T_INITIALIZE_P("{}", "{}", {}, {}, {}, {})'.format(
3075
                self.function.name,
3076
                self.name,
3077
                strify(self.nullable),
3078
                strify(self.nonstrict),
3079
                strify(self.suppress_value_error),
3080
                strify(self.allow_fd),
3081
            )
3082
        else:
3083
            self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {}, {}, {})'.format(
3084
                self.function.name,
3085
                self.name,
3086
                strify(self.nullable),
3087
                strify(self.nonstrict),
3088
                strify(self.make_wide),
3089
                strify(self.suppress_value_error),
3090
                strify(self.allow_fd),
3091
            )
3092
3093
    def cleanup(self):
3094
        return "path_cleanup(&" + self.name + ");\n"
3095
3096
3097
class dir_fd_converter(CConverter):
3098
    type = 'int'
3099
3100
    def converter_init(self, requires=None):
3101
        if self.default in (unspecified, None):
3102
            self.c_default = 'DEFAULT_DIR_FD'
3103
        if isinstance(requires, str):
3104
            self.converter = requires.upper() + '_DIR_FD_CONVERTER'
3105
        else:
3106
            self.converter = 'dir_fd_converter'
3107
3108
class uid_t_converter(CConverter):
3109
    type = "uid_t"
3110
    converter = '_Py_Uid_Converter'
3111
3112
class gid_t_converter(CConverter):
3113
    type = "gid_t"
3114
    converter = '_Py_Gid_Converter'
3115
3116
class dev_t_converter(CConverter):
3117
    type = 'dev_t'
3118
    converter = '_Py_Dev_Converter'
3119
3120
class dev_t_return_converter(unsigned_long_return_converter):
3121
    type = 'dev_t'
3122
    conversion_fn = '_PyLong_FromDev'
3123
    unsigned_cast = '(dev_t)'
3124
3125
class FSConverter_converter(CConverter):
3126
    type = 'PyObject *'
3127
    converter = 'PyUnicode_FSConverter'
3128
    def converter_init(self):
3129
        if self.default is not unspecified:
3130
            fail("FSConverter_converter does not support default values")
3131
        self.c_default = 'NULL'
3132
3133
    def cleanup(self):
3134
        return "Py_XDECREF(" + self.name + ");\n"
3135
3136
class pid_t_converter(CConverter):
3137
    type = 'pid_t'
3138
    format_unit = '" _Py_PARSE_PID "'
3139
3140
    def parse_arg(self, argname, displayname, *, limited_capi):
3141
        return self.format_code("""
3142
            {paramname} = PyLong_AsPid({argname});
3143
            if ({paramname} == (pid_t)(-1) && PyErr_Occurred()) {{{{
3144
                goto exit;
3145
            }}}}
3146
            """, argname=argname)
3147
3148
class idtype_t_converter(CConverter):
3149
    type = 'idtype_t'
3150
    converter = 'idtype_t_converter'
3151
3152
class id_t_converter(CConverter):
3153
    type = 'id_t'
3154
    format_unit = '" _Py_PARSE_PID "'
3155
3156
    def parse_arg(self, argname, displayname, *, limited_capi):
3157
        return self.format_code("""
3158
            {paramname} = (id_t)PyLong_AsPid({argname});
3159
            if ({paramname} == (id_t)(-1) && PyErr_Occurred()) {{{{
3160
                goto exit;
3161
            }}}}
3162
            """, argname=argname)
3163
3164
class intptr_t_converter(CConverter):
3165
    type = 'intptr_t'
3166
    format_unit = '" _Py_PARSE_INTPTR "'
3167
3168
    def parse_arg(self, argname, displayname, *, limited_capi):
3169
        return self.format_code("""
3170
            {paramname} = (intptr_t)PyLong_AsVoidPtr({argname});
3171
            if (!{paramname} && PyErr_Occurred()) {{{{
3172
                goto exit;
3173
            }}}}
3174
            """, argname=argname)
3175
3176
class Py_off_t_converter(CConverter):
3177
    type = 'Py_off_t'
3178
    converter = 'Py_off_t_converter'
3179
3180
class Py_off_t_return_converter(long_return_converter):
3181
    type = 'Py_off_t'
3182
    conversion_fn = 'PyLong_FromPy_off_t'
3183
3184
class confname_converter(CConverter):
3185
    type="int"
3186
    converter="conv_confname"
3187
3188
    def converter_init(self, *, table):
3189
        self.table = table
3190
3191
    def parse_arg(self, argname, displayname, *, limited_capi):
3192
        return self.format_code("""
3193
            if (!{converter}(module, {argname}, &{paramname}, "{table}")) {{{{
3194
                goto exit;
3195
            }}}}
3196
        """, argname=argname, converter=self.converter, table=self.table)
3197
3198
[python start generated code]*/
3199
/*[python end generated code: output=da39a3ee5e6b4b0d input=8189d5ae78244626]*/
3200
3201
/*[clinic input]
3202
3203
os.stat
3204
3205
    path : path_t(allow_fd=True)
3206
        Path to be examined; can be string, bytes, a path-like object or
3207
        open-file-descriptor int.
3208
3209
    *
3210
3211
    dir_fd : dir_fd(requires='fstatat') = None
3212
        If not None, it should be a file descriptor open to a directory,
3213
        and path should be a relative string; path will then be relative to
3214
        that directory.
3215
3216
    follow_symlinks: bool = True
3217
        If False, and the last element of the path is a symbolic link,
3218
        stat will examine the symbolic link itself instead of the file
3219
        the link points to.
3220
3221
Perform a stat system call on the given path.
3222
3223
dir_fd and follow_symlinks may not be implemented
3224
  on your platform.  If they are unavailable, using them will raise a
3225
  NotImplementedError.
3226
3227
It's an error to use dir_fd or follow_symlinks when specifying path as
3228
  an open file descriptor.
3229
3230
[clinic start generated code]*/
3231
3232
static PyObject *
3233
os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
3234
/*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
3235
2.23k
{
3236
2.23k
    return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
3237
2.23k
}
3238
3239
3240
/*[clinic input]
3241
@permit_long_summary
3242
os.lstat
3243
3244
    path : path_t
3245
3246
    *
3247
3248
    dir_fd : dir_fd(requires='fstatat') = None
3249
3250
Perform a stat system call on the given path, without following symbolic links.
3251
3252
Like stat(), but do not follow symbolic links.
3253
Equivalent to stat(path, follow_symlinks=False).
3254
[clinic start generated code]*/
3255
3256
static PyObject *
3257
os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
3258
/*[clinic end generated code: output=ef82a5d35ce8ab37 input=024102124f88e743]*/
3259
0
{
3260
0
    int follow_symlinks = 0;
3261
0
    return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
3262
0
}
3263
3264
3265
/*[clinic input]
3266
os.access -> bool
3267
3268
    path: path_t
3269
        Path to be tested; can be string, bytes, or a path-like object.
3270
3271
    mode: int
3272
        Operating-system mode bitfield.  Can be F_OK to test existence,
3273
        or the inclusive-OR of R_OK, W_OK, and X_OK.
3274
3275
    *
3276
3277
    dir_fd : dir_fd(requires='faccessat') = None
3278
        If not None, it should be a file descriptor open to a directory,
3279
        and path should be relative; path will then be relative to that
3280
        directory.
3281
3282
    effective_ids: bool = False
3283
        If True, access will use the effective uid/gid instead of
3284
        the real uid/gid.
3285
3286
    follow_symlinks: bool = True
3287
        If False, and the last element of the path is a symbolic link,
3288
        access will examine the symbolic link itself instead of the file
3289
        the link points to.
3290
3291
Use the real uid/gid to test for access to a path.
3292
3293
{parameters}
3294
dir_fd, effective_ids, and follow_symlinks may not be implemented
3295
  on your platform.  If they are unavailable, using them will raise a
3296
  NotImplementedError.
3297
3298
Note that most operations will use the effective uid/gid, therefore this
3299
  routine can be used in a suid/sgid environment to test if the invoking
3300
  user has the specified access to the path.
3301
3302
[clinic start generated code]*/
3303
3304
static int
3305
os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3306
               int effective_ids, int follow_symlinks)
3307
/*[clinic end generated code: output=cf84158bc90b1a77 input=c33565f7584b99e4]*/
3308
0
{
3309
0
    int return_value;
3310
3311
#ifdef MS_WINDOWS
3312
    DWORD attr;
3313
#else
3314
0
    int result;
3315
0
#endif
3316
3317
0
#ifdef HAVE_FACCESSAT
3318
0
    int faccessat_unavailable = 0;
3319
0
#endif
3320
3321
#ifndef HAVE_FACCESSAT
3322
    if (follow_symlinks_specified("access", follow_symlinks))
3323
        return -1;
3324
3325
    if (effective_ids) {
3326
        argument_unavailable_error("access", "effective_ids");
3327
        return -1;
3328
    }
3329
#endif
3330
3331
#ifdef MS_WINDOWS
3332
    Py_BEGIN_ALLOW_THREADS
3333
    attr = GetFileAttributesW(path->wide);
3334
    Py_END_ALLOW_THREADS
3335
3336
    /*
3337
     * Access is possible if
3338
     *   * we didn't get a -1, and
3339
     *     * write access wasn't requested,
3340
     *     * or the file isn't read-only,
3341
     *     * or it's a directory.
3342
     * (Directories cannot be read-only on Windows.)
3343
    */
3344
    return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
3345
            (!(mode & 2) ||
3346
            !(attr & FILE_ATTRIBUTE_READONLY) ||
3347
            (attr & FILE_ATTRIBUTE_DIRECTORY));
3348
#else
3349
3350
0
    Py_BEGIN_ALLOW_THREADS
3351
0
#ifdef HAVE_FACCESSAT
3352
0
    if ((dir_fd != DEFAULT_DIR_FD) ||
3353
0
        effective_ids ||
3354
0
        !follow_symlinks) {
3355
3356
0
        if (HAVE_FACCESSAT_RUNTIME) {
3357
0
            int flags = 0;
3358
0
            if (!follow_symlinks)
3359
0
                flags |= AT_SYMLINK_NOFOLLOW;
3360
0
            if (effective_ids)
3361
0
                flags |= AT_EACCESS;
3362
0
            result = faccessat(dir_fd, path->narrow, mode, flags);
3363
0
        } else {
3364
0
            faccessat_unavailable = 1;
3365
0
        }
3366
0
    }
3367
0
    else
3368
0
#endif
3369
0
        result = access(path->narrow, mode);
3370
0
    Py_END_ALLOW_THREADS
3371
3372
0
#ifdef HAVE_FACCESSAT
3373
0
    if (faccessat_unavailable) {
3374
0
        if (dir_fd != DEFAULT_DIR_FD) {
3375
0
            argument_unavailable_error("access", "dir_fd");
3376
0
            return -1;
3377
0
        }
3378
0
        if (follow_symlinks_specified("access", follow_symlinks))
3379
0
            return -1;
3380
3381
0
        if (effective_ids) {
3382
0
            argument_unavailable_error("access", "effective_ids");
3383
0
            return -1;
3384
0
        }
3385
        /* should be unreachable */
3386
0
        return -1;
3387
0
    }
3388
0
#endif
3389
0
    return_value = !result;
3390
0
#endif
3391
3392
0
    return return_value;
3393
0
}
3394
3395
#ifndef F_OK
3396
#define F_OK 0
3397
#endif
3398
#ifndef R_OK
3399
#define R_OK 4
3400
#endif
3401
#ifndef W_OK
3402
#define W_OK 2
3403
#endif
3404
#ifndef X_OK
3405
#define X_OK 1
3406
#endif
3407
3408
3409
#ifdef HAVE_TTYNAME_R
3410
/*[clinic input]
3411
os.ttyname
3412
3413
    fd: int
3414
        Integer file descriptor handle.
3415
3416
    /
3417
3418
Return the name of the terminal device connected to 'fd'.
3419
[clinic start generated code]*/
3420
3421
static PyObject *
3422
os_ttyname_impl(PyObject *module, int fd)
3423
/*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3424
0
{
3425
3426
0
    long size = sysconf(_SC_TTY_NAME_MAX);
3427
0
    if (size == -1) {
3428
0
        return posix_error();
3429
0
    }
3430
0
    char *buffer = (char *)PyMem_RawMalloc(size);
3431
0
    if (buffer == NULL) {
3432
0
        return PyErr_NoMemory();
3433
0
    }
3434
0
    int ret = ttyname_r(fd, buffer, size);
3435
0
    if (ret != 0) {
3436
0
        PyMem_RawFree(buffer);
3437
0
        errno = ret;
3438
0
        return posix_error();
3439
0
    }
3440
0
    PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3441
0
    PyMem_RawFree(buffer);
3442
0
    return res;
3443
0
}
3444
#endif
3445
3446
#ifdef HAVE_CTERMID
3447
/*[clinic input]
3448
os.ctermid
3449
3450
Return the name of the controlling terminal for this process.
3451
[clinic start generated code]*/
3452
3453
static PyObject *
3454
os_ctermid_impl(PyObject *module)
3455
/*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3456
0
{
3457
0
    char *ret;
3458
0
    char buffer[L_ctermid];
3459
3460
#ifdef USE_CTERMID_R
3461
    ret = ctermid_r(buffer);
3462
#else
3463
0
    ret = ctermid(buffer);
3464
0
#endif
3465
0
    if (ret == NULL)
3466
0
        return posix_error();
3467
0
    return PyUnicode_DecodeFSDefault(buffer);
3468
0
}
3469
#endif /* HAVE_CTERMID */
3470
3471
3472
/*[clinic input]
3473
os.chdir
3474
3475
    path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3476
3477
Change the current working directory to the specified path.
3478
3479
path may always be specified as a string.
3480
On some platforms, path may also be specified as an open file descriptor.
3481
If this functionality is unavailable, using it raises an exception.
3482
[clinic start generated code]*/
3483
3484
static PyObject *
3485
os_chdir_impl(PyObject *module, path_t *path)
3486
/*[clinic end generated code: output=3be6400eee26eaae input=a74ceab5d72adf74]*/
3487
0
{
3488
0
    int result;
3489
3490
0
    if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3491
0
        return NULL;
3492
0
    }
3493
3494
0
    Py_BEGIN_ALLOW_THREADS
3495
#ifdef MS_WINDOWS
3496
    /* on unix, success = 0, on windows, success = !0 */
3497
    result = !win32_wchdir(path->wide);
3498
#else
3499
0
#ifdef HAVE_FCHDIR
3500
0
    if (path->fd != -1)
3501
0
        result = fchdir(path->fd);
3502
0
    else
3503
0
#endif
3504
0
        result = chdir(path->narrow);
3505
0
#endif
3506
0
    Py_END_ALLOW_THREADS
3507
3508
0
    if (result) {
3509
0
        return path_error(path);
3510
0
    }
3511
3512
0
    Py_RETURN_NONE;
3513
0
}
3514
3515
3516
#ifdef HAVE_FCHDIR
3517
/*[clinic input]
3518
os.fchdir
3519
3520
    fd: fildes
3521
3522
Change to the directory of the given file descriptor.
3523
3524
fd must be opened on a directory, not a file.
3525
Equivalent to os.chdir(fd).
3526
3527
[clinic start generated code]*/
3528
3529
static PyObject *
3530
os_fchdir_impl(PyObject *module, int fd)
3531
/*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3532
0
{
3533
0
    if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3534
0
        return NULL;
3535
0
    }
3536
0
    return posix_fildes_fd(fd, fchdir);
3537
0
}
3538
#endif /* HAVE_FCHDIR */
3539
3540
#ifdef MS_WINDOWS
3541
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 0
3542
#else
3543
0
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 1
3544
#endif
3545
3546
#ifdef MS_WINDOWS
3547
static int
3548
win32_lchmod(LPCWSTR path, int mode)
3549
{
3550
    DWORD attr = GetFileAttributesW(path);
3551
    if (attr == INVALID_FILE_ATTRIBUTES) {
3552
        return 0;
3553
    }
3554
    if (mode & _S_IWRITE) {
3555
        attr &= ~FILE_ATTRIBUTE_READONLY;
3556
    }
3557
    else {
3558
        attr |= FILE_ATTRIBUTE_READONLY;
3559
    }
3560
    return SetFileAttributesW(path, attr);
3561
}
3562
3563
static int
3564
win32_hchmod(HANDLE hfile, int mode)
3565
{
3566
    FILE_BASIC_INFO info;
3567
    if (!GetFileInformationByHandleEx(hfile, FileBasicInfo,
3568
                                      &info, sizeof(info)))
3569
    {
3570
        return 0;
3571
    }
3572
    if (mode & _S_IWRITE) {
3573
        info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
3574
    }
3575
    else {
3576
        info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
3577
    }
3578
    return SetFileInformationByHandle(hfile, FileBasicInfo,
3579
                                      &info, sizeof(info));
3580
}
3581
3582
static int
3583
win32_fchmod(int fd, int mode)
3584
{
3585
    HANDLE hfile = _Py_get_osfhandle_noraise(fd);
3586
    if (hfile == INVALID_HANDLE_VALUE) {
3587
        SetLastError(ERROR_INVALID_HANDLE);
3588
        return 0;
3589
    }
3590
    return win32_hchmod(hfile, mode);
3591
}
3592
3593
#endif /* MS_WINDOWS */
3594
3595
/*[clinic input]
3596
os.chmod
3597
3598
    path: path_t(allow_fd='PATH_HAVE_FCHMOD')
3599
        Path to be modified.  May always be specified as a str, bytes, or a path-like object.
3600
        On some platforms, path may also be specified as an open file descriptor.
3601
        If this functionality is unavailable, using it raises an exception.
3602
3603
    mode: int
3604
        Operating-system mode bitfield.
3605
        Be careful when using number literals for *mode*. The conventional UNIX notation for
3606
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
3607
        Python.
3608
3609
    *
3610
3611
    dir_fd : dir_fd(requires='fchmodat') = None
3612
        If not None, it should be a file descriptor open to a directory,
3613
        and path should be relative; path will then be relative to that
3614
        directory.
3615
3616
    follow_symlinks: bool(c_default="CHMOD_DEFAULT_FOLLOW_SYMLINKS", \
3617
                          py_default="(os.name != 'nt')") = CHMOD_DEFAULT_FOLLOW_SYMLINKS
3618
        If False, and the last element of the path is a symbolic link,
3619
        chmod will modify the symbolic link itself instead of the file
3620
        the link points to.
3621
3622
Change the access permissions of a file.
3623
3624
It is an error to use dir_fd or follow_symlinks when specifying path as
3625
  an open file descriptor.
3626
dir_fd and follow_symlinks may not be implemented on your platform.
3627
  If they are unavailable, using them will raise a NotImplementedError.
3628
3629
[clinic start generated code]*/
3630
3631
static PyObject *
3632
os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3633
              int follow_symlinks)
3634
/*[clinic end generated code: output=5cf6a94915cc7bff input=fcf115d174b9f3d8]*/
3635
0
{
3636
0
    int result;
3637
3638
0
#ifdef HAVE_FCHMODAT
3639
0
    int fchmodat_nofollow_unsupported = 0;
3640
0
    int fchmodat_unsupported = 0;
3641
0
#endif
3642
3643
#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD) || defined(MS_WINDOWS))
3644
    if (follow_symlinks_specified("chmod", follow_symlinks))
3645
        return NULL;
3646
#endif
3647
3648
0
    if (PySys_Audit("os.chmod", "Oii", path->object, mode,
3649
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3650
0
        return NULL;
3651
0
    }
3652
3653
#ifdef MS_WINDOWS
3654
    result = 0;
3655
    Py_BEGIN_ALLOW_THREADS
3656
    if (path->fd != -1) {
3657
        result = win32_fchmod(path->fd, mode);
3658
    }
3659
    else if (follow_symlinks) {
3660
        HANDLE hfile = CreateFileW(path->wide,
3661
                                   FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
3662
                                   0, NULL,
3663
                                   OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
3664
        if (hfile != INVALID_HANDLE_VALUE) {
3665
            result = win32_hchmod(hfile, mode);
3666
            (void)CloseHandle(hfile);
3667
        }
3668
    }
3669
    else {
3670
        result = win32_lchmod(path->wide, mode);
3671
    }
3672
    Py_END_ALLOW_THREADS
3673
    if (!result) {
3674
        return path_error(path);
3675
    }
3676
#else /* MS_WINDOWS */
3677
0
    Py_BEGIN_ALLOW_THREADS
3678
0
#ifdef HAVE_FCHMOD
3679
0
    if (path->fd != -1)
3680
0
        result = fchmod(path->fd, mode);
3681
0
    else
3682
0
#endif /* HAVE_CHMOD */
3683
#ifdef HAVE_LCHMOD
3684
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3685
        result = lchmod(path->narrow, mode);
3686
    else
3687
#endif /* HAVE_LCHMOD */
3688
0
#ifdef HAVE_FCHMODAT
3689
0
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
3690
0
        if (HAVE_FCHMODAT_RUNTIME) {
3691
            /*
3692
             * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
3693
             * The documentation specifically shows how to use it,
3694
             * and then says it isn't implemented yet.
3695
             * (true on linux with glibc 2.15, and openindiana 3.x)
3696
             *
3697
             * Once it is supported, os.chmod will automatically
3698
             * support dir_fd and follow_symlinks=False.  (Hopefully.)
3699
             * Until then, we need to be careful what exception we raise.
3700
             */
3701
0
            result = fchmodat(dir_fd, path->narrow, mode,
3702
0
                              follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3703
            /*
3704
             * But wait!  We can't throw the exception without allowing threads,
3705
             * and we can't do that in this nested scope.  (Macro trickery, sigh.)
3706
             */
3707
0
            fchmodat_nofollow_unsupported =
3708
0
                             result &&
3709
0
                             ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
3710
0
                             !follow_symlinks;
3711
0
        } else {
3712
0
            fchmodat_unsupported = 1;
3713
0
            fchmodat_nofollow_unsupported = 1;
3714
3715
0
            result = -1;
3716
0
        }
3717
0
    }
3718
0
    else
3719
0
#endif /* HAVE_FHCMODAT */
3720
0
    {
3721
0
#ifdef HAVE_CHMOD
3722
0
        result = chmod(path->narrow, mode);
3723
#elif defined(__wasi__)
3724
        // WASI SDK 15.0 does not support chmod.
3725
        // Ignore missing syscall for now.
3726
        result = 0;
3727
#else
3728
        result = -1;
3729
        errno = ENOSYS;
3730
#endif
3731
0
    }
3732
0
    Py_END_ALLOW_THREADS
3733
3734
0
    if (result) {
3735
0
#ifdef HAVE_FCHMODAT
3736
0
        if (fchmodat_unsupported) {
3737
0
            if (dir_fd != DEFAULT_DIR_FD) {
3738
0
                argument_unavailable_error("chmod", "dir_fd");
3739
0
                return NULL;
3740
0
            }
3741
0
        }
3742
3743
0
        if (fchmodat_nofollow_unsupported) {
3744
0
            if (dir_fd != DEFAULT_DIR_FD)
3745
0
                dir_fd_and_follow_symlinks_invalid("chmod",
3746
0
                                                   dir_fd, follow_symlinks);
3747
0
            else
3748
0
                follow_symlinks_specified("chmod", follow_symlinks);
3749
0
            return NULL;
3750
0
        }
3751
0
        else
3752
0
#endif /* HAVE_FCHMODAT */
3753
0
        return path_error(path);
3754
0
    }
3755
0
#endif /* MS_WINDOWS */
3756
3757
0
    Py_RETURN_NONE;
3758
0
}
3759
3760
3761
#if defined(HAVE_FCHMOD) || defined(MS_WINDOWS)
3762
/*[clinic input]
3763
os.fchmod
3764
3765
    fd: int
3766
        The file descriptor of the file to be modified.
3767
    mode: int
3768
        Operating-system mode bitfield.
3769
        Be careful when using number literals for *mode*. The conventional UNIX notation for
3770
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
3771
        Python.
3772
3773
Change the access permissions of the file given by file descriptor fd.
3774
3775
Equivalent to os.chmod(fd, mode).
3776
[clinic start generated code]*/
3777
3778
static PyObject *
3779
os_fchmod_impl(PyObject *module, int fd, int mode)
3780
/*[clinic end generated code: output=afd9bc05b4e426b3 input=b5594618bbbc22df]*/
3781
0
{
3782
0
    int res;
3783
3784
0
    if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
3785
0
        return NULL;
3786
0
    }
3787
3788
#ifdef MS_WINDOWS
3789
    res = 0;
3790
    Py_BEGIN_ALLOW_THREADS
3791
    res = win32_fchmod(fd, mode);
3792
    Py_END_ALLOW_THREADS
3793
    if (!res) {
3794
        return PyErr_SetFromWindowsErr(0);
3795
    }
3796
#else /* MS_WINDOWS */
3797
0
    int async_err = 0;
3798
0
    do {
3799
0
        Py_BEGIN_ALLOW_THREADS
3800
0
        res = fchmod(fd, mode);
3801
0
        Py_END_ALLOW_THREADS
3802
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3803
0
    if (res != 0)
3804
0
        return (!async_err) ? posix_error() : NULL;
3805
0
#endif /* MS_WINDOWS */
3806
3807
0
    Py_RETURN_NONE;
3808
0
}
3809
#endif /* HAVE_FCHMOD || MS_WINDOWS */
3810
3811
3812
#if defined(HAVE_LCHMOD) || defined(MS_WINDOWS)
3813
/*[clinic input]
3814
os.lchmod
3815
3816
    path: path_t
3817
    mode: int
3818
3819
Change the access permissions of a file, without following symbolic links.
3820
3821
If path is a symlink, this affects the link itself rather than the target.
3822
Equivalent to chmod(path, mode, follow_symlinks=False)."
3823
[clinic start generated code]*/
3824
3825
static PyObject *
3826
os_lchmod_impl(PyObject *module, path_t *path, int mode)
3827
/*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
3828
{
3829
    int res;
3830
    if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
3831
        return NULL;
3832
    }
3833
#ifdef MS_WINDOWS
3834
    Py_BEGIN_ALLOW_THREADS
3835
    res = win32_lchmod(path->wide, mode);
3836
    Py_END_ALLOW_THREADS
3837
    if (!res) {
3838
        path_error(path);
3839
        return NULL;
3840
    }
3841
#else /* MS_WINDOWS */
3842
    Py_BEGIN_ALLOW_THREADS
3843
    res = lchmod(path->narrow, mode);
3844
    Py_END_ALLOW_THREADS
3845
    if (res < 0) {
3846
        path_error(path);
3847
        return NULL;
3848
    }
3849
#endif /* MS_WINDOWS */
3850
    Py_RETURN_NONE;
3851
}
3852
#endif /* HAVE_LCHMOD || MS_WINDOWS */
3853
3854
3855
#ifdef HAVE_CHFLAGS
3856
/*[clinic input]
3857
os.chflags
3858
3859
    path: path_t
3860
    flags: unsigned_long(bitwise=True)
3861
    follow_symlinks: bool=True
3862
3863
Set file flags.
3864
3865
If follow_symlinks is False, and the last element of the path is a symbolic
3866
  link, chflags will change flags on the symbolic link itself instead of the
3867
  file the link points to.
3868
follow_symlinks may not be implemented on your platform.  If it is
3869
unavailable, using it will raise a NotImplementedError.
3870
3871
[clinic start generated code]*/
3872
3873
static PyObject *
3874
os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
3875
                int follow_symlinks)
3876
/*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
3877
{
3878
    int result;
3879
3880
#ifndef HAVE_LCHFLAGS
3881
    if (follow_symlinks_specified("chflags", follow_symlinks))
3882
        return NULL;
3883
#endif
3884
3885
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3886
        return NULL;
3887
    }
3888
3889
    Py_BEGIN_ALLOW_THREADS
3890
#ifdef HAVE_LCHFLAGS
3891
    if (!follow_symlinks)
3892
        result = lchflags(path->narrow, flags);
3893
    else
3894
#endif
3895
        result = chflags(path->narrow, flags);
3896
    Py_END_ALLOW_THREADS
3897
3898
    if (result)
3899
        return path_error(path);
3900
3901
    Py_RETURN_NONE;
3902
}
3903
#endif /* HAVE_CHFLAGS */
3904
3905
3906
#ifdef HAVE_LCHFLAGS
3907
/*[clinic input]
3908
os.lchflags
3909
3910
    path: path_t
3911
    flags: unsigned_long(bitwise=True)
3912
3913
Set file flags.
3914
3915
This function will not follow symbolic links.
3916
Equivalent to chflags(path, flags, follow_symlinks=False).
3917
[clinic start generated code]*/
3918
3919
static PyObject *
3920
os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
3921
/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
3922
{
3923
    int res;
3924
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3925
        return NULL;
3926
    }
3927
    Py_BEGIN_ALLOW_THREADS
3928
    res = lchflags(path->narrow, flags);
3929
    Py_END_ALLOW_THREADS
3930
    if (res < 0) {
3931
        return path_error(path);
3932
    }
3933
    Py_RETURN_NONE;
3934
}
3935
#endif /* HAVE_LCHFLAGS */
3936
3937
3938
#ifdef HAVE_CHROOT
3939
/*[clinic input]
3940
os.chroot
3941
    path: path_t
3942
3943
Change root directory to path.
3944
3945
[clinic start generated code]*/
3946
3947
static PyObject *
3948
os_chroot_impl(PyObject *module, path_t *path)
3949
/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
3950
0
{
3951
0
    int res;
3952
0
    Py_BEGIN_ALLOW_THREADS
3953
0
    res = chroot(path->narrow);
3954
0
    Py_END_ALLOW_THREADS
3955
0
    if (res < 0)
3956
0
        return path_error(path);
3957
0
    Py_RETURN_NONE;
3958
0
}
3959
#endif /* HAVE_CHROOT */
3960
3961
3962
#ifdef HAVE_FSYNC
3963
/*[clinic input]
3964
os.fsync
3965
3966
    fd: fildes
3967
3968
Force write of fd to disk.
3969
[clinic start generated code]*/
3970
3971
static PyObject *
3972
os_fsync_impl(PyObject *module, int fd)
3973
/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
3974
0
{
3975
0
    return posix_fildes_fd(fd, fsync);
3976
0
}
3977
#endif /* HAVE_FSYNC */
3978
3979
3980
#ifdef HAVE_SYNC
3981
/*[clinic input]
3982
os.sync
3983
3984
Force write of everything to disk.
3985
[clinic start generated code]*/
3986
3987
static PyObject *
3988
os_sync_impl(PyObject *module)
3989
/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
3990
0
{
3991
0
    Py_BEGIN_ALLOW_THREADS
3992
0
    sync();
3993
0
    Py_END_ALLOW_THREADS
3994
0
    Py_RETURN_NONE;
3995
0
}
3996
#endif /* HAVE_SYNC */
3997
3998
3999
#ifdef HAVE_FDATASYNC
4000
#ifdef __hpux
4001
extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
4002
#endif
4003
4004
/*[clinic input]
4005
os.fdatasync
4006
4007
    fd: fildes
4008
4009
Force write of fd to disk without forcing update of metadata.
4010
[clinic start generated code]*/
4011
4012
static PyObject *
4013
os_fdatasync_impl(PyObject *module, int fd)
4014
/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
4015
0
{
4016
0
    return posix_fildes_fd(fd, fdatasync);
4017
0
}
4018
#endif /* HAVE_FDATASYNC */
4019
4020
4021
#ifdef HAVE_CHOWN
4022
/*[clinic input]
4023
os.chown
4024
4025
    path : path_t(allow_fd='PATH_HAVE_FCHOWN')
4026
        Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
4027
4028
    uid: uid_t
4029
4030
    gid: gid_t
4031
4032
    *
4033
4034
    dir_fd : dir_fd(requires='fchownat') = None
4035
        If not None, it should be a file descriptor open to a directory,
4036
        and path should be relative; path will then be relative to that
4037
        directory.
4038
4039
    follow_symlinks: bool = True
4040
        If False, and the last element of the path is a symbolic link,
4041
        stat will examine the symbolic link itself instead of the file
4042
        the link points to.
4043
4044
Change the owner and group id of path to the numeric uid and gid.\
4045
4046
path may always be specified as a string.
4047
On some platforms, path may also be specified as an open file descriptor.
4048
  If this functionality is unavailable, using it raises an exception.
4049
If dir_fd is 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 directory.
4051
If follow_symlinks is False, and the last element of the path is a symbolic
4052
  link, chown will modify the symbolic link itself instead of the file the
4053
  link points to.
4054
It is an error to use dir_fd or follow_symlinks when specifying path as
4055
  an open file descriptor.
4056
dir_fd and follow_symlinks may not be implemented on your platform.
4057
  If they are unavailable, using them will raise a NotImplementedError.
4058
4059
[clinic start generated code]*/
4060
4061
static PyObject *
4062
os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
4063
              int dir_fd, int follow_symlinks)
4064
/*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
4065
0
{
4066
0
    int result;
4067
4068
0
#if defined(HAVE_FCHOWNAT)
4069
0
    int fchownat_unsupported = 0;
4070
0
#endif
4071
4072
#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
4073
    if (follow_symlinks_specified("chown", follow_symlinks))
4074
        return NULL;
4075
#endif
4076
0
    if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
4077
0
        fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
4078
0
        return NULL;
4079
4080
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
4081
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4082
0
        return NULL;
4083
0
    }
4084
4085
0
    Py_BEGIN_ALLOW_THREADS
4086
0
#ifdef HAVE_FCHOWN
4087
0
    if (path->fd != -1)
4088
0
        result = fchown(path->fd, uid, gid);
4089
0
    else
4090
0
#endif
4091
0
#ifdef HAVE_LCHOWN
4092
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4093
0
        result = lchown(path->narrow, uid, gid);
4094
0
    else
4095
0
#endif
4096
0
#ifdef HAVE_FCHOWNAT
4097
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
4098
0
      if (HAVE_FCHOWNAT_RUNTIME) {
4099
0
        result = fchownat(dir_fd, path->narrow, uid, gid,
4100
0
                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4101
0
      } else {
4102
0
         fchownat_unsupported = 1;
4103
0
      }
4104
0
    } else
4105
0
#endif
4106
0
        result = chown(path->narrow, uid, gid);
4107
0
    Py_END_ALLOW_THREADS
4108
4109
0
#ifdef HAVE_FCHOWNAT
4110
0
    if (fchownat_unsupported) {
4111
        /* This would be incorrect if the current platform
4112
         * doesn't support lchown.
4113
         */
4114
0
        argument_unavailable_error(NULL, "dir_fd");
4115
0
        return NULL;
4116
0
    }
4117
0
#endif
4118
4119
0
    if (result)
4120
0
        return path_error(path);
4121
4122
0
    Py_RETURN_NONE;
4123
0
}
4124
#endif /* HAVE_CHOWN */
4125
4126
4127
#ifdef HAVE_FCHOWN
4128
/*[clinic input]
4129
os.fchown
4130
4131
    fd: int
4132
    uid: uid_t
4133
    gid: gid_t
4134
4135
Change the owner and group id of the file specified by file descriptor.
4136
4137
Equivalent to os.chown(fd, uid, gid).
4138
4139
[clinic start generated code]*/
4140
4141
static PyObject *
4142
os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
4143
/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
4144
0
{
4145
0
    int res;
4146
0
    int async_err = 0;
4147
4148
0
    if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
4149
0
        return NULL;
4150
0
    }
4151
4152
0
    do {
4153
0
        Py_BEGIN_ALLOW_THREADS
4154
0
        res = fchown(fd, uid, gid);
4155
0
        Py_END_ALLOW_THREADS
4156
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4157
0
    if (res != 0)
4158
0
        return (!async_err) ? posix_error() : NULL;
4159
4160
0
    Py_RETURN_NONE;
4161
0
}
4162
#endif /* HAVE_FCHOWN */
4163
4164
4165
#ifdef HAVE_LCHOWN
4166
/*[clinic input]
4167
os.lchown
4168
4169
    path : path_t
4170
    uid: uid_t
4171
    gid: gid_t
4172
4173
Change the owner and group id of path to the numeric uid and gid.
4174
4175
This function will not follow symbolic links.
4176
Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
4177
[clinic start generated code]*/
4178
4179
static PyObject *
4180
os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
4181
/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
4182
0
{
4183
0
    int res;
4184
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
4185
0
        return NULL;
4186
0
    }
4187
0
    Py_BEGIN_ALLOW_THREADS
4188
0
    res = lchown(path->narrow, uid, gid);
4189
0
    Py_END_ALLOW_THREADS
4190
0
    if (res < 0) {
4191
0
        return path_error(path);
4192
0
    }
4193
0
    Py_RETURN_NONE;
4194
0
}
4195
#endif /* HAVE_LCHOWN */
4196
4197
4198
static PyObject *
4199
posix_getcwd(int use_bytes)
4200
0
{
4201
#ifdef MS_WINDOWS
4202
    wchar_t wbuf[MAXPATHLEN];
4203
    wchar_t *wbuf2 = wbuf;
4204
    DWORD len;
4205
4206
    Py_BEGIN_ALLOW_THREADS
4207
    len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
4208
    /* If the buffer is large enough, len does not include the
4209
       terminating \0. If the buffer is too small, len includes
4210
       the space needed for the terminator. */
4211
    if (len >= Py_ARRAY_LENGTH(wbuf)) {
4212
        if ((Py_ssize_t)len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4213
            wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
4214
        }
4215
        else {
4216
            wbuf2 = NULL;
4217
        }
4218
        if (wbuf2) {
4219
            len = GetCurrentDirectoryW(len, wbuf2);
4220
        }
4221
    }
4222
    Py_END_ALLOW_THREADS
4223
4224
    if (!wbuf2) {
4225
        PyErr_NoMemory();
4226
        return NULL;
4227
    }
4228
    if (!len) {
4229
        PyErr_SetFromWindowsErr(0);
4230
        if (wbuf2 != wbuf)
4231
            PyMem_RawFree(wbuf2);
4232
        return NULL;
4233
    }
4234
4235
    PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
4236
    if (wbuf2 != wbuf) {
4237
        PyMem_RawFree(wbuf2);
4238
    }
4239
4240
    if (use_bytes) {
4241
        if (resobj == NULL) {
4242
            return NULL;
4243
        }
4244
        Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
4245
    }
4246
4247
    return resobj;
4248
#else
4249
0
    const size_t chunk = 1024;
4250
4251
0
    char *buf = NULL;
4252
0
    char *cwd = NULL;
4253
0
    size_t buflen = 0;
4254
4255
0
    Py_BEGIN_ALLOW_THREADS
4256
0
    do {
4257
0
        char *newbuf;
4258
0
        if (buflen <= PY_SSIZE_T_MAX - chunk) {
4259
0
            buflen += chunk;
4260
0
            newbuf = PyMem_RawRealloc(buf, buflen);
4261
0
        }
4262
0
        else {
4263
0
            newbuf = NULL;
4264
0
        }
4265
0
        if (newbuf == NULL) {
4266
0
            PyMem_RawFree(buf);
4267
0
            buf = NULL;
4268
0
            break;
4269
0
        }
4270
0
        buf = newbuf;
4271
4272
0
        cwd = getcwd(buf, buflen);
4273
0
    } while (cwd == NULL && errno == ERANGE);
4274
0
    Py_END_ALLOW_THREADS
4275
4276
0
    if (buf == NULL) {
4277
0
        return PyErr_NoMemory();
4278
0
    }
4279
0
    if (cwd == NULL) {
4280
0
        posix_error();
4281
0
        PyMem_RawFree(buf);
4282
0
        return NULL;
4283
0
    }
4284
4285
0
    PyObject *obj;
4286
0
    if (use_bytes) {
4287
0
        obj = PyBytes_FromStringAndSize(buf, strlen(buf));
4288
0
    }
4289
0
    else {
4290
0
        obj = PyUnicode_DecodeFSDefault(buf);
4291
0
    }
4292
0
#ifdef __linux__
4293
0
    if (buf[0] != '/') {
4294
        /*
4295
         * On Linux >= 2.6.36 with glibc < 2.27, getcwd() can return a
4296
         * relative pathname starting with '(unreachable)'. We detect this
4297
         * and fail with ENOENT, matching newer glibc behaviour.
4298
         */
4299
0
        errno = ENOENT;
4300
0
        path_object_error(obj);
4301
0
        PyMem_RawFree(buf);
4302
0
        return NULL;
4303
0
    }
4304
0
#endif
4305
0
    assert(buf[0] == '/');
4306
0
    PyMem_RawFree(buf);
4307
4308
0
    return obj;
4309
0
#endif   /* !MS_WINDOWS */
4310
0
}
4311
4312
4313
/*[clinic input]
4314
os.getcwd
4315
4316
Return a unicode string representing the current working directory.
4317
[clinic start generated code]*/
4318
4319
static PyObject *
4320
os_getcwd_impl(PyObject *module)
4321
/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
4322
0
{
4323
0
    return posix_getcwd(0);
4324
0
}
4325
4326
4327
/*[clinic input]
4328
os.getcwdb
4329
4330
Return a bytes string representing the current working directory.
4331
[clinic start generated code]*/
4332
4333
static PyObject *
4334
os_getcwdb_impl(PyObject *module)
4335
/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
4336
0
{
4337
0
    return posix_getcwd(1);
4338
0
}
4339
4340
4341
#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
4342
#define HAVE_LINK 1
4343
#endif
4344
4345
#ifdef HAVE_LINK
4346
/*[clinic input]
4347
4348
@permit_long_docstring_body
4349
os.link
4350
4351
    src : path_t
4352
    dst : path_t
4353
    *
4354
    src_dir_fd : dir_fd = None
4355
    dst_dir_fd : dir_fd = None
4356
    follow_symlinks: bool(c_default="-1", py_default="(os.name != 'nt')") = PLACEHOLDER
4357
4358
Create a hard link to a file.
4359
4360
If either src_dir_fd or dst_dir_fd is not None, it should be a file
4361
  descriptor open to a directory, and the respective path string (src or dst)
4362
  should be relative; the path will then be relative to that directory.
4363
If follow_symlinks is False, and the last element of src is a symbolic
4364
  link, link will create a link to the symbolic link itself instead of the
4365
  file the link points to.
4366
src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
4367
  platform.  If they are unavailable, using them will raise a
4368
  NotImplementedError.
4369
[clinic start generated code]*/
4370
4371
static PyObject *
4372
os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4373
             int dst_dir_fd, int follow_symlinks)
4374
/*[clinic end generated code: output=7f00f6007fd5269a input=e2a50a6497050e44]*/
4375
0
{
4376
#ifdef MS_WINDOWS
4377
    BOOL result = FALSE;
4378
#else
4379
0
    int result;
4380
0
#endif
4381
4382
0
#ifdef HAVE_LINKAT
4383
0
    if (HAVE_LINKAT_RUNTIME) {
4384
0
        if (follow_symlinks < 0) {
4385
0
            follow_symlinks = 1;
4386
0
        }
4387
0
    }
4388
0
    else
4389
0
#endif
4390
0
    {
4391
0
        if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
4392
0
            argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
4393
0
            return NULL;
4394
0
        }
4395
/* See issue 85527: link() on Linux works like linkat without AT_SYMLINK_FOLLOW,
4396
   but on Mac it works like linkat *with* AT_SYMLINK_FOLLOW. */
4397
0
#if defined(MS_WINDOWS) || defined(__linux__)
4398
0
        if (follow_symlinks == 1) {
4399
0
            argument_unavailable_error("link", "follow_symlinks=True");
4400
0
            return NULL;
4401
0
        }
4402
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || (defined(__sun) && defined(__SVR4))
4403
        if (follow_symlinks == 0) {
4404
            argument_unavailable_error("link", "follow_symlinks=False");
4405
            return NULL;
4406
        }
4407
#else
4408
        if (follow_symlinks >= 0) {
4409
            argument_unavailable_error("link", "follow_symlinks");
4410
            return NULL;
4411
        }
4412
#endif
4413
0
    }
4414
4415
0
    if (PySys_Audit("os.link", "OOii", src->object, dst->object,
4416
0
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4417
0
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4418
0
        return NULL;
4419
0
    }
4420
4421
#ifdef MS_WINDOWS
4422
    Py_BEGIN_ALLOW_THREADS
4423
    result = CreateHardLinkW(dst->wide, src->wide, NULL);
4424
    Py_END_ALLOW_THREADS
4425
4426
    if (!result)
4427
        return path_error2(src, dst);
4428
#else
4429
0
    Py_BEGIN_ALLOW_THREADS
4430
0
#ifdef HAVE_LINKAT
4431
0
    if (HAVE_LINKAT_RUNTIME) {
4432
0
        result = linkat(src_dir_fd, src->narrow,
4433
0
            dst_dir_fd, dst->narrow,
4434
0
            follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
4435
0
    }
4436
0
    else
4437
0
#endif
4438
0
    {
4439
        /* linkat not available */
4440
0
        result = link(src->narrow, dst->narrow);
4441
0
    }
4442
0
    Py_END_ALLOW_THREADS
4443
4444
0
    if (result)
4445
0
        return path_error2(src, dst);
4446
0
#endif /* MS_WINDOWS */
4447
4448
0
    Py_RETURN_NONE;
4449
0
}
4450
#endif
4451
4452
4453
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4454
static PyObject *
4455
_listdir_windows_no_opendir(path_t *path, PyObject *list)
4456
{
4457
    PyObject *v;
4458
    HANDLE hFindFile = INVALID_HANDLE_VALUE;
4459
    BOOL result, return_bytes;
4460
    wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
4461
    /* only claim to have space for MAX_PATH */
4462
    Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
4463
    wchar_t *wnamebuf = NULL;
4464
4465
    WIN32_FIND_DATAW wFileData;
4466
    const wchar_t *po_wchars;
4467
4468
    if (!path->wide) { /* Default arg: "." */
4469
        po_wchars = L".";
4470
        len = 1;
4471
        return_bytes = 0;
4472
    } else {
4473
        po_wchars = path->wide;
4474
        len = wcslen(path->wide);
4475
        return_bytes = PyBytes_Check(path->object);
4476
    }
4477
    /* The +5 is so we can append "\\*.*\0" */
4478
    wnamebuf = PyMem_New(wchar_t, len + 5);
4479
    if (!wnamebuf) {
4480
        PyErr_NoMemory();
4481
        goto exit;
4482
    }
4483
    wcscpy(wnamebuf, po_wchars);
4484
    if (len > 0) {
4485
        wchar_t wch = wnamebuf[len-1];
4486
        if (wch != SEP && wch != ALTSEP && wch != L':')
4487
            wnamebuf[len++] = SEP;
4488
        wcscpy(wnamebuf + len, L"*.*");
4489
    }
4490
    if ((list = PyList_New(0)) == NULL) {
4491
        goto exit;
4492
    }
4493
    Py_BEGIN_ALLOW_THREADS
4494
    hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4495
    Py_END_ALLOW_THREADS
4496
    if (hFindFile == INVALID_HANDLE_VALUE) {
4497
        int error = GetLastError();
4498
        if (error == ERROR_FILE_NOT_FOUND)
4499
            goto exit;
4500
        path_error(path);
4501
        Py_CLEAR(list);
4502
        goto exit;
4503
    }
4504
    do {
4505
        /* Skip over . and .. */
4506
        if (wcscmp(wFileData.cFileName, L".") != 0 &&
4507
            wcscmp(wFileData.cFileName, L"..") != 0) {
4508
            v = PyUnicode_FromWideChar(wFileData.cFileName,
4509
                                       wcslen(wFileData.cFileName));
4510
            if (return_bytes && v) {
4511
                Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4512
            }
4513
            if (v == NULL) {
4514
                Py_CLEAR(list);
4515
                break;
4516
            }
4517
            if (PyList_Append(list, v) != 0) {
4518
                Py_DECREF(v);
4519
                Py_CLEAR(list);
4520
                break;
4521
            }
4522
            Py_DECREF(v);
4523
        }
4524
        Py_BEGIN_ALLOW_THREADS
4525
        result = FindNextFileW(hFindFile, &wFileData);
4526
        Py_END_ALLOW_THREADS
4527
        /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4528
           it got to the end of the directory. */
4529
        if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4530
            path_error(path);
4531
            Py_CLEAR(list);
4532
            goto exit;
4533
        }
4534
    } while (result == TRUE);
4535
4536
exit:
4537
    if (hFindFile != INVALID_HANDLE_VALUE) {
4538
        if (FindClose(hFindFile) == FALSE) {
4539
            if (list != NULL) {
4540
                path_error(path);
4541
                Py_CLEAR(list);
4542
            }
4543
        }
4544
    }
4545
    PyMem_Free(wnamebuf);
4546
4547
    return list;
4548
}  /* end of _listdir_windows_no_opendir */
4549
4550
#else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4551
4552
static PyObject *
4553
_posix_listdir(path_t *path, PyObject *list)
4554
120
{
4555
120
    PyObject *v;
4556
120
    DIR *dirp = NULL;
4557
120
    struct dirent *ep;
4558
120
    int return_str; /* if false, return bytes */
4559
120
#ifdef HAVE_FDOPENDIR
4560
120
    int fd = -1;
4561
120
#endif
4562
4563
120
    errno = 0;
4564
120
#ifdef HAVE_FDOPENDIR
4565
120
    if (path->fd != -1) {
4566
0
      if (HAVE_FDOPENDIR_RUNTIME) {
4567
        /* closedir() closes the FD, so we duplicate it */
4568
0
        fd = _Py_dup(path->fd);
4569
0
        if (fd == -1)
4570
0
            return NULL;
4571
4572
0
        return_str = 1;
4573
4574
0
        Py_BEGIN_ALLOW_THREADS
4575
0
        dirp = fdopendir(fd);
4576
0
        Py_END_ALLOW_THREADS
4577
0
      } else {
4578
0
        PyErr_SetString(PyExc_TypeError,
4579
0
            "listdir: path should be string, bytes, os.PathLike or None, not int");
4580
0
        return NULL;
4581
0
      }
4582
0
    }
4583
120
    else
4584
120
#endif
4585
120
    {
4586
120
        const char *name;
4587
120
        if (path->narrow) {
4588
120
            name = path->narrow;
4589
            /* only return bytes if they specified a bytes object */
4590
120
            return_str = !PyBytes_Check(path->object);
4591
120
        }
4592
0
        else {
4593
0
            name = ".";
4594
0
            return_str = 1;
4595
0
        }
4596
4597
120
        Py_BEGIN_ALLOW_THREADS
4598
120
        dirp = opendir(name);
4599
120
        Py_END_ALLOW_THREADS
4600
120
    }
4601
4602
120
    if (dirp == NULL) {
4603
0
        path_error(path);
4604
0
        list = NULL;
4605
0
#ifdef HAVE_FDOPENDIR
4606
0
        if (fd != -1) {
4607
0
            Py_BEGIN_ALLOW_THREADS
4608
0
            close(fd);
4609
0
            Py_END_ALLOW_THREADS
4610
0
        }
4611
0
#endif
4612
0
        goto exit;
4613
0
    }
4614
120
    if ((list = PyList_New(0)) == NULL) {
4615
0
        goto exit;
4616
0
    }
4617
9.17k
    for (;;) {
4618
9.17k
        errno = 0;
4619
9.17k
        Py_BEGIN_ALLOW_THREADS
4620
9.17k
        ep = readdir(dirp);
4621
9.17k
        Py_END_ALLOW_THREADS
4622
9.17k
        if (ep == NULL) {
4623
120
            if (errno == 0) {
4624
120
                break;
4625
120
            } else {
4626
0
                path_error(path);
4627
0
                Py_CLEAR(list);
4628
0
                goto exit;
4629
0
            }
4630
120
        }
4631
9.05k
        if (ep->d_name[0] == '.' &&
4632
9.05k
            (NAMLEN(ep) == 1 ||
4633
240
             (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
4634
240
            continue;
4635
8.81k
        if (return_str)
4636
8.81k
            v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
4637
0
        else
4638
0
            v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
4639
8.81k
        if (v == NULL) {
4640
0
            Py_CLEAR(list);
4641
0
            break;
4642
0
        }
4643
8.81k
        if (PyList_Append(list, v) != 0) {
4644
0
            Py_DECREF(v);
4645
0
            Py_CLEAR(list);
4646
0
            break;
4647
0
        }
4648
8.81k
        Py_DECREF(v);
4649
8.81k
    }
4650
4651
120
exit:
4652
120
    if (dirp != NULL) {
4653
120
        Py_BEGIN_ALLOW_THREADS
4654
120
#ifdef HAVE_FDOPENDIR
4655
120
        if (fd > -1)
4656
0
            rewinddir(dirp);
4657
120
#endif
4658
120
        closedir(dirp);
4659
120
        Py_END_ALLOW_THREADS
4660
120
    }
4661
4662
120
    return list;
4663
120
}  /* end of _posix_listdir */
4664
#endif  /* which OS */
4665
4666
4667
/*[clinic input]
4668
@permit_long_docstring_body
4669
os.listdir
4670
4671
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
4672
4673
Return a list containing the names of the files in the directory.
4674
4675
path can be specified as either str, bytes, or a path-like object.  If path is bytes,
4676
  the filenames returned will also be bytes; in all other circumstances
4677
  the filenames returned will be str.
4678
If path is None, uses the path='.'.
4679
On some platforms, path may also be specified as an open file descriptor;\
4680
  the file descriptor must refer to a directory.
4681
  If this functionality is unavailable, using it raises NotImplementedError.
4682
4683
The list is in arbitrary order.  It does not include the special
4684
entries '.' and '..' even if they are present in the directory.
4685
4686
4687
[clinic start generated code]*/
4688
4689
static PyObject *
4690
os_listdir_impl(PyObject *module, path_t *path)
4691
/*[clinic end generated code: output=293045673fcd1a75 input=0bd1728387391b9a]*/
4692
120
{
4693
120
    if (PySys_Audit("os.listdir", "O",
4694
120
                    path->object ? path->object : Py_None) < 0) {
4695
0
        return NULL;
4696
0
    }
4697
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4698
    return _listdir_windows_no_opendir(path, NULL);
4699
#else
4700
120
    return _posix_listdir(path, NULL);
4701
120
#endif
4702
120
}
4703
4704
4705
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
4706
4707
/*[clinic input]
4708
os.listdrives
4709
4710
Return a list containing the names of drives in the system.
4711
4712
A drive name typically looks like 'C:\\'.
4713
4714
[clinic start generated code]*/
4715
4716
static PyObject *
4717
os_listdrives_impl(PyObject *module)
4718
/*[clinic end generated code: output=aaece9dacdf682b5 input=1af9ccc9e583798e]*/
4719
{
4720
    /* Number of possible drives is limited, so 256 should always be enough.
4721
       On the day when it is not, listmounts() will have to be used. */
4722
    wchar_t buffer[256];
4723
    DWORD buflen = Py_ARRAY_LENGTH(buffer);
4724
    PyObject *result = NULL;
4725
    if (PySys_Audit("os.listdrives", NULL) < 0) {
4726
        return NULL;
4727
    }
4728
4729
    Py_BEGIN_ALLOW_THREADS;
4730
    buflen = GetLogicalDriveStringsW(buflen, buffer);
4731
    Py_END_ALLOW_THREADS;
4732
4733
    if (!buflen) {
4734
        PyErr_SetFromWindowsErr(0);
4735
        return NULL;
4736
    } else if (buflen >= Py_ARRAY_LENGTH(buffer)) {
4737
        PyErr_SetFromWindowsErr(ERROR_MORE_DATA);
4738
        return NULL;
4739
    }
4740
4741
    /* buflen includes a null terminator, so remove it */
4742
    PyObject *str = PyUnicode_FromWideChar(buffer, buflen - 1);
4743
    if (str) {
4744
        PyObject *nullchar = PyUnicode_FromStringAndSize("\0", 1);
4745
        if (nullchar) {
4746
            result = PyUnicode_Split(str, nullchar, -1);
4747
            Py_DECREF(nullchar);
4748
        }
4749
        Py_DECREF(str);
4750
    }
4751
    return result;
4752
}
4753
4754
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
4755
4756
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
4757
4758
/*[clinic input]
4759
os.listvolumes
4760
4761
Return a list containing the volumes in the system.
4762
4763
Volumes are typically represented as a GUID path.
4764
4765
[clinic start generated code]*/
4766
4767
static PyObject *
4768
os_listvolumes_impl(PyObject *module)
4769
/*[clinic end generated code: output=534e10ea2bf9d386 input=f6e4e70371f11e99]*/
4770
{
4771
    PyObject *result = PyList_New(0);
4772
    HANDLE find = INVALID_HANDLE_VALUE;
4773
    wchar_t buffer[MAX_PATH + 1];
4774
    if (!result) {
4775
        return NULL;
4776
    }
4777
    if (PySys_Audit("os.listvolumes", NULL) < 0) {
4778
        Py_DECREF(result);
4779
        return NULL;
4780
    }
4781
4782
    int err = 0;
4783
    Py_BEGIN_ALLOW_THREADS;
4784
    find = FindFirstVolumeW(buffer, Py_ARRAY_LENGTH(buffer));
4785
    if (find == INVALID_HANDLE_VALUE) {
4786
        err = GetLastError();
4787
    }
4788
    Py_END_ALLOW_THREADS;
4789
4790
    while (!err) {
4791
        PyObject *s = PyUnicode_FromWideChar(buffer, -1);
4792
        if (!s || PyList_Append(result, s) < 0) {
4793
            Py_XDECREF(s);
4794
            Py_CLEAR(result);
4795
            break;
4796
        }
4797
        Py_DECREF(s);
4798
4799
        Py_BEGIN_ALLOW_THREADS;
4800
        if (!FindNextVolumeW(find, buffer, Py_ARRAY_LENGTH(buffer))) {
4801
            err = GetLastError();
4802
        }
4803
        Py_END_ALLOW_THREADS;
4804
    }
4805
4806
    if (find != INVALID_HANDLE_VALUE) {
4807
        Py_BEGIN_ALLOW_THREADS;
4808
        FindVolumeClose(find);
4809
        Py_END_ALLOW_THREADS;
4810
    }
4811
    if (err && err != ERROR_NO_MORE_FILES) {
4812
        PyErr_SetFromWindowsErr(err);
4813
        Py_XDECREF(result);
4814
        result = NULL;
4815
    }
4816
    return result;
4817
}
4818
4819
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
4820
4821
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
4822
4823
/*[clinic input]
4824
os.listmounts
4825
4826
    volume: path_t
4827
4828
Return a list containing mount points for a particular volume.
4829
4830
'volume' should be a GUID path as returned from os.listvolumes.
4831
4832
[clinic start generated code]*/
4833
4834
static PyObject *
4835
os_listmounts_impl(PyObject *module, path_t *volume)
4836
/*[clinic end generated code: output=06da49679de4512e input=a8a27178e3f67845]*/
4837
{
4838
    wchar_t default_buffer[MAX_PATH + 1];
4839
    DWORD buflen = Py_ARRAY_LENGTH(default_buffer);
4840
    LPWSTR buffer = default_buffer;
4841
    DWORD attributes;
4842
    PyObject *str = NULL;
4843
    PyObject *nullchar = NULL;
4844
    PyObject *result = NULL;
4845
4846
    /* Ensure we have a valid volume path before continuing */
4847
    Py_BEGIN_ALLOW_THREADS
4848
    attributes = GetFileAttributesW(volume->wide);
4849
    Py_END_ALLOW_THREADS
4850
    if (attributes == INVALID_FILE_ATTRIBUTES &&
4851
        GetLastError() == ERROR_UNRECOGNIZED_VOLUME)
4852
    {
4853
        return PyErr_SetFromWindowsErr(ERROR_UNRECOGNIZED_VOLUME);
4854
    }
4855
4856
    if (PySys_Audit("os.listmounts", "O", volume->object) < 0) {
4857
        return NULL;
4858
    }
4859
4860
    while (1) {
4861
        BOOL success;
4862
        Py_BEGIN_ALLOW_THREADS
4863
        success = GetVolumePathNamesForVolumeNameW(volume->wide, buffer,
4864
                                                   buflen, &buflen);
4865
        Py_END_ALLOW_THREADS
4866
        if (success) {
4867
            break;
4868
        }
4869
        if (GetLastError() != ERROR_MORE_DATA) {
4870
            PyErr_SetFromWindowsErr(0);
4871
            goto exit;
4872
        }
4873
        if (buffer != default_buffer) {
4874
            PyMem_Free((void *)buffer);
4875
        }
4876
        buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * buflen);
4877
        if (!buffer) {
4878
            PyErr_NoMemory();
4879
            goto exit;
4880
        }
4881
    }
4882
    if (buflen < 2) {
4883
        result = PyList_New(0);
4884
        goto exit;
4885
    }
4886
    // buflen includes two null terminators, one for the last string
4887
    // and one for the array of strings.
4888
    str = PyUnicode_FromWideChar(buffer, buflen - 2);
4889
    nullchar = PyUnicode_FromStringAndSize("\0", 1);
4890
    if (str && nullchar) {
4891
        result = PyUnicode_Split(str, nullchar, -1);
4892
    }
4893
exit:
4894
    if (buffer != default_buffer) {
4895
        PyMem_Free(buffer);
4896
    }
4897
    Py_XDECREF(nullchar);
4898
    Py_XDECREF(str);
4899
    return result;
4900
}
4901
4902
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
4903
4904
#ifdef MS_WINDOWS
4905
4906
/*[clinic input]
4907
os._path_isdevdrive
4908
4909
    path: path_t
4910
4911
Determines whether the specified path is on a Windows Dev Drive.
4912
4913
[clinic start generated code]*/
4914
4915
static PyObject *
4916
os__path_isdevdrive_impl(PyObject *module, path_t *path)
4917
/*[clinic end generated code: output=1f437ea6677433a2 input=ee83e4996a48e23d]*/
4918
{
4919
#ifndef PERSISTENT_VOLUME_STATE_DEV_VOLUME
4920
    /* This flag will be documented at
4921
       https://learn.microsoft.com/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_fs_persistent_volume_information
4922
       after release, and will be available in the latest WinSDK.
4923
       We include the flag to avoid a specific version dependency
4924
       on the latest WinSDK. */
4925
    const int PERSISTENT_VOLUME_STATE_DEV_VOLUME = 0x00002000;
4926
#endif
4927
    int err = 0;
4928
    PyObject *r = NULL;
4929
    wchar_t volume[MAX_PATH];
4930
4931
    Py_BEGIN_ALLOW_THREADS
4932
    if (!GetVolumePathNameW(path->wide, volume, MAX_PATH)) {
4933
        /* invalid path of some kind */
4934
        /* Note that this also includes the case where a volume is mounted
4935
           in a path longer than 260 characters. This is likely to be rare
4936
           and problematic for other reasons, so a (soft) failure in this
4937
           check seems okay. */
4938
        err = GetLastError();
4939
    } else if (GetDriveTypeW(volume) != DRIVE_FIXED) {
4940
        /* only care about local dev drives */
4941
        r = Py_False;
4942
    } else {
4943
        HANDLE hVolume = CreateFileW(
4944
            volume,
4945
            FILE_READ_ATTRIBUTES,
4946
            FILE_SHARE_READ | FILE_SHARE_WRITE,
4947
            NULL,
4948
            OPEN_EXISTING,
4949
            FILE_FLAG_BACKUP_SEMANTICS,
4950
            NULL
4951
        );
4952
        if (hVolume == INVALID_HANDLE_VALUE) {
4953
            err = GetLastError();
4954
        } else {
4955
            FILE_FS_PERSISTENT_VOLUME_INFORMATION volumeState = {0};
4956
            volumeState.Version = 1;
4957
            volumeState.FlagMask = PERSISTENT_VOLUME_STATE_DEV_VOLUME;
4958
            if (!DeviceIoControl(
4959
                hVolume,
4960
                FSCTL_QUERY_PERSISTENT_VOLUME_STATE,
4961
                &volumeState,
4962
                sizeof(volumeState),
4963
                &volumeState,
4964
                sizeof(volumeState),
4965
                NULL,
4966
                NULL
4967
            )) {
4968
                err = GetLastError();
4969
            }
4970
            CloseHandle(hVolume);
4971
            if (err == ERROR_INVALID_PARAMETER) {
4972
                /* not supported on this platform */
4973
                r = Py_False;
4974
            } else if (!err) {
4975
                r = (volumeState.VolumeFlags & PERSISTENT_VOLUME_STATE_DEV_VOLUME)
4976
                    ? Py_True : Py_False;
4977
            }
4978
        }
4979
    }
4980
    Py_END_ALLOW_THREADS
4981
4982
    if (err) {
4983
        PyErr_SetFromWindowsErr(err);
4984
        return NULL;
4985
    }
4986
4987
    if (r) {
4988
        return Py_NewRef(r);
4989
    }
4990
4991
    return NULL;
4992
}
4993
4994
4995
int
4996
_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
4997
{
4998
    wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
4999
    DWORD result;
5000
5001
    result = GetFullPathNameW(path,
5002
                              Py_ARRAY_LENGTH(woutbuf), woutbuf,
5003
                              NULL);
5004
    if (!result) {
5005
        return -1;
5006
    }
5007
5008
    if (result >= Py_ARRAY_LENGTH(woutbuf)) {
5009
        if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
5010
            woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
5011
        }
5012
        else {
5013
            woutbufp = NULL;
5014
        }
5015
        if (!woutbufp) {
5016
            *abspath_p = NULL;
5017
            return 0;
5018
        }
5019
5020
        result = GetFullPathNameW(path, result, woutbufp, NULL);
5021
        if (!result) {
5022
            PyMem_RawFree(woutbufp);
5023
            return -1;
5024
        }
5025
    }
5026
5027
    if (woutbufp != woutbuf) {
5028
        *abspath_p = woutbufp;
5029
        return 0;
5030
    }
5031
5032
    *abspath_p = _PyMem_RawWcsdup(woutbufp);
5033
    return 0;
5034
}
5035
5036
5037
/* A helper function for abspath on win32 */
5038
/*[clinic input]
5039
os._getfullpathname
5040
5041
    path: path_t
5042
    /
5043
5044
[clinic start generated code]*/
5045
5046
static PyObject *
5047
os__getfullpathname_impl(PyObject *module, path_t *path)
5048
/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
5049
{
5050
    wchar_t *abspath;
5051
5052
    if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
5053
        return win32_error_object("GetFullPathNameW", path->object);
5054
    }
5055
    if (abspath == NULL) {
5056
        return PyErr_NoMemory();
5057
    }
5058
5059
    PyObject *str = PyUnicode_FromWideChar(abspath, -1);
5060
    PyMem_RawFree(abspath);
5061
    if (str == NULL) {
5062
        return NULL;
5063
    }
5064
    if (PyBytes_Check(path->object)) {
5065
        Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
5066
    }
5067
    return str;
5068
}
5069
5070
5071
/*[clinic input]
5072
os._getfinalpathname
5073
5074
    path: path_t
5075
    /
5076
5077
A helper function for samepath on windows.
5078
[clinic start generated code]*/
5079
5080
static PyObject *
5081
os__getfinalpathname_impl(PyObject *module, path_t *path)
5082
/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
5083
{
5084
    HANDLE hFile;
5085
    wchar_t buf[MAXPATHLEN], *target_path = buf;
5086
    int buf_size = Py_ARRAY_LENGTH(buf);
5087
    int result_length;
5088
    PyObject *result;
5089
5090
    Py_BEGIN_ALLOW_THREADS
5091
    hFile = CreateFileW(
5092
        path->wide,
5093
        0, /* desired access */
5094
        0, /* share mode */
5095
        NULL, /* security attributes */
5096
        OPEN_EXISTING,
5097
        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
5098
        FILE_FLAG_BACKUP_SEMANTICS,
5099
        NULL);
5100
    Py_END_ALLOW_THREADS
5101
5102
    if (hFile == INVALID_HANDLE_VALUE) {
5103
        return win32_error_object("CreateFileW", path->object);
5104
    }
5105
5106
    /* We have a good handle to the target, use it to determine the
5107
       target path name. */
5108
    while (1) {
5109
        Py_BEGIN_ALLOW_THREADS
5110
        result_length = GetFinalPathNameByHandleW(hFile, target_path,
5111
                                                  buf_size, VOLUME_NAME_DOS);
5112
        Py_END_ALLOW_THREADS
5113
5114
        if (!result_length) {
5115
            result = win32_error_object("GetFinalPathNameByHandleW",
5116
                                         path->object);
5117
            goto cleanup;
5118
        }
5119
5120
        if (result_length < buf_size) {
5121
            break;
5122
        }
5123
5124
        wchar_t *tmp;
5125
        tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
5126
                            result_length * sizeof(*tmp));
5127
        if (!tmp) {
5128
            result = PyErr_NoMemory();
5129
            goto cleanup;
5130
        }
5131
5132
        buf_size = result_length;
5133
        target_path = tmp;
5134
    }
5135
5136
    result = PyUnicode_FromWideChar(target_path, result_length);
5137
    if (result && PyBytes_Check(path->object)) {
5138
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5139
    }
5140
5141
cleanup:
5142
    if (target_path != buf) {
5143
        PyMem_Free(target_path);
5144
    }
5145
    CloseHandle(hFile);
5146
    return result;
5147
}
5148
5149
/*[clinic input]
5150
os._findfirstfile
5151
    path: path_t
5152
    /
5153
A function to get the real file name without accessing the file in Windows.
5154
[clinic start generated code]*/
5155
5156
static PyObject *
5157
os__findfirstfile_impl(PyObject *module, path_t *path)
5158
/*[clinic end generated code: output=106dd3f0779c83dd input=0734dff70f60e1a8]*/
5159
{
5160
    PyObject *result;
5161
    HANDLE hFindFile;
5162
    WIN32_FIND_DATAW wFileData;
5163
    WCHAR *wRealFileName;
5164
5165
    Py_BEGIN_ALLOW_THREADS
5166
    hFindFile = FindFirstFileW(path->wide, &wFileData);
5167
    Py_END_ALLOW_THREADS
5168
5169
    if (hFindFile == INVALID_HANDLE_VALUE) {
5170
        path_error(path);
5171
        return NULL;
5172
    }
5173
5174
    wRealFileName = wFileData.cFileName;
5175
    result = PyUnicode_FromWideChar(wRealFileName, -1);
5176
    FindClose(hFindFile);
5177
    return result;
5178
}
5179
5180
5181
/*[clinic input]
5182
os._getvolumepathname
5183
5184
    path: path_t
5185
5186
A helper function for ismount on Win32.
5187
[clinic start generated code]*/
5188
5189
static PyObject *
5190
os__getvolumepathname_impl(PyObject *module, path_t *path)
5191
/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
5192
{
5193
    PyObject *result;
5194
    wchar_t *mountpath=NULL;
5195
    size_t buflen;
5196
    BOOL ret;
5197
5198
    /* Volume path should be shorter than entire path */
5199
    buflen = Py_MAX(path->length, MAX_PATH);
5200
5201
    if (buflen > PY_DWORD_MAX) {
5202
        PyErr_SetString(PyExc_OverflowError, "path too long");
5203
        return NULL;
5204
    }
5205
5206
    mountpath = PyMem_New(wchar_t, buflen);
5207
    if (mountpath == NULL)
5208
        return PyErr_NoMemory();
5209
5210
    Py_BEGIN_ALLOW_THREADS
5211
    ret = GetVolumePathNameW(path->wide, mountpath,
5212
                             Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
5213
    Py_END_ALLOW_THREADS
5214
5215
    if (!ret) {
5216
        result = win32_error_object("_getvolumepathname", path->object);
5217
        goto exit;
5218
    }
5219
    result = PyUnicode_FromWideChar(mountpath, -1);
5220
    if (PyBytes_Check(path->object))
5221
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5222
5223
exit:
5224
    PyMem_Free(mountpath);
5225
    return result;
5226
}
5227
5228
5229
/*[clinic input]
5230
os._path_splitroot
5231
5232
    path: path_t,
5233
    /
5234
5235
Removes everything after the root on Win32.
5236
[clinic start generated code]*/
5237
5238
static PyObject *
5239
os__path_splitroot_impl(PyObject *module, path_t *path)
5240
/*[clinic end generated code: output=ab7f1a88b654581c input=42831e41f8458f6d]*/
5241
{
5242
    wchar_t *buffer;
5243
    wchar_t *end;
5244
    PyObject *result = NULL;
5245
    HRESULT ret;
5246
5247
    buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
5248
    if (!buffer) {
5249
        return NULL;
5250
    }
5251
    wcscpy(buffer, path->wide);
5252
    for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
5253
        *p = L'\\';
5254
    }
5255
5256
    Py_BEGIN_ALLOW_THREADS
5257
    ret = PathCchSkipRoot(buffer, &end);
5258
    Py_END_ALLOW_THREADS
5259
    if (FAILED(ret)) {
5260
        result = Py_BuildValue("sO", "", path->object);
5261
    } else if (end != buffer) {
5262
        size_t rootLen = (size_t)(end - buffer);
5263
        result = Py_BuildValue("NN",
5264
            PyUnicode_FromWideChar(path->wide, rootLen),
5265
            PyUnicode_FromWideChar(path->wide + rootLen, -1)
5266
        );
5267
    } else {
5268
        result = Py_BuildValue("Os", path->object, "");
5269
    }
5270
    PyMem_Free(buffer);
5271
5272
    return result;
5273
}
5274
5275
5276
#define PY_IFREG  1 // Regular file
5277
#define PY_IFDIR  2 // Directory
5278
#define PY_IFLNK  4 // Symlink
5279
#define PY_IFMNT  8 // Mount Point (junction)
5280
#define PY_IFLRP 16 // Link Reparse Point (name-surrogate, symlink, junction)
5281
#define PY_IFRRP 32 // Regular Reparse Point
5282
5283
static inline BOOL
5284
_testInfo(DWORD attributes, DWORD reparseTag, BOOL diskDevice, int testedType)
5285
{
5286
    switch (testedType) {
5287
    case PY_IFREG:
5288
        return diskDevice && attributes &&
5289
               !(attributes & FILE_ATTRIBUTE_DIRECTORY);
5290
    case PY_IFDIR:
5291
        return attributes & FILE_ATTRIBUTE_DIRECTORY;
5292
    case PY_IFLNK:
5293
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5294
               reparseTag == IO_REPARSE_TAG_SYMLINK;
5295
    case PY_IFMNT:
5296
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5297
               reparseTag == IO_REPARSE_TAG_MOUNT_POINT;
5298
    case PY_IFLRP:
5299
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5300
               IsReparseTagNameSurrogate(reparseTag);
5301
    case PY_IFRRP:
5302
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5303
               reparseTag && !IsReparseTagNameSurrogate(reparseTag);
5304
    }
5305
5306
    return FALSE;
5307
}
5308
5309
static BOOL
5310
_testFileTypeByHandle(HANDLE hfile, int testedType, BOOL diskOnly)
5311
{
5312
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5313
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5314
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5315
5316
    BOOL diskDevice = GetFileType(hfile) == FILE_TYPE_DISK;
5317
    if (diskOnly && !diskDevice) {
5318
        return FALSE;
5319
    }
5320
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5321
        FILE_ATTRIBUTE_TAG_INFO info;
5322
        return GetFileInformationByHandleEx(hfile, FileAttributeTagInfo, &info,
5323
                                            sizeof(info)) &&
5324
               _testInfo(info.FileAttributes, info.ReparseTag, diskDevice,
5325
                         testedType);
5326
    }
5327
    FILE_BASIC_INFO info;
5328
    return GetFileInformationByHandleEx(hfile, FileBasicInfo, &info,
5329
                                        sizeof(info)) &&
5330
           _testInfo(info.FileAttributes, 0, diskDevice, testedType);
5331
}
5332
5333
static BOOL
5334
_testFileTypeByName(LPCWSTR path, int testedType)
5335
{
5336
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5337
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5338
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5339
5340
    FILE_STAT_BASIC_INFORMATION info;
5341
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5342
                                     sizeof(info)))
5343
    {
5344
        BOOL diskDevice = info.DeviceType == FILE_DEVICE_DISK ||
5345
                          info.DeviceType == FILE_DEVICE_VIRTUAL_DISK ||
5346
                          info.DeviceType == FILE_DEVICE_CD_ROM;
5347
        BOOL result = _testInfo(info.FileAttributes, info.ReparseTag,
5348
                                diskDevice, testedType);
5349
        if (!result || (testedType != PY_IFREG && testedType != PY_IFDIR) ||
5350
            !(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
5351
        {
5352
            return result;
5353
        }
5354
    }
5355
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5356
                GetLastError()))
5357
    {
5358
        return FALSE;
5359
    }
5360
5361
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5362
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5363
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5364
    }
5365
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5366
                               OPEN_EXISTING, flags, NULL);
5367
    if (hfile != INVALID_HANDLE_VALUE) {
5368
        BOOL result = _testFileTypeByHandle(hfile, testedType, FALSE);
5369
        CloseHandle(hfile);
5370
        return result;
5371
    }
5372
5373
    switch (GetLastError()) {
5374
    case ERROR_ACCESS_DENIED:
5375
    case ERROR_SHARING_VIOLATION:
5376
    case ERROR_CANT_ACCESS_FILE:
5377
    case ERROR_INVALID_PARAMETER:
5378
        int rc;
5379
        STRUCT_STAT st;
5380
        if (testedType == PY_IFREG || testedType == PY_IFDIR) {
5381
            rc = STAT(path, &st);
5382
        }
5383
        else {
5384
            // PY_IFRRP is not generally supported in this case, except for
5385
            // unhandled reparse points such as IO_REPARSE_TAG_APPEXECLINK.
5386
            rc = LSTAT(path, &st);
5387
        }
5388
        if (!rc) {
5389
            return _testInfo(st.st_file_attributes, st.st_reparse_tag,
5390
                             st.st_mode & S_IFREG, testedType);
5391
        }
5392
    }
5393
5394
    return FALSE;
5395
}
5396
5397
5398
static BOOL
5399
_testFileExistsByName(LPCWSTR path, BOOL followLinks)
5400
{
5401
    FILE_STAT_BASIC_INFORMATION info;
5402
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5403
                                     sizeof(info)))
5404
    {
5405
        if (!(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ||
5406
            (!followLinks && IsReparseTagNameSurrogate(info.ReparseTag)))
5407
        {
5408
            return TRUE;
5409
        }
5410
    }
5411
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5412
                    GetLastError()))
5413
    {
5414
        return FALSE;
5415
    }
5416
5417
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5418
    if (!followLinks) {
5419
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5420
    }
5421
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5422
                               OPEN_EXISTING, flags, NULL);
5423
    if (hfile != INVALID_HANDLE_VALUE) {
5424
        if (followLinks) {
5425
            CloseHandle(hfile);
5426
            return TRUE;
5427
        }
5428
        // Regular Reparse Points (PY_IFRRP) have to be traversed.
5429
        BOOL result = _testFileTypeByHandle(hfile, PY_IFRRP, FALSE);
5430
        CloseHandle(hfile);
5431
        if (!result) {
5432
            return TRUE;
5433
        }
5434
        hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
5435
                            FILE_FLAG_BACKUP_SEMANTICS, NULL);
5436
        if (hfile != INVALID_HANDLE_VALUE) {
5437
            CloseHandle(hfile);
5438
            return TRUE;
5439
        }
5440
    }
5441
5442
    switch (GetLastError()) {
5443
    case ERROR_ACCESS_DENIED:
5444
    case ERROR_SHARING_VIOLATION:
5445
    case ERROR_CANT_ACCESS_FILE:
5446
    case ERROR_INVALID_PARAMETER:
5447
        STRUCT_STAT _st;
5448
        return followLinks ? !STAT(path, &_st): !LSTAT(path, &_st);
5449
    }
5450
5451
    return FALSE;
5452
}
5453
5454
5455
static BOOL
5456
_testFileExists(path_t *path, BOOL followLinks)
5457
{
5458
    BOOL result = FALSE;
5459
    if (path->value_error) {
5460
        return FALSE;
5461
    }
5462
5463
    Py_BEGIN_ALLOW_THREADS
5464
    if (path->fd != -1) {
5465
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5466
        if (hfile != INVALID_HANDLE_VALUE) {
5467
            if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) {
5468
                result = TRUE;
5469
            }
5470
        }
5471
    }
5472
    else if (path->wide) {
5473
        result = _testFileExistsByName(path->wide, followLinks);
5474
    }
5475
    Py_END_ALLOW_THREADS
5476
5477
    return result;
5478
}
5479
5480
5481
static BOOL
5482
_testFileType(path_t *path, int testedType)
5483
{
5484
    BOOL result = FALSE;
5485
    if (path->value_error) {
5486
        return FALSE;
5487
    }
5488
5489
    Py_BEGIN_ALLOW_THREADS
5490
    if (path->fd != -1) {
5491
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5492
        if (hfile != INVALID_HANDLE_VALUE) {
5493
            result = _testFileTypeByHandle(hfile, testedType, TRUE);
5494
        }
5495
    }
5496
    else if (path->wide) {
5497
        result = _testFileTypeByName(path->wide, testedType);
5498
    }
5499
    Py_END_ALLOW_THREADS
5500
5501
    return result;
5502
}
5503
5504
5505
/*[clinic input]
5506
os._path_exists -> bool
5507
5508
    path: path_t(allow_fd=True, suppress_value_error=True)
5509
5510
Test whether a path exists.  Returns False for broken symbolic links.
5511
5512
[clinic start generated code]*/
5513
5514
static int
5515
os__path_exists_impl(PyObject *module, path_t *path)
5516
/*[clinic end generated code: output=8da13acf666e16ba input=142beabfc66783eb]*/
5517
{
5518
    return _testFileExists(path, TRUE);
5519
}
5520
5521
5522
/*[clinic input]
5523
os._path_lexists -> bool
5524
5525
    path: path_t(allow_fd=True, suppress_value_error=True)
5526
5527
Test whether a path exists.  Returns True for broken symbolic links.
5528
5529
[clinic start generated code]*/
5530
5531
static int
5532
os__path_lexists_impl(PyObject *module, path_t *path)
5533
/*[clinic end generated code: output=e7240ed5fc45bff3 input=208205112a3cc1ed]*/
5534
{
5535
    return _testFileExists(path, FALSE);
5536
}
5537
5538
5539
/*[clinic input]
5540
os._path_isdir -> bool
5541
5542
    path: path_t(allow_fd=True, suppress_value_error=True),
5543
    /
5544
5545
Return true if the pathname refers to an existing directory.
5546
5547
[clinic start generated code]*/
5548
5549
static int
5550
os__path_isdir_impl(PyObject *module, path_t *path)
5551
/*[clinic end generated code: output=d5786196f9e2fa7a input=0d3fd790564d244b]*/
5552
{
5553
    return _testFileType(path, PY_IFDIR);
5554
}
5555
5556
5557
/*[clinic input]
5558
os._path_isfile -> bool
5559
5560
    path: path_t(allow_fd=True, suppress_value_error=True)
5561
5562
Test whether a path is a regular file
5563
5564
[clinic start generated code]*/
5565
5566
static int
5567
os__path_isfile_impl(PyObject *module, path_t *path)
5568
/*[clinic end generated code: output=5c3073bc212b9863 input=4ac1fd350b30a39e]*/
5569
{
5570
    return _testFileType(path, PY_IFREG);
5571
}
5572
5573
5574
/*[clinic input]
5575
os._path_islink -> bool
5576
5577
    path: path_t(allow_fd=True, suppress_value_error=True)
5578
5579
Test whether a path is a symbolic link
5580
5581
[clinic start generated code]*/
5582
5583
static int
5584
os__path_islink_impl(PyObject *module, path_t *path)
5585
/*[clinic end generated code: output=30da7bda8296adcc input=7510ce05b547debb]*/
5586
{
5587
    return _testFileType(path, PY_IFLNK);
5588
}
5589
5590
5591
/*[clinic input]
5592
os._path_isjunction -> bool
5593
5594
    path: path_t(allow_fd=True, suppress_value_error=True)
5595
5596
Test whether a path is a junction
5597
5598
[clinic start generated code]*/
5599
5600
static int
5601
os__path_isjunction_impl(PyObject *module, path_t *path)
5602
/*[clinic end generated code: output=e1d17a9dd18a9945 input=7dcb8bc4e972fcaf]*/
5603
{
5604
    return _testFileType(path, PY_IFMNT);
5605
}
5606
5607
#undef PY_IFREG
5608
#undef PY_IFDIR
5609
#undef PY_IFLNK
5610
#undef PY_IFMNT
5611
#undef PY_IFLRP
5612
#undef PY_IFRRP
5613
5614
#endif /* MS_WINDOWS */
5615
5616
5617
/*[clinic input]
5618
os._path_splitroot_ex
5619
5620
    path: path_t(make_wide=True, nonstrict=True),
5621
    /
5622
5623
Split a pathname into drive, root and tail.
5624
5625
The tail contains anything after the root.
5626
[clinic start generated code]*/
5627
5628
static PyObject *
5629
os__path_splitroot_ex_impl(PyObject *module, path_t *path)
5630
/*[clinic end generated code: output=4b0072b6cdf4b611 input=4ac47b394d68bd21]*/
5631
0
{
5632
0
    Py_ssize_t drvsize, rootsize;
5633
0
    PyObject *drv = NULL, *root = NULL, *tail = NULL, *result = NULL;
5634
5635
0
    const wchar_t *buffer = path->wide;
5636
0
    _Py_skiproot(buffer, path->length, &drvsize, &rootsize);
5637
0
    drv = PyUnicode_FromWideChar(buffer, drvsize);
5638
0
    if (drv == NULL) {
5639
0
        goto exit;
5640
0
    }
5641
0
    root = PyUnicode_FromWideChar(&buffer[drvsize], rootsize);
5642
0
    if (root == NULL) {
5643
0
        goto exit;
5644
0
    }
5645
0
    tail = PyUnicode_FromWideChar(&buffer[drvsize + rootsize],
5646
0
                                  path->length - drvsize - rootsize);
5647
0
    if (tail == NULL) {
5648
0
        goto exit;
5649
0
    }
5650
0
    if (PyBytes_Check(path->object)) {
5651
0
        Py_SETREF(drv, PyUnicode_EncodeFSDefault(drv));
5652
0
        if (drv == NULL) {
5653
0
            goto exit;
5654
0
        }
5655
0
        Py_SETREF(root, PyUnicode_EncodeFSDefault(root));
5656
0
        if (root == NULL) {
5657
0
            goto exit;
5658
0
        }
5659
0
        Py_SETREF(tail, PyUnicode_EncodeFSDefault(tail));
5660
0
        if (tail == NULL) {
5661
0
            goto exit;
5662
0
        }
5663
0
    }
5664
0
    result = PyTuple_Pack(3, drv, root, tail);
5665
0
exit:
5666
0
    Py_XDECREF(drv);
5667
0
    Py_XDECREF(root);
5668
0
    Py_XDECREF(tail);
5669
0
    return result;
5670
0
}
5671
5672
5673
/*[clinic input]
5674
os._path_normpath
5675
5676
    path: path_t(make_wide=True, nonstrict=True)
5677
5678
Normalize path, eliminating double slashes, etc.
5679
[clinic start generated code]*/
5680
5681
static PyObject *
5682
os__path_normpath_impl(PyObject *module, path_t *path)
5683
/*[clinic end generated code: output=d353e7ed9410c044 input=3d4ac23b06332dcb]*/
5684
110
{
5685
110
    PyObject *result;
5686
110
    Py_ssize_t norm_len;
5687
110
    wchar_t *norm_path = _Py_normpath_and_size((wchar_t *)path->wide,
5688
110
                                               path->length, &norm_len);
5689
110
    if (!norm_len) {
5690
0
        result = PyUnicode_FromOrdinal('.');
5691
0
    }
5692
110
    else {
5693
110
        result = PyUnicode_FromWideChar(norm_path, norm_len);
5694
110
    }
5695
110
    if (PyBytes_Check(path->object)) {
5696
0
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5697
0
    }
5698
110
    return result;
5699
110
}
5700
5701
/*[clinic input]
5702
os.mkdir
5703
5704
    path : path_t
5705
5706
    mode: int = 0o777
5707
5708
    *
5709
5710
    dir_fd : dir_fd(requires='mkdirat') = None
5711
5712
# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
5713
5714
Create a directory.
5715
5716
If dir_fd is not None, it should be a file descriptor open to a directory,
5717
  and path should be relative; path will then be relative to that directory.
5718
dir_fd may not be implemented on your platform.
5719
  If it is unavailable, using it will raise a NotImplementedError.
5720
5721
The mode argument is ignored on Windows. Where it is used, the current umask
5722
value is first masked out.
5723
[clinic start generated code]*/
5724
5725
static PyObject *
5726
os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
5727
/*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
5728
0
{
5729
0
    int result;
5730
#ifdef MS_WINDOWS
5731
    int error = 0;
5732
    SECURITY_ATTRIBUTES secAttr = { sizeof(secAttr) };
5733
    SECURITY_ATTRIBUTES *pSecAttr = NULL;
5734
#endif
5735
0
#ifdef HAVE_MKDIRAT
5736
0
    int mkdirat_unavailable = 0;
5737
0
#endif
5738
5739
0
    if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
5740
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5741
0
        return NULL;
5742
0
    }
5743
5744
#ifdef MS_WINDOWS
5745
    Py_BEGIN_ALLOW_THREADS
5746
    // For API sets that don't support these APIs, we have no choice
5747
    // but to silently create a directory with default ACL.
5748
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
5749
    if (mode == 0700 /* 0o700 */) {
5750
        ULONG sdSize;
5751
        pSecAttr = &secAttr;
5752
        // Set a discretionary ACL (D) that is protected (P) and includes
5753
        // inheritable (OICI) entries that allow (A) full control (FA) to
5754
        // SYSTEM (SY), Administrators (BA), and the owner (OW).
5755
        if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
5756
            L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)",
5757
            SDDL_REVISION_1,
5758
            &secAttr.lpSecurityDescriptor,
5759
            &sdSize
5760
        )) {
5761
            error = GetLastError();
5762
        }
5763
    }
5764
#endif
5765
    if (!error) {
5766
        result = CreateDirectoryW(path->wide, pSecAttr);
5767
        if (secAttr.lpSecurityDescriptor &&
5768
            // uncommonly, LocalFree returns non-zero on error, but still uses
5769
            // GetLastError() to see what the error code is
5770
            LocalFree(secAttr.lpSecurityDescriptor)) {
5771
            error = GetLastError();
5772
        }
5773
    }
5774
    Py_END_ALLOW_THREADS
5775
5776
    if (error) {
5777
        return PyErr_SetFromWindowsErr(error);
5778
    }
5779
    if (!result) {
5780
        return path_error(path);
5781
    }
5782
#else
5783
0
    Py_BEGIN_ALLOW_THREADS
5784
0
#if HAVE_MKDIRAT
5785
0
    if (dir_fd != DEFAULT_DIR_FD) {
5786
0
      if (HAVE_MKDIRAT_RUNTIME) {
5787
0
        result = mkdirat(dir_fd, path->narrow, mode);
5788
5789
0
      } else {
5790
0
        mkdirat_unavailable = 1;
5791
0
      }
5792
0
    } else
5793
0
#endif
5794
#if defined(__WATCOMC__) && !defined(__QNX__)
5795
        result = mkdir(path->narrow);
5796
#else
5797
0
        result = mkdir(path->narrow, mode);
5798
0
#endif
5799
0
    Py_END_ALLOW_THREADS
5800
5801
0
#if HAVE_MKDIRAT
5802
0
    if (mkdirat_unavailable) {
5803
0
        argument_unavailable_error(NULL, "dir_fd");
5804
0
        return NULL;
5805
0
    }
5806
0
#endif
5807
5808
0
    if (result < 0)
5809
0
        return path_error(path);
5810
0
#endif /* MS_WINDOWS */
5811
0
    Py_RETURN_NONE;
5812
0
}
5813
5814
5815
/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
5816
#if defined(HAVE_SYS_RESOURCE_H)
5817
#include <sys/resource.h>
5818
#endif
5819
5820
5821
#ifdef HAVE_NICE
5822
/*[clinic input]
5823
os.nice
5824
5825
    increment: int
5826
    /
5827
5828
Add increment to the priority of process and return the new priority.
5829
[clinic start generated code]*/
5830
5831
static PyObject *
5832
os_nice_impl(PyObject *module, int increment)
5833
/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
5834
0
{
5835
0
    int value;
5836
5837
    /* There are two flavours of 'nice': one that returns the new
5838
       priority (as required by almost all standards out there) and the
5839
       Linux/FreeBSD one, which returns '0' on success and advices
5840
       the use of getpriority() to get the new priority.
5841
5842
       If we are of the nice family that returns the new priority, we
5843
       need to clear errno before the call, and check if errno is filled
5844
       before calling posix_error() on a returnvalue of -1, because the
5845
       -1 may be the actual new priority! */
5846
5847
0
    errno = 0;
5848
0
    value = nice(increment);
5849
#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
5850
    if (value == 0)
5851
        value = getpriority(PRIO_PROCESS, 0);
5852
#endif
5853
0
    if (value == -1 && errno != 0)
5854
        /* either nice() or getpriority() returned an error */
5855
0
        return posix_error();
5856
0
    return PyLong_FromLong((long) value);
5857
0
}
5858
#endif /* HAVE_NICE */
5859
5860
5861
#ifdef HAVE_GETPRIORITY
5862
/*[clinic input]
5863
os.getpriority
5864
5865
    which: int
5866
    who: int
5867
5868
Return program scheduling priority.
5869
[clinic start generated code]*/
5870
5871
static PyObject *
5872
os_getpriority_impl(PyObject *module, int which, int who)
5873
/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
5874
0
{
5875
0
    int retval;
5876
5877
0
    errno = 0;
5878
0
    retval = getpriority(which, who);
5879
0
    if (errno != 0)
5880
0
        return posix_error();
5881
0
    return PyLong_FromLong((long)retval);
5882
0
}
5883
#endif /* HAVE_GETPRIORITY */
5884
5885
5886
#ifdef HAVE_SETPRIORITY
5887
/*[clinic input]
5888
os.setpriority
5889
5890
    which: int
5891
    who: int
5892
    priority: int
5893
5894
Set program scheduling priority.
5895
[clinic start generated code]*/
5896
5897
static PyObject *
5898
os_setpriority_impl(PyObject *module, int which, int who, int priority)
5899
/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
5900
0
{
5901
0
    int retval;
5902
5903
0
    retval = setpriority(which, who, priority);
5904
0
    if (retval == -1)
5905
0
        return posix_error();
5906
0
    Py_RETURN_NONE;
5907
0
}
5908
#endif /* HAVE_SETPRIORITY */
5909
5910
5911
static PyObject *
5912
internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
5913
0
{
5914
0
    const char *function_name = is_replace ? "replace" : "rename";
5915
0
    int dir_fd_specified;
5916
5917
0
#ifdef HAVE_RENAMEAT
5918
0
    int renameat_unavailable = 0;
5919
0
#endif
5920
5921
#ifdef MS_WINDOWS
5922
    BOOL result;
5923
    int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
5924
#else
5925
0
    int result;
5926
0
#endif
5927
5928
0
    dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
5929
0
                       (dst_dir_fd != DEFAULT_DIR_FD);
5930
#ifndef HAVE_RENAMEAT
5931
    if (dir_fd_specified) {
5932
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
5933
        return NULL;
5934
    }
5935
#endif
5936
5937
0
    if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
5938
0
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
5939
0
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
5940
0
        return NULL;
5941
0
    }
5942
5943
#ifdef MS_WINDOWS
5944
    Py_BEGIN_ALLOW_THREADS
5945
    result = MoveFileExW(src->wide, dst->wide, flags);
5946
    Py_END_ALLOW_THREADS
5947
5948
    if (!result)
5949
        return path_error2(src, dst);
5950
5951
#else
5952
0
    Py_BEGIN_ALLOW_THREADS
5953
0
#ifdef HAVE_RENAMEAT
5954
0
    if (dir_fd_specified) {
5955
0
        if (HAVE_RENAMEAT_RUNTIME) {
5956
0
            result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
5957
0
        } else {
5958
0
            renameat_unavailable = 1;
5959
0
        }
5960
0
    } else
5961
0
#endif
5962
0
    result = rename(src->narrow, dst->narrow);
5963
0
    Py_END_ALLOW_THREADS
5964
5965
5966
0
#ifdef HAVE_RENAMEAT
5967
0
    if (renameat_unavailable) {
5968
0
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
5969
0
        return NULL;
5970
0
    }
5971
0
#endif
5972
5973
0
    if (result)
5974
0
        return path_error2(src, dst);
5975
0
#endif
5976
0
    Py_RETURN_NONE;
5977
0
}
5978
5979
5980
/*[clinic input]
5981
@permit_long_docstring_body
5982
os.rename
5983
5984
    src : path_t
5985
    dst : path_t
5986
    *
5987
    src_dir_fd : dir_fd = None
5988
    dst_dir_fd : dir_fd = None
5989
5990
Rename a file or directory.
5991
5992
If either src_dir_fd or dst_dir_fd is not None, it should be a file
5993
  descriptor open to a directory, and the respective path string (src or dst)
5994
  should be relative; the path will then be relative to that directory.
5995
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
5996
  If they are unavailable, using them will raise a NotImplementedError.
5997
[clinic start generated code]*/
5998
5999
static PyObject *
6000
os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6001
               int dst_dir_fd)
6002
/*[clinic end generated code: output=59e803072cf41230 input=11aae8c091162766]*/
6003
0
{
6004
0
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
6005
0
}
6006
6007
6008
/*[clinic input]
6009
@permit_long_docstring_body
6010
os.replace = os.rename
6011
6012
Rename a file or directory, overwriting the destination.
6013
6014
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6015
  descriptor open to a directory, and the respective path string (src or dst)
6016
  should be relative; the path will then be relative to that directory.
6017
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6018
  If they are unavailable, using them will raise a NotImplementedError.
6019
[clinic start generated code]*/
6020
6021
static PyObject *
6022
os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6023
                int dst_dir_fd)
6024
/*[clinic end generated code: output=1968c02e7857422b input=78d6c8087e90994c]*/
6025
0
{
6026
0
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
6027
0
}
6028
6029
6030
/*[clinic input]
6031
os.rmdir
6032
6033
    path: path_t
6034
    *
6035
    dir_fd: dir_fd(requires='unlinkat') = None
6036
6037
Remove a directory.
6038
6039
If dir_fd is not None, it should be a file descriptor open to a directory,
6040
  and path should be relative; path will then be relative to that directory.
6041
dir_fd may not be implemented on your platform.
6042
  If it is unavailable, using it will raise a NotImplementedError.
6043
[clinic start generated code]*/
6044
6045
static PyObject *
6046
os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
6047
/*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
6048
0
{
6049
0
    int result;
6050
0
#ifdef HAVE_UNLINKAT
6051
0
    int unlinkat_unavailable = 0;
6052
0
#endif
6053
6054
0
    if (PySys_Audit("os.rmdir", "Oi", path->object,
6055
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6056
0
        return NULL;
6057
0
    }
6058
6059
0
    Py_BEGIN_ALLOW_THREADS
6060
#ifdef MS_WINDOWS
6061
    /* Windows, success=1, UNIX, success=0 */
6062
    result = !RemoveDirectoryW(path->wide);
6063
#else
6064
0
#ifdef HAVE_UNLINKAT
6065
0
    if (dir_fd != DEFAULT_DIR_FD) {
6066
0
      if (HAVE_UNLINKAT_RUNTIME) {
6067
0
        result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
6068
0
      } else {
6069
0
        unlinkat_unavailable = 1;
6070
0
        result = -1;
6071
0
      }
6072
0
    } else
6073
0
#endif
6074
0
        result = rmdir(path->narrow);
6075
0
#endif
6076
0
    Py_END_ALLOW_THREADS
6077
6078
0
#ifdef HAVE_UNLINKAT
6079
0
    if (unlinkat_unavailable) {
6080
0
        argument_unavailable_error("rmdir", "dir_fd");
6081
0
        return NULL;
6082
0
    }
6083
0
#endif
6084
6085
0
    if (result)
6086
0
        return path_error(path);
6087
6088
0
    Py_RETURN_NONE;
6089
0
}
6090
6091
6092
#ifdef HAVE_SYSTEM
6093
#ifdef MS_WINDOWS
6094
/*[clinic input]
6095
os.system -> long
6096
6097
    command: Py_UNICODE
6098
6099
Execute the command in a subshell.
6100
[clinic start generated code]*/
6101
6102
static long
6103
os_system_impl(PyObject *module, const wchar_t *command)
6104
/*[clinic end generated code: output=dd528cbd5943a679 input=303f5ce97df606b0]*/
6105
{
6106
    long result;
6107
6108
    if (PySys_Audit("os.system", "(u)", command) < 0) {
6109
        return -1;
6110
    }
6111
6112
    Py_BEGIN_ALLOW_THREADS
6113
    _Py_BEGIN_SUPPRESS_IPH
6114
    result = _wsystem(command);
6115
    _Py_END_SUPPRESS_IPH
6116
    Py_END_ALLOW_THREADS
6117
    return result;
6118
}
6119
#else /* MS_WINDOWS */
6120
/*[clinic input]
6121
os.system -> long
6122
6123
    command: FSConverter
6124
6125
Execute the command in a subshell.
6126
[clinic start generated code]*/
6127
6128
static long
6129
os_system_impl(PyObject *module, PyObject *command)
6130
/*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
6131
0
{
6132
0
    long result;
6133
0
    const char *bytes = PyBytes_AsString(command);
6134
6135
0
    if (PySys_Audit("os.system", "(O)", command) < 0) {
6136
0
        return -1;
6137
0
    }
6138
6139
0
    Py_BEGIN_ALLOW_THREADS
6140
0
    result = system(bytes);
6141
0
    Py_END_ALLOW_THREADS
6142
0
    return result;
6143
0
}
6144
#endif
6145
#endif /* HAVE_SYSTEM */
6146
6147
6148
#ifdef HAVE_UMASK
6149
/*[clinic input]
6150
os.umask
6151
6152
    mask: int
6153
    /
6154
6155
Set the current numeric umask and return the previous umask.
6156
[clinic start generated code]*/
6157
6158
static PyObject *
6159
os_umask_impl(PyObject *module, int mask)
6160
/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
6161
0
{
6162
0
    int i = (int)umask(mask);
6163
0
    if (i < 0)
6164
0
        return posix_error();
6165
0
    return PyLong_FromLong((long)i);
6166
0
}
6167
#endif
6168
6169
#ifdef MS_WINDOWS
6170
6171
/* override the default DeleteFileW behavior so that directory
6172
symlinks can be removed with this function, the same as with
6173
Unix symlinks */
6174
BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
6175
{
6176
    WIN32_FILE_ATTRIBUTE_DATA info;
6177
    WIN32_FIND_DATAW find_data;
6178
    HANDLE find_data_handle;
6179
    int is_directory = 0;
6180
    int is_link = 0;
6181
6182
    if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
6183
        is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
6184
6185
        /* Get WIN32_FIND_DATA structure for the path to determine if
6186
           it is a symlink */
6187
        if(is_directory &&
6188
           info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
6189
            find_data_handle = FindFirstFileW(lpFileName, &find_data);
6190
6191
            if(find_data_handle != INVALID_HANDLE_VALUE) {
6192
                /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
6193
                   IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
6194
                is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
6195
                          find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
6196
                FindClose(find_data_handle);
6197
            }
6198
        }
6199
    }
6200
6201
    if (is_directory && is_link)
6202
        return RemoveDirectoryW(lpFileName);
6203
6204
    return DeleteFileW(lpFileName);
6205
}
6206
#endif /* MS_WINDOWS */
6207
6208
6209
/*[clinic input]
6210
os.unlink
6211
6212
    path: path_t
6213
    *
6214
    dir_fd: dir_fd(requires='unlinkat')=None
6215
6216
Remove a file (same as remove()).
6217
6218
If dir_fd is not None, it should be a file descriptor open to a directory,
6219
  and path should be relative; path will then be relative to that directory.
6220
dir_fd may not be implemented on your platform.
6221
  If it is unavailable, using it will raise a NotImplementedError.
6222
6223
[clinic start generated code]*/
6224
6225
static PyObject *
6226
os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
6227
/*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
6228
0
{
6229
0
    int result;
6230
0
#ifdef HAVE_UNLINKAT
6231
0
    int unlinkat_unavailable = 0;
6232
0
#endif
6233
6234
0
    if (PySys_Audit("os.remove", "Oi", path->object,
6235
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6236
0
        return NULL;
6237
0
    }
6238
6239
0
    Py_BEGIN_ALLOW_THREADS
6240
0
    _Py_BEGIN_SUPPRESS_IPH
6241
#ifdef MS_WINDOWS
6242
    /* Windows, success=1, UNIX, success=0 */
6243
    result = !Py_DeleteFileW(path->wide);
6244
#else
6245
0
#ifdef HAVE_UNLINKAT
6246
0
    if (dir_fd != DEFAULT_DIR_FD) {
6247
0
      if (HAVE_UNLINKAT_RUNTIME) {
6248
6249
0
        result = unlinkat(dir_fd, path->narrow, 0);
6250
0
      } else {
6251
0
        unlinkat_unavailable = 1;
6252
0
      }
6253
0
    } else
6254
0
#endif /* HAVE_UNLINKAT */
6255
0
        result = unlink(path->narrow);
6256
0
#endif
6257
0
    _Py_END_SUPPRESS_IPH
6258
0
    Py_END_ALLOW_THREADS
6259
6260
0
#ifdef HAVE_UNLINKAT
6261
0
    if (unlinkat_unavailable) {
6262
0
        argument_unavailable_error(NULL, "dir_fd");
6263
0
        return NULL;
6264
0
    }
6265
0
#endif
6266
6267
0
    if (result)
6268
0
        return path_error(path);
6269
6270
0
    Py_RETURN_NONE;
6271
0
}
6272
6273
6274
/*[clinic input]
6275
os.remove = os.unlink
6276
6277
Remove a file (same as unlink()).
6278
6279
If dir_fd is not None, it should be a file descriptor open to a directory,
6280
  and path should be relative; path will then be relative to that directory.
6281
dir_fd may not be implemented on your platform.
6282
  If it is unavailable, using it will raise a NotImplementedError.
6283
[clinic start generated code]*/
6284
6285
static PyObject *
6286
os_remove_impl(PyObject *module, path_t *path, int dir_fd)
6287
/*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
6288
0
{
6289
0
    return os_unlink_impl(module, path, dir_fd);
6290
0
}
6291
6292
6293
static PyStructSequence_Field uname_result_fields[] = {
6294
    {"sysname",    "operating system name"},
6295
    {"nodename",   "name of machine on network (implementation-defined)"},
6296
    {"release",    "operating system release"},
6297
    {"version",    "operating system version"},
6298
    {"machine",    "hardware identifier"},
6299
    {NULL}
6300
};
6301
6302
PyDoc_STRVAR(uname_result__doc__,
6303
"uname_result: Result from os.uname().\n\n\
6304
This object may be accessed either as a tuple of\n\
6305
  (sysname, nodename, release, version, machine),\n\
6306
or via the attributes sysname, nodename, release, version, and machine.\n\
6307
\n\
6308
See os.uname for more information.");
6309
6310
static PyStructSequence_Desc uname_result_desc = {
6311
    MODNAME ".uname_result", /* name */
6312
    uname_result__doc__, /* doc */
6313
    uname_result_fields,
6314
    5
6315
};
6316
6317
#ifdef HAVE_UNAME
6318
/*[clinic input]
6319
os.uname
6320
6321
Return an object identifying the current operating system.
6322
6323
The object behaves like a named tuple with the following fields:
6324
  (sysname, nodename, release, version, machine)
6325
6326
[clinic start generated code]*/
6327
6328
static PyObject *
6329
os_uname_impl(PyObject *module)
6330
/*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
6331
0
{
6332
0
    struct utsname u;
6333
0
    int res;
6334
0
    PyObject *value;
6335
6336
0
    Py_BEGIN_ALLOW_THREADS
6337
0
    res = uname(&u);
6338
0
    Py_END_ALLOW_THREADS
6339
0
    if (res < 0)
6340
0
        return posix_error();
6341
6342
0
    PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
6343
0
    value = PyStructSequence_New((PyTypeObject *)UnameResultType);
6344
0
    if (value == NULL)
6345
0
        return NULL;
6346
6347
0
#define SET(i, field) \
6348
0
    { \
6349
0
    PyObject *o = PyUnicode_DecodeFSDefault(field); \
6350
0
    if (!o) { \
6351
0
        Py_DECREF(value); \
6352
0
        return NULL; \
6353
0
    } \
6354
0
    PyStructSequence_SET_ITEM(value, i, o); \
6355
0
    } \
6356
0
6357
0
    SET(0, u.sysname);
6358
0
    SET(1, u.nodename);
6359
0
    SET(2, u.release);
6360
0
    SET(3, u.version);
6361
0
    SET(4, u.machine);
6362
6363
0
#undef SET
6364
6365
0
    return value;
6366
0
}
6367
#endif /* HAVE_UNAME */
6368
6369
6370
6371
typedef struct {
6372
    int    now;
6373
    time_t atime_s;
6374
    long   atime_ns;
6375
    time_t mtime_s;
6376
    long   mtime_ns;
6377
} utime_t;
6378
6379
/*
6380
 * these macros assume that "ut" is a pointer to a utime_t
6381
 * they also intentionally leak the declaration of a pointer named "time"
6382
 */
6383
#define UTIME_TO_TIMESPEC \
6384
0
    struct timespec ts[2]; \
6385
0
    struct timespec *time; \
6386
0
    if (ut->now) \
6387
0
        time = NULL; \
6388
0
    else { \
6389
0
        ts[0].tv_sec = ut->atime_s; \
6390
0
        ts[0].tv_nsec = ut->atime_ns; \
6391
0
        ts[1].tv_sec = ut->mtime_s; \
6392
0
        ts[1].tv_nsec = ut->mtime_ns; \
6393
0
        time = ts; \
6394
0
    } \
6395
6396
#define UTIME_TO_TIMEVAL \
6397
0
    struct timeval tv[2]; \
6398
0
    struct timeval *time; \
6399
0
    if (ut->now) \
6400
0
        time = NULL; \
6401
0
    else { \
6402
0
        tv[0].tv_sec = ut->atime_s; \
6403
0
        tv[0].tv_usec = ut->atime_ns / 1000; \
6404
0
        tv[1].tv_sec = ut->mtime_s; \
6405
0
        tv[1].tv_usec = ut->mtime_ns / 1000; \
6406
0
        time = tv; \
6407
0
    } \
6408
6409
#define UTIME_TO_UTIMBUF \
6410
    struct utimbuf u; \
6411
    struct utimbuf *time; \
6412
    if (ut->now) \
6413
        time = NULL; \
6414
    else { \
6415
        u.actime = ut->atime_s; \
6416
        u.modtime = ut->mtime_s; \
6417
        time = &u; \
6418
    }
6419
6420
#define UTIME_TO_TIME_T \
6421
    time_t timet[2]; \
6422
    time_t *time; \
6423
    if (ut->now) \
6424
        time = NULL; \
6425
    else { \
6426
        timet[0] = ut->atime_s; \
6427
        timet[1] = ut->mtime_s; \
6428
        time = timet; \
6429
    } \
6430
6431
6432
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
6433
6434
static int
6435
utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
6436
0
{
6437
#if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
6438
    if (HAVE_UTIMENSAT_RUNTIME) {
6439
        int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6440
        UTIME_TO_TIMESPEC;
6441
        return utimensat(dir_fd, path, time, flags);
6442
    }  else {
6443
        errno = ENOSYS;
6444
        return -1;
6445
    }
6446
#elif defined(HAVE_UTIMENSAT)
6447
0
    int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6448
0
    UTIME_TO_TIMESPEC;
6449
0
    return utimensat(dir_fd, path, time, flags);
6450
#elif defined(HAVE_FUTIMESAT)
6451
    UTIME_TO_TIMEVAL;
6452
    /*
6453
     * follow_symlinks will never be false here;
6454
     * we only allow !follow_symlinks and dir_fd together
6455
     * if we have utimensat()
6456
     */
6457
    assert(follow_symlinks);
6458
    return futimesat(dir_fd, path, time);
6459
#endif
6460
0
}
6461
6462
0
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
6463
#else
6464
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
6465
#endif
6466
6467
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
6468
6469
static int
6470
utime_fd(utime_t *ut, int fd)
6471
0
{
6472
0
#ifdef HAVE_FUTIMENS
6473
6474
0
    if (HAVE_FUTIMENS_RUNTIME) {
6475
6476
0
    UTIME_TO_TIMESPEC;
6477
0
    return futimens(fd, time);
6478
6479
0
    } else
6480
#ifndef HAVE_FUTIMES
6481
    {
6482
        /* Not sure if this can happen */
6483
        PyErr_SetString(
6484
            PyExc_RuntimeError,
6485
            "neither futimens nor futimes are supported"
6486
            " on this system");
6487
        return -1;
6488
    }
6489
#endif
6490
6491
0
#endif
6492
0
#ifdef HAVE_FUTIMES
6493
0
    {
6494
0
    UTIME_TO_TIMEVAL;
6495
0
    return futimes(fd, time);
6496
0
    }
6497
0
#endif
6498
0
}
6499
6500
    #define PATH_UTIME_HAVE_FD 1
6501
#else
6502
    #define PATH_UTIME_HAVE_FD 0
6503
#endif
6504
6505
#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
6506
#  define UTIME_HAVE_NOFOLLOW_SYMLINKS
6507
#endif
6508
6509
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
6510
6511
static int
6512
utime_nofollow_symlinks(utime_t *ut, const char *path)
6513
0
{
6514
0
#ifdef HAVE_UTIMENSAT
6515
0
    if (HAVE_UTIMENSAT_RUNTIME) {
6516
0
        UTIME_TO_TIMESPEC;
6517
0
        return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
6518
0
    } else
6519
#ifndef HAVE_LUTIMES
6520
    {
6521
        /* Not sure if this can happen */
6522
        PyErr_SetString(
6523
            PyExc_RuntimeError,
6524
            "neither utimensat nor lutimes are supported"
6525
            " on this system");
6526
        return -1;
6527
    }
6528
#endif
6529
0
#endif
6530
6531
0
#ifdef HAVE_LUTIMES
6532
0
    {
6533
0
    UTIME_TO_TIMEVAL;
6534
0
    return lutimes(path, time);
6535
0
    }
6536
0
#endif
6537
0
}
6538
6539
#endif
6540
6541
#ifndef MS_WINDOWS
6542
6543
static int
6544
utime_default(utime_t *ut, const char *path)
6545
0
{
6546
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
6547
    if (HAVE_UTIMENSAT_RUNTIME) {
6548
        UTIME_TO_TIMESPEC;
6549
        return utimensat(DEFAULT_DIR_FD, path, time, 0);
6550
    } else {
6551
        UTIME_TO_TIMEVAL;
6552
        return utimes(path, time);
6553
    }
6554
#elif defined(HAVE_UTIMENSAT)
6555
0
    UTIME_TO_TIMESPEC;
6556
0
    return utimensat(DEFAULT_DIR_FD, path, time, 0);
6557
#elif defined(HAVE_UTIMES)
6558
    UTIME_TO_TIMEVAL;
6559
    return utimes(path, time);
6560
#elif defined(HAVE_UTIME_H)
6561
    UTIME_TO_UTIMBUF;
6562
    return utime(path, time);
6563
#else
6564
    UTIME_TO_TIME_T;
6565
    return utime(path, time);
6566
#endif
6567
0
}
6568
6569
#endif
6570
6571
static int
6572
split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
6573
0
{
6574
0
    int result = 0;
6575
0
    PyObject *divmod;
6576
0
    divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
6577
0
    if (!divmod)
6578
0
        goto exit;
6579
0
    if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
6580
0
        PyErr_Format(PyExc_TypeError,
6581
0
                     "%.200s.__divmod__() must return a 2-tuple, not %.200s",
6582
0
                     _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
6583
0
        goto exit;
6584
0
    }
6585
0
    *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
6586
0
    if ((*s == -1) && PyErr_Occurred())
6587
0
        goto exit;
6588
0
    *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
6589
0
    if ((*ns == -1) && PyErr_Occurred())
6590
0
        goto exit;
6591
6592
0
    result = 1;
6593
0
exit:
6594
0
    Py_XDECREF(divmod);
6595
0
    return result;
6596
0
}
6597
6598
6599
/*[clinic input]
6600
os.utime
6601
6602
    path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
6603
    times: object = None
6604
    *
6605
    ns: object = NULL
6606
    dir_fd: dir_fd(requires='futimensat') = None
6607
    follow_symlinks: bool=True
6608
6609
# "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
6610
6611
Set the access and modified time of path.
6612
6613
path may always be specified as a string.
6614
On some platforms, path may also be specified as an open file descriptor.
6615
  If this functionality is unavailable, using it raises an exception.
6616
6617
If times is not None, it must be a tuple (atime, mtime);
6618
    atime and mtime should be expressed as float seconds since the epoch.
6619
If ns is specified, it must be a tuple (atime_ns, mtime_ns);
6620
    atime_ns and mtime_ns should be expressed as integer nanoseconds
6621
    since the epoch.
6622
If times is None and ns is unspecified, utime uses the current time.
6623
Specifying tuples for both times and ns is an error.
6624
6625
If dir_fd is not None, it should be a file descriptor open to a directory,
6626
  and path should be relative; path will then be relative to that directory.
6627
If follow_symlinks is False, and the last element of the path is a symbolic
6628
  link, utime will modify the symbolic link itself instead of the file the
6629
  link points to.
6630
It is an error to use dir_fd or follow_symlinks when specifying path
6631
  as an open file descriptor.
6632
dir_fd and follow_symlinks may not be available on your platform.
6633
  If they are unavailable, using them will raise a NotImplementedError.
6634
6635
[clinic start generated code]*/
6636
6637
static PyObject *
6638
os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
6639
              int dir_fd, int follow_symlinks)
6640
/*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
6641
0
{
6642
#ifdef MS_WINDOWS
6643
    HANDLE hFile;
6644
    FILETIME atime, mtime;
6645
#else
6646
0
    int result;
6647
0
#endif
6648
6649
0
    utime_t utime;
6650
6651
0
    memset(&utime, 0, sizeof(utime_t));
6652
6653
0
    if (times != Py_None && ns) {
6654
0
        PyErr_SetString(PyExc_ValueError,
6655
0
                     "utime: you may specify either 'times'"
6656
0
                     " or 'ns' but not both");
6657
0
        return NULL;
6658
0
    }
6659
6660
0
    if (times != Py_None) {
6661
0
        time_t a_sec, m_sec;
6662
0
        long a_nsec, m_nsec;
6663
0
        if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
6664
0
            PyErr_SetString(PyExc_TypeError,
6665
0
                         "utime: 'times' must be either"
6666
0
                         " a tuple of two ints or None");
6667
0
            return NULL;
6668
0
        }
6669
0
        utime.now = 0;
6670
0
        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
6671
0
                                     &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
6672
0
            _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
6673
0
                                     &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
6674
0
            return NULL;
6675
0
        }
6676
0
        utime.atime_s = a_sec;
6677
0
        utime.atime_ns = a_nsec;
6678
0
        utime.mtime_s = m_sec;
6679
0
        utime.mtime_ns = m_nsec;
6680
0
    }
6681
0
    else if (ns) {
6682
0
        if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
6683
0
            PyErr_SetString(PyExc_TypeError,
6684
0
                         "utime: 'ns' must be a tuple of two ints");
6685
0
            return NULL;
6686
0
        }
6687
0
        utime.now = 0;
6688
0
        if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
6689
0
                                      &utime.atime_s, &utime.atime_ns) ||
6690
0
            !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
6691
0
                                       &utime.mtime_s, &utime.mtime_ns)) {
6692
0
            return NULL;
6693
0
        }
6694
0
    }
6695
0
    else {
6696
        /* times and ns are both None/unspecified. use "now". */
6697
0
        utime.now = 1;
6698
0
    }
6699
6700
#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
6701
    if (follow_symlinks_specified("utime", follow_symlinks))
6702
        return NULL;
6703
#endif
6704
6705
0
    if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
6706
0
        dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
6707
0
        fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
6708
0
        return NULL;
6709
6710
#if !defined(HAVE_UTIMENSAT)
6711
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
6712
        PyErr_SetString(PyExc_ValueError,
6713
                     "utime: cannot use dir_fd and follow_symlinks "
6714
                     "together on this platform");
6715
        return NULL;
6716
    }
6717
#endif
6718
6719
0
    if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
6720
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6721
0
        return NULL;
6722
0
    }
6723
6724
#ifdef MS_WINDOWS
6725
    Py_BEGIN_ALLOW_THREADS
6726
    hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
6727
                        NULL, OPEN_EXISTING,
6728
                        FILE_FLAG_BACKUP_SEMANTICS, NULL);
6729
    Py_END_ALLOW_THREADS
6730
    if (hFile == INVALID_HANDLE_VALUE) {
6731
        path_error(path);
6732
        return NULL;
6733
    }
6734
6735
    if (utime.now) {
6736
        GetSystemTimeAsFileTime(&mtime);
6737
        atime = mtime;
6738
    }
6739
    else {
6740
        _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
6741
        _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
6742
    }
6743
    if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
6744
        path_error(path);
6745
        CloseHandle(hFile);
6746
        return NULL;
6747
    }
6748
    CloseHandle(hFile);
6749
#else /* MS_WINDOWS */
6750
0
    Py_BEGIN_ALLOW_THREADS
6751
6752
0
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
6753
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
6754
0
        result = utime_nofollow_symlinks(&utime, path->narrow);
6755
0
    else
6756
0
#endif
6757
6758
0
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
6759
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
6760
0
        result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
6761
6762
0
    } else
6763
0
#endif
6764
6765
0
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
6766
0
    if (path->fd != -1)
6767
0
        result = utime_fd(&utime, path->fd);
6768
0
    else
6769
0
#endif
6770
6771
0
    result = utime_default(&utime, path->narrow);
6772
6773
0
    Py_END_ALLOW_THREADS
6774
6775
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
6776
    /* See utime_dir_fd implementation */
6777
    if (result == -1 && errno == ENOSYS) {
6778
        argument_unavailable_error(NULL, "dir_fd");
6779
        return NULL;
6780
    }
6781
#endif
6782
6783
0
    if (result < 0) {
6784
0
        path_error(path);
6785
0
        return NULL;
6786
0
    }
6787
6788
0
#endif /* MS_WINDOWS */
6789
6790
0
    Py_RETURN_NONE;
6791
0
}
6792
6793
/* Process operations */
6794
6795
6796
/*[clinic input]
6797
os._exit
6798
6799
    status: int
6800
6801
Exit to the system with specified status, without normal exit processing.
6802
[clinic start generated code]*/
6803
6804
static PyObject *
6805
os__exit_impl(PyObject *module, int status)
6806
/*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
6807
0
{
6808
0
    _exit(status);
6809
0
    return NULL; /* Make gcc -Wall happy */
6810
0
}
6811
6812
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
6813
#define EXECV_CHAR wchar_t
6814
#else
6815
0
#define EXECV_CHAR char
6816
#endif
6817
6818
#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
6819
static void
6820
free_string_array(EXECV_CHAR **array, Py_ssize_t count)
6821
0
{
6822
0
    Py_ssize_t i;
6823
0
    for (i = 0; i < count; i++)
6824
0
        PyMem_Free(array[i]);
6825
0
    PyMem_Free(array);
6826
0
}
6827
6828
static int
6829
fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
6830
0
{
6831
0
    Py_ssize_t size;
6832
0
    PyObject *ub;
6833
0
    int result = 0;
6834
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
6835
    if (!PyUnicode_FSDecoder(o, &ub))
6836
        return 0;
6837
    *out = PyUnicode_AsWideCharString(ub, &size);
6838
    if (*out)
6839
        result = 1;
6840
#else
6841
0
    if (!PyUnicode_FSConverter(o, &ub))
6842
0
        return 0;
6843
0
    size = PyBytes_GET_SIZE(ub);
6844
0
    *out = PyMem_Malloc(size + 1);
6845
0
    if (*out) {
6846
0
        memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
6847
0
        result = 1;
6848
0
    } else
6849
0
        PyErr_NoMemory();
6850
0
#endif
6851
0
    Py_DECREF(ub);
6852
0
    return result;
6853
0
}
6854
#endif
6855
6856
#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
6857
static EXECV_CHAR**
6858
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
6859
0
{
6860
0
    Py_ssize_t i, pos, envc;
6861
0
    PyObject *keys=NULL, *vals=NULL;
6862
0
    PyObject *key2, *val2, *keyval;
6863
0
    EXECV_CHAR **envlist;
6864
6865
0
    i = PyMapping_Size(env);
6866
0
    if (i < 0)
6867
0
        return NULL;
6868
0
    envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
6869
0
    if (envlist == NULL) {
6870
0
        PyErr_NoMemory();
6871
0
        return NULL;
6872
0
    }
6873
0
    envc = 0;
6874
0
    keys = PyMapping_Keys(env);
6875
0
    if (!keys)
6876
0
        goto error;
6877
0
    vals = PyMapping_Values(env);
6878
0
    if (!vals)
6879
0
        goto error;
6880
0
    if (!PyList_Check(keys) || !PyList_Check(vals)) {
6881
0
        PyErr_Format(PyExc_TypeError,
6882
0
                     "env.keys() or env.values() is not a list");
6883
0
        goto error;
6884
0
    }
6885
6886
0
    for (pos = 0; pos < i; pos++) {
6887
0
        PyObject *key = PyList_GetItem(keys, pos);  // Borrowed ref.
6888
0
        if (key == NULL) {
6889
0
            goto error;
6890
0
        }
6891
0
        PyObject *val = PyList_GetItem(vals, pos);  // Borrowed ref.
6892
0
        if (val == NULL) {
6893
0
            goto error;
6894
0
        }
6895
6896
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
6897
        if (!PyUnicode_FSDecoder(key, &key2))
6898
            goto error;
6899
        if (!PyUnicode_FSDecoder(val, &val2)) {
6900
            Py_DECREF(key2);
6901
            goto error;
6902
        }
6903
        /* Search from index 1 because on Windows starting '=' is allowed for
6904
           defining hidden environment variables. */
6905
        if (PyUnicode_GET_LENGTH(key2) == 0 ||
6906
            PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
6907
        {
6908
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
6909
            Py_DECREF(key2);
6910
            Py_DECREF(val2);
6911
            goto error;
6912
        }
6913
        keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
6914
#else
6915
0
        if (!PyUnicode_FSConverter(key, &key2))
6916
0
            goto error;
6917
0
        if (!PyUnicode_FSConverter(val, &val2)) {
6918
0
            Py_DECREF(key2);
6919
0
            goto error;
6920
0
        }
6921
0
        if (PyBytes_GET_SIZE(key2) == 0 ||
6922
0
            strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
6923
0
        {
6924
0
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
6925
0
            Py_DECREF(key2);
6926
0
            Py_DECREF(val2);
6927
0
            goto error;
6928
0
        }
6929
0
        keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
6930
0
                                             PyBytes_AS_STRING(val2));
6931
0
#endif
6932
0
        Py_DECREF(key2);
6933
0
        Py_DECREF(val2);
6934
0
        if (!keyval)
6935
0
            goto error;
6936
6937
0
        if (!fsconvert_strdup(keyval, &envlist[envc++])) {
6938
0
            Py_DECREF(keyval);
6939
0
            goto error;
6940
0
        }
6941
6942
0
        Py_DECREF(keyval);
6943
0
    }
6944
0
    Py_DECREF(vals);
6945
0
    Py_DECREF(keys);
6946
6947
0
    envlist[envc] = 0;
6948
0
    *envc_ptr = envc;
6949
0
    return envlist;
6950
6951
0
error:
6952
0
    Py_XDECREF(keys);
6953
0
    Py_XDECREF(vals);
6954
0
    free_string_array(envlist, envc);
6955
0
    return NULL;
6956
0
}
6957
6958
static EXECV_CHAR**
6959
parse_arglist(PyObject* argv, Py_ssize_t *argc)
6960
0
{
6961
0
    int i;
6962
0
    EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
6963
0
    if (argvlist == NULL) {
6964
0
        PyErr_NoMemory();
6965
0
        return NULL;
6966
0
    }
6967
0
    for (i = 0; i < *argc; i++) {
6968
0
        PyObject* item = PySequence_ITEM(argv, i);
6969
0
        if (item == NULL)
6970
0
            goto fail;
6971
0
        if (!fsconvert_strdup(item, &argvlist[i])) {
6972
0
            Py_DECREF(item);
6973
0
            goto fail;
6974
0
        }
6975
0
        Py_DECREF(item);
6976
0
    }
6977
0
    argvlist[*argc] = NULL;
6978
0
    return argvlist;
6979
0
fail:
6980
0
    *argc = i;
6981
0
    free_string_array(argvlist, *argc);
6982
0
    return NULL;
6983
0
}
6984
6985
#endif
6986
6987
6988
#ifdef HAVE_EXECV
6989
/*[clinic input]
6990
os.execv
6991
6992
    path: path_t
6993
        Path of executable file.
6994
    argv: object
6995
        Tuple or list of strings.
6996
    /
6997
6998
Execute an executable path with arguments, replacing current process.
6999
[clinic start generated code]*/
7000
7001
static PyObject *
7002
os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
7003
/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
7004
0
{
7005
0
    EXECV_CHAR **argvlist;
7006
0
    Py_ssize_t argc;
7007
7008
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7009
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7010
0
        PyErr_SetString(PyExc_RuntimeError,
7011
0
                        "exec not supported for isolated subinterpreters");
7012
0
        return NULL;
7013
0
    }
7014
7015
    /* execv has two arguments: (path, argv), where
7016
       argv is a list or tuple of strings. */
7017
7018
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7019
0
        PyErr_SetString(PyExc_TypeError,
7020
0
                        "execv() arg 2 must be a tuple or list");
7021
0
        return NULL;
7022
0
    }
7023
0
    argc = PySequence_Size(argv);
7024
0
    if (argc < 1) {
7025
0
        PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
7026
0
        return NULL;
7027
0
    }
7028
7029
0
    argvlist = parse_arglist(argv, &argc);
7030
0
    if (argvlist == NULL) {
7031
0
        return NULL;
7032
0
    }
7033
0
    if (!argvlist[0][0]) {
7034
0
        PyErr_SetString(PyExc_ValueError,
7035
0
            "execv() arg 2 first element cannot be empty");
7036
0
        free_string_array(argvlist, argc);
7037
0
        return NULL;
7038
0
    }
7039
7040
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
7041
0
        free_string_array(argvlist, argc);
7042
0
        return NULL;
7043
0
    }
7044
7045
0
    _Py_BEGIN_SUPPRESS_IPH
7046
#ifdef HAVE_WEXECV
7047
    _wexecv(path->wide, argvlist);
7048
#else
7049
0
    execv(path->narrow, argvlist);
7050
0
#endif
7051
0
    _Py_END_SUPPRESS_IPH
7052
7053
    /* If we get here it's definitely an error */
7054
7055
0
    posix_error();
7056
0
    free_string_array(argvlist, argc);
7057
0
    return NULL;
7058
0
}
7059
7060
7061
/*[clinic input]
7062
os.execve
7063
7064
    path: path_t(allow_fd='PATH_HAVE_FEXECVE')
7065
        Path of executable file.
7066
    argv: object
7067
        Tuple or list of strings.
7068
    env: object
7069
        Dictionary of strings mapping to strings.
7070
7071
Execute an executable path with arguments, replacing current process.
7072
[clinic start generated code]*/
7073
7074
static PyObject *
7075
os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
7076
/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
7077
0
{
7078
0
    EXECV_CHAR **argvlist = NULL;
7079
0
    EXECV_CHAR **envlist;
7080
0
    Py_ssize_t argc, envc;
7081
7082
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7083
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7084
0
        PyErr_SetString(PyExc_RuntimeError,
7085
0
                        "exec not supported for isolated subinterpreters");
7086
0
        return NULL;
7087
0
    }
7088
7089
    /* execve has three arguments: (path, argv, env), where
7090
       argv is a list or tuple of strings and env is a dictionary
7091
       like posix.environ. */
7092
7093
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7094
0
        PyErr_SetString(PyExc_TypeError,
7095
0
                        "execve: argv must be a tuple or list");
7096
0
        goto fail_0;
7097
0
    }
7098
0
    argc = PySequence_Size(argv);
7099
0
    if (argc < 1) {
7100
0
        PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
7101
0
        return NULL;
7102
0
    }
7103
7104
0
    if (!PyMapping_Check(env)) {
7105
0
        PyErr_SetString(PyExc_TypeError,
7106
0
                        "execve: environment must be a mapping object");
7107
0
        goto fail_0;
7108
0
    }
7109
7110
0
    argvlist = parse_arglist(argv, &argc);
7111
0
    if (argvlist == NULL) {
7112
0
        goto fail_0;
7113
0
    }
7114
0
    if (!argvlist[0][0]) {
7115
0
        PyErr_SetString(PyExc_ValueError,
7116
0
            "execve: argv first element cannot be empty");
7117
0
        goto fail_0;
7118
0
    }
7119
7120
0
    envlist = parse_envlist(env, &envc);
7121
0
    if (envlist == NULL)
7122
0
        goto fail_0;
7123
7124
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
7125
0
        goto fail_1;
7126
0
    }
7127
7128
0
    _Py_BEGIN_SUPPRESS_IPH
7129
0
#ifdef HAVE_FEXECVE
7130
0
    if (path->fd > -1)
7131
0
        fexecve(path->fd, argvlist, envlist);
7132
0
    else
7133
0
#endif
7134
#ifdef HAVE_WEXECV
7135
        _wexecve(path->wide, argvlist, envlist);
7136
#else
7137
0
        execve(path->narrow, argvlist, envlist);
7138
0
#endif
7139
0
    _Py_END_SUPPRESS_IPH
7140
7141
    /* If we get here it's definitely an error */
7142
7143
0
    posix_path_error(path);
7144
0
  fail_1:
7145
0
    free_string_array(envlist, envc);
7146
0
  fail_0:
7147
0
    if (argvlist)
7148
0
        free_string_array(argvlist, argc);
7149
0
    return NULL;
7150
0
}
7151
7152
#endif /* HAVE_EXECV */
7153
7154
#ifdef HAVE_POSIX_SPAWN
7155
7156
enum posix_spawn_file_actions_identifier {
7157
    POSIX_SPAWN_OPEN,
7158
    POSIX_SPAWN_CLOSE,
7159
    POSIX_SPAWN_DUP2
7160
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7161
    ,POSIX_SPAWN_CLOSEFROM
7162
#endif
7163
};
7164
7165
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
7166
static int
7167
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
7168
#endif
7169
7170
static int
7171
parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
7172
                        int resetids, int setsid, PyObject *setsigmask,
7173
                        PyObject *setsigdef, PyObject *scheduler,
7174
                        posix_spawnattr_t *attrp)
7175
0
{
7176
0
    long all_flags = 0;
7177
7178
0
    errno = posix_spawnattr_init(attrp);
7179
0
    if (errno) {
7180
0
        posix_error();
7181
0
        return -1;
7182
0
    }
7183
7184
0
    if (setpgroup) {
7185
0
        pid_t pgid = PyLong_AsPid(setpgroup);
7186
0
        if (pgid == (pid_t)-1 && PyErr_Occurred()) {
7187
0
            goto fail;
7188
0
        }
7189
0
        errno = posix_spawnattr_setpgroup(attrp, pgid);
7190
0
        if (errno) {
7191
0
            posix_error();
7192
0
            goto fail;
7193
0
        }
7194
0
        all_flags |= POSIX_SPAWN_SETPGROUP;
7195
0
    }
7196
7197
0
    if (resetids) {
7198
0
        all_flags |= POSIX_SPAWN_RESETIDS;
7199
0
    }
7200
7201
0
    if (setsid) {
7202
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7203
        if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
7204
#endif
7205
0
#ifdef POSIX_SPAWN_SETSID
7206
0
        all_flags |= POSIX_SPAWN_SETSID;
7207
#elif defined(POSIX_SPAWN_SETSID_NP)
7208
        all_flags |= POSIX_SPAWN_SETSID_NP;
7209
#else
7210
        argument_unavailable_error(func_name, "setsid");
7211
        return -1;
7212
#endif
7213
7214
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7215
        } else {
7216
            argument_unavailable_error(func_name, "setsid");
7217
            return -1;
7218
        }
7219
#endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
7220
7221
0
    }
7222
7223
0
#ifdef HAVE_SIGSET_T
7224
0
   if (setsigmask) {
7225
0
        sigset_t set;
7226
0
        if (!_Py_Sigset_Converter(setsigmask, &set)) {
7227
0
            goto fail;
7228
0
        }
7229
0
        errno = posix_spawnattr_setsigmask(attrp, &set);
7230
0
        if (errno) {
7231
0
            posix_error();
7232
0
            goto fail;
7233
0
        }
7234
0
        all_flags |= POSIX_SPAWN_SETSIGMASK;
7235
0
    }
7236
7237
0
    if (setsigdef) {
7238
0
        sigset_t set;
7239
0
        if (!_Py_Sigset_Converter(setsigdef, &set)) {
7240
0
            goto fail;
7241
0
        }
7242
0
        errno = posix_spawnattr_setsigdefault(attrp, &set);
7243
0
        if (errno) {
7244
0
            posix_error();
7245
0
            goto fail;
7246
0
        }
7247
0
        all_flags |= POSIX_SPAWN_SETSIGDEF;
7248
0
    }
7249
#else
7250
    if (setsigmask || setsigdef) {
7251
        PyErr_SetString(PyExc_NotImplementedError,
7252
                        "sigset is not supported on this platform");
7253
        goto fail;
7254
    }
7255
#endif
7256
7257
0
    if (scheduler) {
7258
0
#ifdef POSIX_SPAWN_SETSCHEDULER
7259
0
        PyObject *py_schedpolicy;
7260
0
        PyObject *schedparam_obj;
7261
0
        struct sched_param schedparam;
7262
7263
0
        if (!PyArg_ParseTuple(scheduler, "OO"
7264
0
                        ";A scheduler tuple must have two elements",
7265
0
                        &py_schedpolicy, &schedparam_obj)) {
7266
0
            goto fail;
7267
0
        }
7268
0
        if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
7269
0
            goto fail;
7270
0
        }
7271
0
        if (py_schedpolicy != Py_None) {
7272
0
            int schedpolicy = PyLong_AsInt(py_schedpolicy);
7273
7274
0
            if (schedpolicy == -1 && PyErr_Occurred()) {
7275
0
                goto fail;
7276
0
            }
7277
0
            errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
7278
0
            if (errno) {
7279
0
                posix_error();
7280
0
                goto fail;
7281
0
            }
7282
0
            all_flags |= POSIX_SPAWN_SETSCHEDULER;
7283
0
        }
7284
0
        errno = posix_spawnattr_setschedparam(attrp, &schedparam);
7285
0
        if (errno) {
7286
0
            posix_error();
7287
0
            goto fail;
7288
0
        }
7289
0
        all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
7290
#else
7291
        PyErr_SetString(PyExc_NotImplementedError,
7292
                "The scheduler option is not supported in this system.");
7293
        goto fail;
7294
#endif
7295
0
    }
7296
7297
0
    errno = posix_spawnattr_setflags(attrp, all_flags);
7298
0
    if (errno) {
7299
0
        posix_error();
7300
0
        goto fail;
7301
0
    }
7302
7303
0
    return 0;
7304
7305
0
fail:
7306
0
    (void)posix_spawnattr_destroy(attrp);
7307
0
    return -1;
7308
0
}
7309
7310
static int
7311
parse_file_actions(PyObject *file_actions,
7312
                   posix_spawn_file_actions_t *file_actionsp,
7313
                   PyObject *temp_buffer)
7314
0
{
7315
0
    PyObject *seq;
7316
0
    PyObject *file_action = NULL;
7317
0
    PyObject *tag_obj;
7318
7319
0
    seq = PySequence_Fast(file_actions,
7320
0
                          "file_actions must be a sequence or None");
7321
0
    if (seq == NULL) {
7322
0
        return -1;
7323
0
    }
7324
7325
0
    errno = posix_spawn_file_actions_init(file_actionsp);
7326
0
    if (errno) {
7327
0
        posix_error();
7328
0
        Py_DECREF(seq);
7329
0
        return -1;
7330
0
    }
7331
7332
0
    for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
7333
0
        file_action = PySequence_Fast_GET_ITEM(seq, i);
7334
0
        Py_INCREF(file_action);
7335
0
        if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
7336
0
            PyErr_SetString(PyExc_TypeError,
7337
0
                "Each file_actions element must be a non-empty tuple");
7338
0
            goto fail;
7339
0
        }
7340
0
        long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
7341
0
        if (tag == -1 && PyErr_Occurred()) {
7342
0
            goto fail;
7343
0
        }
7344
7345
        /* Populate the file_actions object */
7346
0
        switch (tag) {
7347
0
            case POSIX_SPAWN_OPEN: {
7348
0
                int fd, oflag;
7349
0
                PyObject *path;
7350
0
                unsigned long mode;
7351
0
                if (!PyArg_ParseTuple(file_action, "OiO&ik"
7352
0
                        ";A open file_action tuple must have 5 elements",
7353
0
                        &tag_obj, &fd, PyUnicode_FSConverter, &path,
7354
0
                        &oflag, &mode))
7355
0
                {
7356
0
                    goto fail;
7357
0
                }
7358
0
                if (PyList_Append(temp_buffer, path)) {
7359
0
                    Py_DECREF(path);
7360
0
                    goto fail;
7361
0
                }
7362
0
                errno = posix_spawn_file_actions_addopen(file_actionsp,
7363
0
                        fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
7364
0
                if (errno) {
7365
0
                    posix_error();
7366
0
                    Py_DECREF(path);
7367
0
                    goto fail;
7368
0
                }
7369
0
                Py_DECREF(path);
7370
0
                break;
7371
0
            }
7372
0
            case POSIX_SPAWN_CLOSE: {
7373
0
                int fd;
7374
0
                if (!PyArg_ParseTuple(file_action, "Oi"
7375
0
                        ";A close file_action tuple must have 2 elements",
7376
0
                        &tag_obj, &fd))
7377
0
                {
7378
0
                    goto fail;
7379
0
                }
7380
0
                errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
7381
0
                if (errno) {
7382
0
                    posix_error();
7383
0
                    goto fail;
7384
0
                }
7385
0
                break;
7386
0
            }
7387
0
            case POSIX_SPAWN_DUP2: {
7388
0
                int fd1, fd2;
7389
0
                if (!PyArg_ParseTuple(file_action, "Oii"
7390
0
                        ";A dup2 file_action tuple must have 3 elements",
7391
0
                        &tag_obj, &fd1, &fd2))
7392
0
                {
7393
0
                    goto fail;
7394
0
                }
7395
0
                errno = posix_spawn_file_actions_adddup2(file_actionsp,
7396
0
                                                         fd1, fd2);
7397
0
                if (errno) {
7398
0
                    posix_error();
7399
0
                    goto fail;
7400
0
                }
7401
0
                break;
7402
0
            }
7403
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7404
            case POSIX_SPAWN_CLOSEFROM: {
7405
                int fd;
7406
                if (!PyArg_ParseTuple(file_action, "Oi"
7407
                        ";A closefrom file_action tuple must have 2 elements",
7408
                        &tag_obj, &fd))
7409
                {
7410
                    goto fail;
7411
                }
7412
                errno = posix_spawn_file_actions_addclosefrom_np(file_actionsp,
7413
                                                                 fd);
7414
                if (errno) {
7415
                    posix_error();
7416
                    goto fail;
7417
                }
7418
                break;
7419
            }
7420
#endif
7421
0
            default: {
7422
0
                PyErr_SetString(PyExc_TypeError,
7423
0
                                "Unknown file_actions identifier");
7424
0
                goto fail;
7425
0
            }
7426
0
        }
7427
0
        Py_DECREF(file_action);
7428
0
    }
7429
7430
0
    Py_DECREF(seq);
7431
0
    return 0;
7432
7433
0
fail:
7434
0
    Py_DECREF(seq);
7435
0
    Py_DECREF(file_action);
7436
0
    (void)posix_spawn_file_actions_destroy(file_actionsp);
7437
0
    return -1;
7438
0
}
7439
7440
7441
static PyObject *
7442
py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
7443
               PyObject *env, PyObject *file_actions,
7444
               PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
7445
               PyObject *setsigdef, PyObject *scheduler)
7446
0
{
7447
0
    const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
7448
0
    EXECV_CHAR **argvlist = NULL;
7449
0
    EXECV_CHAR **envlist = NULL;
7450
0
    posix_spawn_file_actions_t file_actions_buf;
7451
0
    posix_spawn_file_actions_t *file_actionsp = NULL;
7452
0
    posix_spawnattr_t attr;
7453
0
    posix_spawnattr_t *attrp = NULL;
7454
0
    Py_ssize_t argc, envc;
7455
0
    PyObject *result = NULL;
7456
0
    PyObject *temp_buffer = NULL;
7457
0
    pid_t pid;
7458
0
    int err_code;
7459
7460
    /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
7461
       argv is a list or tuple of strings and env is a dictionary
7462
       like posix.environ. */
7463
7464
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7465
0
        PyErr_Format(PyExc_TypeError,
7466
0
                     "%s: argv must be a tuple or list", func_name);
7467
0
        goto exit;
7468
0
    }
7469
0
    argc = PySequence_Size(argv);
7470
0
    if (argc < 1) {
7471
0
        PyErr_Format(PyExc_ValueError,
7472
0
                     "%s: argv must not be empty", func_name);
7473
0
        return NULL;
7474
0
    }
7475
7476
0
    if (!PyMapping_Check(env) && env != Py_None) {
7477
0
        PyErr_Format(PyExc_TypeError,
7478
0
                     "%s: environment must be a mapping object or None", func_name);
7479
0
        goto exit;
7480
0
    }
7481
7482
0
    argvlist = parse_arglist(argv, &argc);
7483
0
    if (argvlist == NULL) {
7484
0
        goto exit;
7485
0
    }
7486
0
    if (!argvlist[0][0]) {
7487
0
        PyErr_Format(PyExc_ValueError,
7488
0
                     "%s: argv first element cannot be empty", func_name);
7489
0
        goto exit;
7490
0
    }
7491
7492
#ifdef USE_DARWIN_NS_GET_ENVIRON
7493
    // There is no environ global in this situation.
7494
    char **environ = NULL;
7495
#endif
7496
7497
0
    if (env == Py_None) {
7498
#ifdef USE_DARWIN_NS_GET_ENVIRON
7499
        environ = *_NSGetEnviron();
7500
#endif
7501
0
        envlist = environ;
7502
0
    } else {
7503
0
        envlist = parse_envlist(env, &envc);
7504
0
        if (envlist == NULL) {
7505
0
            goto exit;
7506
0
        }
7507
0
    }
7508
7509
0
    if (file_actions != NULL && file_actions != Py_None) {
7510
        /* There is a bug in old versions of glibc that makes some of the
7511
         * helper functions for manipulating file actions not copy the provided
7512
         * buffers. The problem is that posix_spawn_file_actions_addopen does not
7513
         * copy the value of path for some old versions of glibc (<2.20).
7514
         * The use of temp_buffer here is a workaround that keeps the
7515
         * python objects that own the buffers alive until posix_spawn gets called.
7516
         * Check https://bugs.python.org/issue33630 and
7517
         * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
7518
0
        temp_buffer = PyList_New(0);
7519
0
        if (!temp_buffer) {
7520
0
            goto exit;
7521
0
        }
7522
0
        if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
7523
0
            goto exit;
7524
0
        }
7525
0
        file_actionsp = &file_actions_buf;
7526
0
    }
7527
7528
0
    if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
7529
0
                                setsigmask, setsigdef, scheduler, &attr)) {
7530
0
        goto exit;
7531
0
    }
7532
0
    attrp = &attr;
7533
7534
0
    if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
7535
0
        goto exit;
7536
0
    }
7537
7538
0
    _Py_BEGIN_SUPPRESS_IPH
7539
0
#ifdef HAVE_POSIX_SPAWNP
7540
0
    if (use_posix_spawnp) {
7541
0
        err_code = posix_spawnp(&pid, path->narrow,
7542
0
                                file_actionsp, attrp, argvlist, envlist);
7543
0
    }
7544
0
    else
7545
0
#endif /* HAVE_POSIX_SPAWNP */
7546
0
    {
7547
0
        err_code = posix_spawn(&pid, path->narrow,
7548
0
                               file_actionsp, attrp, argvlist, envlist);
7549
0
    }
7550
0
    _Py_END_SUPPRESS_IPH
7551
7552
0
    if (err_code) {
7553
0
        errno = err_code;
7554
0
        PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
7555
0
        goto exit;
7556
0
    }
7557
#ifdef _Py_MEMORY_SANITIZER
7558
    __msan_unpoison(&pid, sizeof(pid));
7559
#endif
7560
0
    result = PyLong_FromPid(pid);
7561
7562
0
exit:
7563
0
    if (file_actionsp) {
7564
0
        (void)posix_spawn_file_actions_destroy(file_actionsp);
7565
0
    }
7566
0
    if (attrp) {
7567
0
        (void)posix_spawnattr_destroy(attrp);
7568
0
    }
7569
0
    if (envlist && envlist != environ) {
7570
0
        free_string_array(envlist, envc);
7571
0
    }
7572
0
    if (argvlist) {
7573
0
        free_string_array(argvlist, argc);
7574
0
    }
7575
0
    Py_XDECREF(temp_buffer);
7576
0
    return result;
7577
0
}
7578
7579
7580
/*[clinic input]
7581
7582
os.posix_spawn
7583
    path: path_t
7584
        Path of executable file.
7585
    argv: object
7586
        Tuple or list of strings.
7587
    env: object
7588
        Dictionary of strings mapping to strings.
7589
    /
7590
    *
7591
    file_actions: object(c_default='NULL') = ()
7592
        A sequence of file action tuples.
7593
    setpgroup: object = NULL
7594
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
7595
    resetids: bool = False
7596
        If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
7597
    setsid: bool = False
7598
        If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
7599
    setsigmask: object(c_default='NULL') = ()
7600
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
7601
    setsigdef: object(c_default='NULL') = ()
7602
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
7603
    scheduler: object = NULL
7604
        A tuple with the scheduler policy (optional) and parameters.
7605
7606
Execute the program specified by path in a new process.
7607
[clinic start generated code]*/
7608
7609
static PyObject *
7610
os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
7611
                    PyObject *env, PyObject *file_actions,
7612
                    PyObject *setpgroup, int resetids, int setsid,
7613
                    PyObject *setsigmask, PyObject *setsigdef,
7614
                    PyObject *scheduler)
7615
/*[clinic end generated code: output=14a1098c566bc675 input=808aed1090d84e33]*/
7616
0
{
7617
0
    return py_posix_spawn(0, module, path, argv, env, file_actions,
7618
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
7619
0
                          scheduler);
7620
0
}
7621
 #endif /* HAVE_POSIX_SPAWN */
7622
7623
7624
7625
#ifdef HAVE_POSIX_SPAWNP
7626
/*[clinic input]
7627
7628
os.posix_spawnp
7629
    path: path_t
7630
        Path of executable file.
7631
    argv: object
7632
        Tuple or list of strings.
7633
    env: object
7634
        Dictionary of strings mapping to strings.
7635
    /
7636
    *
7637
    file_actions: object(c_default='NULL') = ()
7638
        A sequence of file action tuples.
7639
    setpgroup: object = NULL
7640
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
7641
    resetids: bool = False
7642
        If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
7643
    setsid: bool = False
7644
        If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
7645
    setsigmask: object(c_default='NULL') = ()
7646
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
7647
    setsigdef: object(c_default='NULL') = ()
7648
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
7649
    scheduler: object = NULL
7650
        A tuple with the scheduler policy (optional) and parameters.
7651
7652
Execute the program specified by path in a new process.
7653
[clinic start generated code]*/
7654
7655
static PyObject *
7656
os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
7657
                     PyObject *env, PyObject *file_actions,
7658
                     PyObject *setpgroup, int resetids, int setsid,
7659
                     PyObject *setsigmask, PyObject *setsigdef,
7660
                     PyObject *scheduler)
7661
/*[clinic end generated code: output=7b9aaefe3031238d input=9e89e616116752a1]*/
7662
0
{
7663
0
    return py_posix_spawn(1, module, path, argv, env, file_actions,
7664
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
7665
0
                          scheduler);
7666
0
}
7667
#endif /* HAVE_POSIX_SPAWNP */
7668
7669
#ifdef HAVE_RTPSPAWN
7670
static intptr_t
7671
_rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
7672
               const char  *envp[])
7673
{
7674
     RTP_ID rtpid;
7675
     int status;
7676
     pid_t res;
7677
     int async_err = 0;
7678
7679
     /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
7680
        uStackSize=0 cannot be used, the default stack size is too small for
7681
        Python. */
7682
     if (envp) {
7683
         rtpid = rtpSpawn(rtpFileName, argv, envp,
7684
                          100, 0x1000000, 0, VX_FP_TASK);
7685
     }
7686
     else {
7687
         rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
7688
                          100, 0x1000000, 0, VX_FP_TASK);
7689
     }
7690
     if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
7691
         do {
7692
             res = waitpid((pid_t)rtpid, &status, 0);
7693
         } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7694
7695
         if (res < 0)
7696
             return RTP_ID_ERROR;
7697
         return ((intptr_t)status);
7698
     }
7699
     return ((intptr_t)rtpid);
7700
}
7701
#endif
7702
7703
#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
7704
/*[clinic input]
7705
os.spawnv
7706
7707
    mode: int
7708
        Mode of process creation.
7709
    path: path_t
7710
        Path of executable file.
7711
    argv: object
7712
        Tuple or list of strings.
7713
    /
7714
7715
Execute the program specified by path in a new process.
7716
[clinic start generated code]*/
7717
7718
static PyObject *
7719
os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
7720
/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
7721
{
7722
    EXECV_CHAR **argvlist;
7723
    int i;
7724
    Py_ssize_t argc;
7725
    intptr_t spawnval;
7726
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
7727
7728
    /* spawnv has three arguments: (mode, path, argv), where
7729
       argv is a list or tuple of strings. */
7730
7731
    if (PyList_Check(argv)) {
7732
        argc = PyList_Size(argv);
7733
        getitem = PyList_GetItem;
7734
    }
7735
    else if (PyTuple_Check(argv)) {
7736
        argc = PyTuple_Size(argv);
7737
        getitem = PyTuple_GetItem;
7738
    }
7739
    else {
7740
        PyErr_SetString(PyExc_TypeError,
7741
                        "spawnv() arg 2 must be a tuple or list");
7742
        return NULL;
7743
    }
7744
    if (argc == 0) {
7745
        PyErr_SetString(PyExc_ValueError,
7746
            "spawnv() arg 2 cannot be empty");
7747
        return NULL;
7748
    }
7749
7750
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
7751
    if (argvlist == NULL) {
7752
        return PyErr_NoMemory();
7753
    }
7754
    for (i = 0; i < argc; i++) {
7755
        if (!fsconvert_strdup((*getitem)(argv, i),
7756
                              &argvlist[i])) {
7757
            free_string_array(argvlist, i);
7758
            PyErr_SetString(
7759
                PyExc_TypeError,
7760
                "spawnv() arg 2 must contain only strings");
7761
            return NULL;
7762
        }
7763
        if (i == 0 && !argvlist[0][0]) {
7764
            free_string_array(argvlist, i + 1);
7765
            PyErr_SetString(
7766
                PyExc_ValueError,
7767
                "spawnv() arg 2 first element cannot be empty");
7768
            return NULL;
7769
        }
7770
    }
7771
    argvlist[argc] = NULL;
7772
7773
#if !defined(HAVE_RTPSPAWN)
7774
    if (mode == _OLD_P_OVERLAY)
7775
        mode = _P_OVERLAY;
7776
#endif
7777
7778
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
7779
                    Py_None) < 0) {
7780
        free_string_array(argvlist, argc);
7781
        return NULL;
7782
    }
7783
7784
    Py_BEGIN_ALLOW_THREADS
7785
    _Py_BEGIN_SUPPRESS_IPH
7786
#ifdef HAVE_WSPAWNV
7787
    spawnval = _wspawnv(mode, path->wide, argvlist);
7788
#elif defined(HAVE_RTPSPAWN)
7789
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
7790
#else
7791
    spawnval = _spawnv(mode, path->narrow, argvlist);
7792
#endif
7793
    _Py_END_SUPPRESS_IPH
7794
    Py_END_ALLOW_THREADS
7795
7796
    int saved_errno = errno;
7797
    free_string_array(argvlist, argc);
7798
7799
    if (spawnval == -1) {
7800
        errno = saved_errno;
7801
        posix_error();
7802
        return NULL;
7803
    }
7804
    return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
7805
}
7806
7807
/*[clinic input]
7808
os.spawnve
7809
7810
    mode: int
7811
        Mode of process creation.
7812
    path: path_t
7813
        Path of executable file.
7814
    argv: object
7815
        Tuple or list of strings.
7816
    env: object
7817
        Dictionary of strings mapping to strings.
7818
    /
7819
7820
Execute the program specified by path in a new process.
7821
[clinic start generated code]*/
7822
7823
static PyObject *
7824
os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
7825
                PyObject *env)
7826
/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
7827
{
7828
    EXECV_CHAR **argvlist;
7829
    EXECV_CHAR **envlist;
7830
    PyObject *res = NULL;
7831
    Py_ssize_t argc, i, envc;
7832
    intptr_t spawnval;
7833
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
7834
    Py_ssize_t lastarg = 0;
7835
7836
    /* spawnve has four arguments: (mode, path, argv, env), where
7837
       argv is a list or tuple of strings and env is a dictionary
7838
       like posix.environ. */
7839
7840
    if (PyList_Check(argv)) {
7841
        argc = PyList_Size(argv);
7842
        getitem = PyList_GetItem;
7843
    }
7844
    else if (PyTuple_Check(argv)) {
7845
        argc = PyTuple_Size(argv);
7846
        getitem = PyTuple_GetItem;
7847
    }
7848
    else {
7849
        PyErr_SetString(PyExc_TypeError,
7850
                        "spawnve() arg 2 must be a tuple or list");
7851
        goto fail_0;
7852
    }
7853
    if (argc == 0) {
7854
        PyErr_SetString(PyExc_ValueError,
7855
            "spawnve() arg 2 cannot be empty");
7856
        goto fail_0;
7857
    }
7858
    if (!PyMapping_Check(env)) {
7859
        PyErr_SetString(PyExc_TypeError,
7860
                        "spawnve() arg 3 must be a mapping object");
7861
        goto fail_0;
7862
    }
7863
7864
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
7865
    if (argvlist == NULL) {
7866
        PyErr_NoMemory();
7867
        goto fail_0;
7868
    }
7869
    for (i = 0; i < argc; i++) {
7870
        if (!fsconvert_strdup((*getitem)(argv, i),
7871
                              &argvlist[i]))
7872
        {
7873
            lastarg = i;
7874
            goto fail_1;
7875
        }
7876
        if (i == 0 && !argvlist[0][0]) {
7877
            lastarg = i + 1;
7878
            PyErr_SetString(
7879
                PyExc_ValueError,
7880
                "spawnv() arg 2 first element cannot be empty");
7881
            goto fail_1;
7882
        }
7883
    }
7884
    lastarg = argc;
7885
    argvlist[argc] = NULL;
7886
7887
    envlist = parse_envlist(env, &envc);
7888
    if (envlist == NULL)
7889
        goto fail_1;
7890
7891
#if !defined(HAVE_RTPSPAWN)
7892
    if (mode == _OLD_P_OVERLAY)
7893
        mode = _P_OVERLAY;
7894
#endif
7895
7896
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
7897
        goto fail_2;
7898
    }
7899
7900
    Py_BEGIN_ALLOW_THREADS
7901
    _Py_BEGIN_SUPPRESS_IPH
7902
#ifdef HAVE_WSPAWNV
7903
    spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
7904
#elif defined(HAVE_RTPSPAWN)
7905
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
7906
                           (const char **)envlist);
7907
#else
7908
    spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
7909
#endif
7910
    _Py_END_SUPPRESS_IPH
7911
    Py_END_ALLOW_THREADS
7912
7913
    if (spawnval == -1)
7914
        (void) posix_error();
7915
    else
7916
        res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
7917
7918
  fail_2:
7919
    while (--envc >= 0) {
7920
        PyMem_Free(envlist[envc]);
7921
    }
7922
    PyMem_Free(envlist);
7923
  fail_1:
7924
    free_string_array(argvlist, lastarg);
7925
  fail_0:
7926
    return res;
7927
}
7928
7929
#endif /* HAVE_SPAWNV */
7930
7931
#ifdef HAVE_FORK
7932
7933
/* Helper function to validate arguments.
7934
   Returns 0 on success.  non-zero on failure with a TypeError raised.
7935
   If obj is non-NULL it must be callable.  */
7936
static int
7937
check_null_or_callable(PyObject *obj, const char* obj_name)
7938
0
{
7939
0
    if (obj && !PyCallable_Check(obj)) {
7940
0
        PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
7941
0
                     obj_name, _PyType_Name(Py_TYPE(obj)));
7942
0
        return -1;
7943
0
    }
7944
0
    return 0;
7945
0
}
7946
7947
/*[clinic input]
7948
os.register_at_fork
7949
7950
    *
7951
    before: object=NULL
7952
        A callable to be called in the parent before the fork() syscall.
7953
    after_in_child: object=NULL
7954
        A callable to be called in the child after fork().
7955
    after_in_parent: object=NULL
7956
        A callable to be called in the parent after fork().
7957
7958
Register callables to be called when forking a new process.
7959
7960
'before' callbacks are called in reverse order.
7961
'after_in_child' and 'after_in_parent' callbacks are called in order.
7962
7963
[clinic start generated code]*/
7964
7965
static PyObject *
7966
os_register_at_fork_impl(PyObject *module, PyObject *before,
7967
                         PyObject *after_in_child, PyObject *after_in_parent)
7968
/*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
7969
0
{
7970
0
    PyInterpreterState *interp;
7971
7972
0
    if (!before && !after_in_child && !after_in_parent) {
7973
0
        PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
7974
0
        return NULL;
7975
0
    }
7976
0
    if (check_null_or_callable(before, "before") ||
7977
0
        check_null_or_callable(after_in_child, "after_in_child") ||
7978
0
        check_null_or_callable(after_in_parent, "after_in_parent")) {
7979
0
        return NULL;
7980
0
    }
7981
0
    interp = _PyInterpreterState_GET();
7982
7983
0
    if (register_at_forker(&interp->before_forkers, before)) {
7984
0
        return NULL;
7985
0
    }
7986
0
    if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
7987
0
        return NULL;
7988
0
    }
7989
0
    if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
7990
0
        return NULL;
7991
0
    }
7992
0
    Py_RETURN_NONE;
7993
0
}
7994
#endif /* HAVE_FORK */
7995
7996
#if defined(HAVE_FORK1) || defined(HAVE_FORKPTY) || defined(HAVE_FORK)
7997
// Common code to raise a warning if we detect there is more than one thread
7998
// running in the process. Best effort, silent if unable to count threads.
7999
// Constraint: Quick. Never overcounts. Never leaves an error set.
8000
//
8001
// This should only be called from the parent process after
8002
// PyOS_AfterFork_Parent().
8003
static int
8004
warn_about_fork_with_threads(const char* name)
8005
0
{
8006
    // It's not safe to issue the warning while the world is stopped, because
8007
    // other threads might be holding locks that we need, which would deadlock.
8008
0
    assert(!_PyRuntime.stoptheworld.world_stopped);
8009
8010
    // TODO: Consider making an `os` module API to return the current number
8011
    // of threads in the process. That'd presumably use this platform code but
8012
    // raise an error rather than using the inaccurate fallback.
8013
0
    Py_ssize_t num_python_threads = 0;
8014
#if defined(__APPLE__) && defined(HAVE_GETPID)
8015
    mach_port_t macos_self = mach_task_self();
8016
    mach_port_t macos_task;
8017
    if (task_for_pid(macos_self, getpid(), &macos_task) == KERN_SUCCESS) {
8018
        thread_array_t macos_threads;
8019
        mach_msg_type_number_t macos_n_threads;
8020
        if (task_threads(macos_task, &macos_threads,
8021
                         &macos_n_threads) == KERN_SUCCESS) {
8022
            num_python_threads = macos_n_threads;
8023
        }
8024
    }
8025
#elif defined(__linux__)
8026
    // Linux /proc/self/stat 20th field is the number of threads.
8027
0
    FILE* proc_stat = fopen("/proc/self/stat", "r");
8028
0
    if (proc_stat) {
8029
0
        size_t n;
8030
        // Size chosen arbitrarily. ~60% more bytes than a 20th column index
8031
        // observed on the author's workstation.
8032
0
        char stat_line[160];
8033
0
        n = fread(&stat_line, 1, 159, proc_stat);
8034
0
        stat_line[n] = '\0';
8035
0
        fclose(proc_stat);
8036
8037
0
        char *saveptr = NULL;
8038
0
        char *field = strtok_r(stat_line, " ", &saveptr);
8039
0
        unsigned int idx;
8040
0
        for (idx = 19; idx && field; --idx) {
8041
0
            field = strtok_r(NULL, " ", &saveptr);
8042
0
        }
8043
0
        if (idx == 0 && field) {  // found the 20th field
8044
0
            num_python_threads = atoi(field);  // 0 on error
8045
0
        }
8046
0
    }
8047
0
#endif
8048
0
    if (num_python_threads <= 0) {
8049
        // Fall back to just the number our threading module knows about.
8050
        // An incomplete view of the world, but better than nothing.
8051
0
        PyObject *threading = PyImport_GetModule(&_Py_ID(threading));
8052
0
        if (!threading) {
8053
0
            PyErr_Clear();
8054
0
            return 0;
8055
0
        }
8056
0
        PyObject *threading_active =
8057
0
                PyObject_GetAttr(threading, &_Py_ID(_active));
8058
0
        if (!threading_active) {
8059
0
            PyErr_Clear();
8060
0
            Py_DECREF(threading);
8061
0
            return 0;
8062
0
        }
8063
0
        PyObject *threading_limbo =
8064
0
                PyObject_GetAttr(threading, &_Py_ID(_limbo));
8065
0
        if (!threading_limbo) {
8066
0
            PyErr_Clear();
8067
0
            Py_DECREF(threading);
8068
0
            Py_DECREF(threading_active);
8069
0
            return 0;
8070
0
        }
8071
0
        Py_DECREF(threading);
8072
        // Duplicating what threading.active_count() does but without holding
8073
        // threading._active_limbo_lock so our count could be inaccurate if
8074
        // these dicts are mid-update from another thread.  Not a big deal.
8075
        // Worst case if someone replaced threading._active or threading._limbo
8076
        // with non-dicts, we get -1 from *Length() below and undercount.
8077
        // Nobody should, but we're best effort so we clear errors and move on.
8078
0
        num_python_threads = (PyMapping_Length(threading_active)
8079
0
                              + PyMapping_Length(threading_limbo));
8080
0
        PyErr_Clear();
8081
0
        Py_DECREF(threading_active);
8082
0
        Py_DECREF(threading_limbo);
8083
0
    }
8084
0
    if (num_python_threads > 1) {
8085
0
        return PyErr_WarnFormat(
8086
0
                PyExc_DeprecationWarning, 1,
8087
0
#ifdef HAVE_GETPID
8088
0
                "This process (pid=%d) is multi-threaded, "
8089
#else
8090
                "This process is multi-threaded, "
8091
#endif
8092
0
                "use of %s() may lead to deadlocks in the child.",
8093
0
#ifdef HAVE_GETPID
8094
0
                getpid(),
8095
0
#endif
8096
0
                name);
8097
0
    }
8098
0
    return 0;
8099
0
}
8100
#endif  // HAVE_FORK1 || HAVE_FORKPTY || HAVE_FORK
8101
8102
#ifdef HAVE_FORK1
8103
/*[clinic input]
8104
os.fork1
8105
8106
Fork a child process with a single multiplexed (i.e., not bound) thread.
8107
8108
Return 0 to child process and PID of child to parent process.
8109
[clinic start generated code]*/
8110
8111
static PyObject *
8112
os_fork1_impl(PyObject *module)
8113
/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
8114
{
8115
    pid_t pid;
8116
8117
    PyInterpreterState *interp = _PyInterpreterState_GET();
8118
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8119
        PyErr_SetString(PyExc_PythonFinalizationError,
8120
                        "can't fork at interpreter shutdown");
8121
        return NULL;
8122
    }
8123
    if (!_Py_IsMainInterpreter(interp)) {
8124
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
8125
        return NULL;
8126
    }
8127
    PyOS_BeforeFork();
8128
    pid = fork1();
8129
    int saved_errno = errno;
8130
    if (pid == 0) {
8131
        /* child: this clobbers and resets the import lock. */
8132
        PyOS_AfterFork_Child();
8133
    } else {
8134
        /* parent: release the import lock. */
8135
        PyOS_AfterFork_Parent();
8136
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8137
        if (warn_about_fork_with_threads("fork1") < 0) {
8138
            return NULL;
8139
        }
8140
    }
8141
    if (pid == -1) {
8142
        errno = saved_errno;
8143
        return posix_error();
8144
    }
8145
    return PyLong_FromPid(pid);
8146
}
8147
#endif /* HAVE_FORK1 */
8148
8149
8150
#ifdef HAVE_FORK
8151
/*[clinic input]
8152
os.fork
8153
8154
Fork a child process.
8155
8156
Return 0 to child process and PID of child to parent process.
8157
[clinic start generated code]*/
8158
8159
static PyObject *
8160
os_fork_impl(PyObject *module)
8161
/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
8162
0
{
8163
0
    pid_t pid;
8164
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
8165
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8166
0
        PyErr_SetString(PyExc_PythonFinalizationError,
8167
0
                        "can't fork at interpreter shutdown");
8168
0
        return NULL;
8169
0
    }
8170
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) {
8171
0
        PyErr_SetString(PyExc_RuntimeError,
8172
0
                        "fork not supported for isolated subinterpreters");
8173
0
        return NULL;
8174
0
    }
8175
0
    if (PySys_Audit("os.fork", NULL) < 0) {
8176
0
        return NULL;
8177
0
    }
8178
0
    PyOS_BeforeFork();
8179
0
    pid = fork();
8180
0
    int saved_errno = errno;
8181
0
    if (pid == 0) {
8182
        /* child: this clobbers and resets the import lock. */
8183
0
        PyOS_AfterFork_Child();
8184
0
    } else {
8185
        /* parent: release the import lock. */
8186
0
        PyOS_AfterFork_Parent();
8187
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8188
0
        if (warn_about_fork_with_threads("fork") < 0)
8189
0
            return NULL;
8190
0
    }
8191
0
    if (pid == -1) {
8192
0
        errno = saved_errno;
8193
0
        return posix_error();
8194
0
    }
8195
0
    return PyLong_FromPid(pid);
8196
0
}
8197
#endif /* HAVE_FORK */
8198
8199
8200
#ifdef HAVE_SCHED_H
8201
#ifdef HAVE_SCHED_GET_PRIORITY_MAX
8202
/*[clinic input]
8203
os.sched_get_priority_max
8204
8205
    policy: int
8206
8207
Get the maximum scheduling priority for policy.
8208
[clinic start generated code]*/
8209
8210
static PyObject *
8211
os_sched_get_priority_max_impl(PyObject *module, int policy)
8212
/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
8213
0
{
8214
    /* make sure that errno is cleared before the call */
8215
0
    errno = 0;
8216
0
    int max = sched_get_priority_max(policy);
8217
0
    if (max == -1 && errno)
8218
0
        return posix_error();
8219
0
    return PyLong_FromLong(max);
8220
0
}
8221
8222
8223
/*[clinic input]
8224
os.sched_get_priority_min
8225
8226
    policy: int
8227
8228
Get the minimum scheduling priority for policy.
8229
[clinic start generated code]*/
8230
8231
static PyObject *
8232
os_sched_get_priority_min_impl(PyObject *module, int policy)
8233
/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
8234
0
{
8235
    /* make sure that errno is cleared before the call */
8236
0
    errno = 0;
8237
0
    int min = sched_get_priority_min(policy);
8238
0
    if (min == -1 && errno)
8239
0
        return posix_error();
8240
0
    return PyLong_FromLong(min);
8241
0
}
8242
#endif /* HAVE_SCHED_GET_PRIORITY_MAX */
8243
8244
8245
#ifdef HAVE_SCHED_SETSCHEDULER
8246
/*[clinic input]
8247
os.sched_getscheduler
8248
    pid: pid_t
8249
    /
8250
8251
Get the scheduling policy for the process identified by pid.
8252
8253
Passing 0 for pid returns the scheduling policy for the calling process.
8254
[clinic start generated code]*/
8255
8256
static PyObject *
8257
os_sched_getscheduler_impl(PyObject *module, pid_t pid)
8258
/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
8259
0
{
8260
0
    int policy;
8261
8262
0
    policy = sched_getscheduler(pid);
8263
0
    if (policy < 0)
8264
0
        return posix_error();
8265
0
    return PyLong_FromLong(policy);
8266
0
}
8267
#endif /* HAVE_SCHED_SETSCHEDULER */
8268
8269
8270
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
8271
/*[clinic input]
8272
class os.sched_param "PyObject *" "SchedParamType"
8273
8274
@classmethod
8275
os.sched_param.__new__
8276
8277
    sched_priority: object
8278
        A scheduling parameter.
8279
8280
Currently has only one field: sched_priority
8281
[clinic start generated code]*/
8282
8283
static PyObject *
8284
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
8285
/*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
8286
0
{
8287
0
    PyObject *res;
8288
8289
0
    res = PyStructSequence_New(type);
8290
0
    if (!res)
8291
0
        return NULL;
8292
0
    PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority));
8293
0
    return res;
8294
0
}
8295
8296
static PyObject *
8297
os_sched_param_reduce(PyObject *self, PyObject *Py_UNUSED(dummy))
8298
0
{
8299
0
    return Py_BuildValue("(O(N))", Py_TYPE(self), PyStructSequence_GetItem(self, 0));
8300
0
}
8301
8302
static PyMethodDef os_sched_param_reduce_method = {
8303
    "__reduce__", os_sched_param_reduce, METH_NOARGS | METH_COEXIST, NULL,
8304
};
8305
8306
PyDoc_VAR(os_sched_param__doc__);
8307
8308
static PyStructSequence_Field sched_param_fields[] = {
8309
    {"sched_priority", "the scheduling priority"},
8310
    {0}
8311
};
8312
8313
static PyStructSequence_Desc sched_param_desc = {
8314
    "sched_param", /* name */
8315
    os_sched_param__doc__, /* doc */
8316
    sched_param_fields,
8317
    1
8318
};
8319
8320
static int
8321
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
8322
0
{
8323
0
    long priority;
8324
8325
0
    if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
8326
0
        PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
8327
0
        return 0;
8328
0
    }
8329
0
    priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
8330
0
    if (priority == -1 && PyErr_Occurred())
8331
0
        return 0;
8332
0
    if (priority > INT_MAX || priority < INT_MIN) {
8333
0
        PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
8334
0
        return 0;
8335
0
    }
8336
0
    res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
8337
0
    return 1;
8338
0
}
8339
#endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
8340
8341
8342
#ifdef HAVE_SCHED_SETSCHEDULER
8343
/*[clinic input]
8344
os.sched_setscheduler
8345
8346
    pid: pid_t
8347
    policy: int
8348
    param as param_obj: object
8349
    /
8350
8351
Set the scheduling policy for the process identified by pid.
8352
8353
If pid is 0, the calling process is changed.
8354
param is an instance of sched_param.
8355
[clinic start generated code]*/
8356
8357
static PyObject *
8358
os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
8359
                           PyObject *param_obj)
8360
/*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
8361
0
{
8362
0
    struct sched_param param;
8363
0
    if (!convert_sched_param(module, param_obj, &param)) {
8364
0
        return NULL;
8365
0
    }
8366
8367
    /*
8368
    ** sched_setscheduler() returns 0 in Linux, but the previous
8369
    ** scheduling policy under Solaris/Illumos, and others.
8370
    ** On error, -1 is returned in all Operating Systems.
8371
    */
8372
0
    if (sched_setscheduler(pid, policy, &param) == -1)
8373
0
        return posix_error();
8374
0
    Py_RETURN_NONE;
8375
0
}
8376
#endif  /* HAVE_SCHED_SETSCHEDULER*/
8377
8378
8379
#ifdef HAVE_SCHED_SETPARAM
8380
/*[clinic input]
8381
os.sched_getparam
8382
    pid: pid_t
8383
    /
8384
8385
Returns scheduling parameters for the process identified by pid.
8386
8387
If pid is 0, returns parameters for the calling process.
8388
Return value is an instance of sched_param.
8389
[clinic start generated code]*/
8390
8391
static PyObject *
8392
os_sched_getparam_impl(PyObject *module, pid_t pid)
8393
/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
8394
0
{
8395
0
    struct sched_param param;
8396
0
    PyObject *result;
8397
0
    PyObject *priority;
8398
8399
0
    if (sched_getparam(pid, &param))
8400
0
        return posix_error();
8401
0
    PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
8402
0
    result = PyStructSequence_New((PyTypeObject *)SchedParamType);
8403
0
    if (!result)
8404
0
        return NULL;
8405
0
    priority = PyLong_FromLong(param.sched_priority);
8406
0
    if (!priority) {
8407
0
        Py_DECREF(result);
8408
0
        return NULL;
8409
0
    }
8410
0
    PyStructSequence_SET_ITEM(result, 0, priority);
8411
0
    return result;
8412
0
}
8413
8414
8415
/*[clinic input]
8416
os.sched_setparam
8417
    pid: pid_t
8418
    param as param_obj: object
8419
    /
8420
8421
Set scheduling parameters for the process identified by pid.
8422
8423
If pid is 0, sets parameters for the calling process.
8424
param should be an instance of sched_param.
8425
[clinic start generated code]*/
8426
8427
static PyObject *
8428
os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
8429
/*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
8430
0
{
8431
0
    struct sched_param param;
8432
0
    if (!convert_sched_param(module, param_obj, &param)) {
8433
0
        return NULL;
8434
0
    }
8435
8436
0
    if (sched_setparam(pid, &param))
8437
0
        return posix_error();
8438
0
    Py_RETURN_NONE;
8439
0
}
8440
#endif /* HAVE_SCHED_SETPARAM */
8441
8442
8443
#ifdef HAVE_SCHED_RR_GET_INTERVAL
8444
/*[clinic input]
8445
@permit_long_summary
8446
os.sched_rr_get_interval -> double
8447
    pid: pid_t
8448
    /
8449
8450
Return the round-robin quantum for the process identified by pid, in seconds.
8451
8452
Value returned is a float.
8453
[clinic start generated code]*/
8454
8455
static double
8456
os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
8457
/*[clinic end generated code: output=7e2d935833ab47dc input=cab0b83586776b10]*/
8458
0
{
8459
0
    struct timespec interval;
8460
0
    if (sched_rr_get_interval(pid, &interval)) {
8461
0
        posix_error();
8462
0
        return -1.0;
8463
0
    }
8464
#ifdef _Py_MEMORY_SANITIZER
8465
    __msan_unpoison(&interval, sizeof(interval));
8466
#endif
8467
0
    return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
8468
0
}
8469
#endif /* HAVE_SCHED_RR_GET_INTERVAL */
8470
8471
8472
/*[clinic input]
8473
os.sched_yield
8474
8475
Voluntarily relinquish the CPU.
8476
[clinic start generated code]*/
8477
8478
static PyObject *
8479
os_sched_yield_impl(PyObject *module)
8480
/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
8481
0
{
8482
0
    int result;
8483
0
    Py_BEGIN_ALLOW_THREADS
8484
0
    result = sched_yield();
8485
0
    Py_END_ALLOW_THREADS
8486
0
    if (result < 0) {
8487
0
        return posix_error();
8488
0
    }
8489
0
    Py_RETURN_NONE;
8490
0
}
8491
8492
#ifdef HAVE_SCHED_SETAFFINITY
8493
/* The minimum number of CPUs allocated in a cpu_set_t */
8494
static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
8495
8496
/*[clinic input]
8497
os.sched_setaffinity
8498
    pid: pid_t
8499
    mask : object
8500
    /
8501
8502
Set the CPU affinity of the process identified by pid to mask.
8503
8504
mask should be an iterable of integers identifying CPUs.
8505
[clinic start generated code]*/
8506
8507
static PyObject *
8508
os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
8509
/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
8510
0
{
8511
0
    int ncpus;
8512
0
    size_t setsize;
8513
0
    cpu_set_t *cpu_set = NULL;
8514
0
    PyObject *iterator = NULL, *item;
8515
8516
0
    iterator = PyObject_GetIter(mask);
8517
0
    if (iterator == NULL)
8518
0
        return NULL;
8519
8520
0
    ncpus = NCPUS_START;
8521
0
    setsize = CPU_ALLOC_SIZE(ncpus);
8522
0
    cpu_set = CPU_ALLOC(ncpus);
8523
0
    if (cpu_set == NULL) {
8524
0
        PyErr_NoMemory();
8525
0
        goto error;
8526
0
    }
8527
0
    CPU_ZERO_S(setsize, cpu_set);
8528
8529
0
    while ((item = PyIter_Next(iterator))) {
8530
0
        long cpu;
8531
0
        if (!PyIndex_Check(item)) {
8532
0
            PyErr_Format(PyExc_TypeError,
8533
0
                        "expected an iterator of ints, "
8534
0
                        "but iterator yielded %R",
8535
0
                        Py_TYPE(item));
8536
0
            Py_DECREF(item);
8537
0
            goto error;
8538
0
        }
8539
0
        cpu = PyLong_AsLong(item);
8540
0
        Py_DECREF(item);
8541
0
        if (cpu < 0) {
8542
0
            if (!PyErr_Occurred())
8543
0
                PyErr_SetString(PyExc_ValueError, "negative CPU number");
8544
0
            goto error;
8545
0
        }
8546
0
        if (cpu > INT_MAX - 1) {
8547
0
            PyErr_SetString(PyExc_OverflowError, "CPU number too large");
8548
0
            goto error;
8549
0
        }
8550
0
        if (cpu >= ncpus) {
8551
            /* Grow CPU mask to fit the CPU number */
8552
0
            int newncpus = ncpus;
8553
0
            cpu_set_t *newmask;
8554
0
            size_t newsetsize;
8555
0
            while (newncpus <= cpu) {
8556
0
                if (newncpus > INT_MAX / 2)
8557
0
                    newncpus = cpu + 1;
8558
0
                else
8559
0
                    newncpus = newncpus * 2;
8560
0
            }
8561
0
            newmask = CPU_ALLOC(newncpus);
8562
0
            if (newmask == NULL) {
8563
0
                PyErr_NoMemory();
8564
0
                goto error;
8565
0
            }
8566
0
            newsetsize = CPU_ALLOC_SIZE(newncpus);
8567
0
            CPU_ZERO_S(newsetsize, newmask);
8568
0
            memcpy(newmask, cpu_set, setsize);
8569
0
            CPU_FREE(cpu_set);
8570
0
            setsize = newsetsize;
8571
0
            cpu_set = newmask;
8572
0
            ncpus = newncpus;
8573
0
        }
8574
0
        CPU_SET_S(cpu, setsize, cpu_set);
8575
0
    }
8576
0
    if (PyErr_Occurred()) {
8577
0
        goto error;
8578
0
    }
8579
0
    Py_CLEAR(iterator);
8580
8581
0
    if (sched_setaffinity(pid, setsize, cpu_set)) {
8582
0
        posix_error();
8583
0
        goto error;
8584
0
    }
8585
0
    CPU_FREE(cpu_set);
8586
0
    Py_RETURN_NONE;
8587
8588
0
error:
8589
0
    if (cpu_set)
8590
0
        CPU_FREE(cpu_set);
8591
0
    Py_XDECREF(iterator);
8592
0
    return NULL;
8593
0
}
8594
8595
8596
/*[clinic input]
8597
@permit_long_summary
8598
os.sched_getaffinity
8599
    pid: pid_t
8600
    /
8601
8602
Return the affinity of the process identified by pid (or the current process if zero).
8603
8604
The affinity is returned as a set of CPU identifiers.
8605
[clinic start generated code]*/
8606
8607
static PyObject *
8608
os_sched_getaffinity_impl(PyObject *module, pid_t pid)
8609
/*[clinic end generated code: output=f726f2c193c17a4f input=cb79ff13579ef091]*/
8610
0
{
8611
0
    int ncpus = NCPUS_START;
8612
0
    size_t setsize;
8613
0
    cpu_set_t *mask;
8614
8615
0
    while (1) {
8616
0
        setsize = CPU_ALLOC_SIZE(ncpus);
8617
0
        mask = CPU_ALLOC(ncpus);
8618
0
        if (mask == NULL) {
8619
0
            return PyErr_NoMemory();
8620
0
        }
8621
0
        if (sched_getaffinity(pid, setsize, mask) == 0) {
8622
0
            break;
8623
0
        }
8624
0
        CPU_FREE(mask);
8625
0
        if (errno != EINVAL) {
8626
0
            return posix_error();
8627
0
        }
8628
0
        if (ncpus > INT_MAX / 2) {
8629
0
            PyErr_SetString(PyExc_OverflowError,
8630
0
                            "could not allocate a large enough CPU set");
8631
0
            return NULL;
8632
0
        }
8633
0
        ncpus *= 2;
8634
0
    }
8635
8636
0
    PyObject *res = PySet_New(NULL);
8637
0
    if (res == NULL) {
8638
0
        goto error;
8639
0
    }
8640
8641
0
    int cpu = 0;
8642
0
    int count = CPU_COUNT_S(setsize, mask);
8643
0
    for (; count; cpu++) {
8644
0
        if (CPU_ISSET_S(cpu, setsize, mask)) {
8645
0
            PyObject *cpu_num = PyLong_FromLong(cpu);
8646
0
            --count;
8647
0
            if (cpu_num == NULL) {
8648
0
                goto error;
8649
0
            }
8650
0
            if (PySet_Add(res, cpu_num)) {
8651
0
                Py_DECREF(cpu_num);
8652
0
                goto error;
8653
0
            }
8654
0
            Py_DECREF(cpu_num);
8655
0
        }
8656
0
    }
8657
0
    CPU_FREE(mask);
8658
0
    return res;
8659
8660
0
error:
8661
0
    if (mask) {
8662
0
        CPU_FREE(mask);
8663
0
    }
8664
0
    Py_XDECREF(res);
8665
0
    return NULL;
8666
0
}
8667
#endif /* HAVE_SCHED_SETAFFINITY */
8668
8669
#endif /* HAVE_SCHED_H */
8670
8671
8672
#ifdef HAVE_POSIX_OPENPT
8673
/*[clinic input]
8674
os.posix_openpt -> int
8675
8676
    oflag: int
8677
    /
8678
8679
Open and return a file descriptor for a master pseudo-terminal device.
8680
8681
Performs a posix_openpt() C function call. The oflag argument is used to
8682
set file status flags and file access modes as specified in the manual page
8683
of posix_openpt() of your system.
8684
[clinic start generated code]*/
8685
8686
static int
8687
os_posix_openpt_impl(PyObject *module, int oflag)
8688
/*[clinic end generated code: output=ee0bc2624305fc79 input=0de33d0e29693caa]*/
8689
0
{
8690
0
    int fd;
8691
8692
0
#if defined(O_CLOEXEC)
8693
0
    oflag |= O_CLOEXEC;
8694
0
#endif
8695
8696
0
    fd = posix_openpt(oflag);
8697
0
    if (fd == -1) {
8698
0
        posix_error();
8699
0
        return -1;
8700
0
    }
8701
8702
    // Just in case, likely a no-op given O_CLOEXEC above.
8703
0
    if (_Py_set_inheritable(fd, 0, NULL) < 0) {
8704
0
        close(fd);
8705
0
        return -1;
8706
0
    }
8707
8708
0
    return fd;
8709
0
}
8710
#endif /* HAVE_POSIX_OPENPT */
8711
8712
#ifdef HAVE_GRANTPT
8713
/*[clinic input]
8714
os.grantpt
8715
8716
    fd: fildes
8717
        File descriptor of a master pseudo-terminal device.
8718
    /
8719
8720
Grant access to the slave pseudo-terminal device.
8721
8722
Performs a grantpt() C function call.
8723
[clinic start generated code]*/
8724
8725
static PyObject *
8726
os_grantpt_impl(PyObject *module, int fd)
8727
/*[clinic end generated code: output=dfd580015cf548ab input=0668e3b96760e849]*/
8728
0
{
8729
0
    int ret;
8730
0
    int saved_errno;
8731
0
    PyOS_sighandler_t sig_saved;
8732
8733
0
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
8734
8735
0
    ret = grantpt(fd);
8736
0
    if (ret == -1)
8737
0
        saved_errno = errno;
8738
8739
0
    PyOS_setsig(SIGCHLD, sig_saved);
8740
8741
0
    if (ret == -1) {
8742
0
        errno = saved_errno;
8743
0
        return posix_error();
8744
0
    }
8745
8746
0
    Py_RETURN_NONE;
8747
0
}
8748
#endif /* HAVE_GRANTPT */
8749
8750
#ifdef HAVE_UNLOCKPT
8751
/*[clinic input]
8752
os.unlockpt
8753
8754
    fd: fildes
8755
        File descriptor of a master pseudo-terminal device.
8756
    /
8757
8758
Unlock a pseudo-terminal master/slave pair.
8759
8760
Performs an unlockpt() C function call.
8761
[clinic start generated code]*/
8762
8763
static PyObject *
8764
os_unlockpt_impl(PyObject *module, int fd)
8765
/*[clinic end generated code: output=e08d354dec12d30c input=de7ab1f59f69a2b4]*/
8766
0
{
8767
0
    if (unlockpt(fd) == -1)
8768
0
        return posix_error();
8769
8770
0
    Py_RETURN_NONE;
8771
0
}
8772
#endif /* HAVE_UNLOCKPT */
8773
8774
#if defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R)
8775
static PyObject *
8776
py_ptsname(int fd)
8777
0
{
8778
0
    // POSIX manpage: Upon failure, ptsname() shall return a null pointer
8779
0
    // and may set errno. Always initialize errno to avoid undefined behavior.
8780
0
    errno = 0;
8781
0
    char *name = ptsname(fd);
8782
0
    if (name == NULL) {
8783
0
        return posix_error();
8784
0
    }
8785
0
    return PyUnicode_DecodeFSDefault(name);
8786
0
}
8787
8788
/*[clinic input]
8789
os.ptsname
8790
8791
    fd: fildes
8792
        File descriptor of a master pseudo-terminal device.
8793
    /
8794
8795
Return the name of the slave pseudo-terminal device.
8796
8797
If the ptsname_r() C function is available, it is called;
8798
otherwise, performs a ptsname() C function call.
8799
[clinic start generated code]*/
8800
8801
static PyObject *
8802
os_ptsname_impl(PyObject *module, int fd)
8803
/*[clinic end generated code: output=ef300fadc5675872 input=1369ccc0546f3130]*/
8804
0
{
8805
0
#ifdef HAVE_PTSNAME_R
8806
0
    int ret;
8807
0
    char name[MAXPATHLEN+1];
8808
8809
0
    if (HAVE_PTSNAME_R_RUNTIME) {
8810
0
        ret = ptsname_r(fd, name, sizeof(name));
8811
0
    }
8812
0
    else {
8813
        // fallback to ptsname() if ptsname_r() is not available in runtime.
8814
0
        return py_ptsname(fd);
8815
0
    }
8816
0
    if (ret != 0) {
8817
0
        errno = ret;
8818
0
        return posix_error();
8819
0
    }
8820
8821
0
    return PyUnicode_DecodeFSDefault(name);
8822
#else
8823
    return py_ptsname(fd);
8824
#endif /* HAVE_PTSNAME_R */
8825
0
}
8826
#endif /* defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) */
8827
8828
/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
8829
#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
8830
#  define DEV_PTY_FILE "/dev/ptc"
8831
#  define HAVE_DEV_PTMX
8832
#else
8833
#  define DEV_PTY_FILE "/dev/ptmx"
8834
#endif
8835
8836
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
8837
#ifdef HAVE_PTY_H
8838
#include <pty.h>
8839
#elif defined(HAVE_LIBUTIL_H)
8840
#include <libutil.h>
8841
#elif defined(HAVE_UTIL_H)
8842
#include <util.h>
8843
#endif /* HAVE_PTY_H */
8844
#ifdef HAVE_UTMP_H
8845
#include <utmp.h>
8846
#endif /* HAVE_UTMP_H */
8847
#ifdef HAVE_STROPTS_H
8848
#include <stropts.h>
8849
#endif
8850
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
8851
8852
8853
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
8854
/*[clinic input]
8855
os.openpty
8856
8857
Open a pseudo-terminal.
8858
8859
Return a tuple of (master_fd, slave_fd) containing open file descriptors
8860
for both the master and slave ends.
8861
[clinic start generated code]*/
8862
8863
static PyObject *
8864
os_openpty_impl(PyObject *module)
8865
/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
8866
0
{
8867
0
    int master_fd = -1, slave_fd = -1;
8868
#ifndef HAVE_OPENPTY
8869
    char * slave_name;
8870
#endif
8871
#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
8872
    PyOS_sighandler_t sig_saved;
8873
#if defined(__sun) && defined(__SVR4)
8874
    extern char *ptsname(int fildes);
8875
#endif
8876
#endif
8877
8878
0
#ifdef HAVE_OPENPTY
8879
0
    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
8880
0
        goto posix_error;
8881
8882
0
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
8883
0
        goto error;
8884
0
    if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
8885
0
        goto error;
8886
8887
#elif defined(HAVE__GETPTY)
8888
    slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
8889
    if (slave_name == NULL)
8890
        goto posix_error;
8891
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
8892
        goto error;
8893
8894
    slave_fd = _Py_open(slave_name, O_RDWR);
8895
    if (slave_fd < 0)
8896
        goto error;
8897
8898
#else
8899
    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
8900
    if (master_fd < 0)
8901
        goto posix_error;
8902
8903
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
8904
8905
    /* change permission of slave */
8906
    if (grantpt(master_fd) < 0) {
8907
        int saved_errno = errno;
8908
        PyOS_setsig(SIGCHLD, sig_saved);
8909
        errno = saved_errno;
8910
        goto posix_error;
8911
    }
8912
8913
    /* unlock slave */
8914
    if (unlockpt(master_fd) < 0) {
8915
        int saved_errno = errno;
8916
        PyOS_setsig(SIGCHLD, sig_saved);
8917
        errno = saved_errno;
8918
        goto posix_error;
8919
    }
8920
8921
    PyOS_setsig(SIGCHLD, sig_saved);
8922
8923
    slave_name = ptsname(master_fd); /* get name of slave */
8924
    if (slave_name == NULL)
8925
        goto posix_error;
8926
8927
    slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
8928
    if (slave_fd == -1)
8929
        goto error;
8930
8931
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
8932
        goto posix_error;
8933
8934
#if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
8935
    ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
8936
    ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
8937
#ifndef __hpux
8938
    ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
8939
#endif /* __hpux */
8940
#endif /* HAVE_CYGWIN */
8941
#endif /* HAVE_OPENPTY */
8942
8943
0
    return Py_BuildValue("(ii)", master_fd, slave_fd);
8944
8945
0
posix_error:
8946
0
    posix_error();
8947
0
error:
8948
0
    if (master_fd != -1)
8949
0
        close(master_fd);
8950
0
    if (slave_fd != -1)
8951
0
        close(slave_fd);
8952
0
    return NULL;
8953
0
}
8954
#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
8955
8956
8957
#if defined(HAVE_SETSID) && defined(TIOCSCTTY)
8958
#define HAVE_FALLBACK_LOGIN_TTY 1
8959
#endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
8960
8961
#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
8962
/*[clinic input]
8963
os.login_tty
8964
8965
    fd: fildes
8966
    /
8967
8968
Prepare the tty of which fd is a file descriptor for a new login session.
8969
8970
Make the calling process a session leader; make the tty the
8971
controlling tty, the stdin, the stdout, and the stderr of the
8972
calling process; close fd.
8973
[clinic start generated code]*/
8974
8975
static PyObject *
8976
os_login_tty_impl(PyObject *module, int fd)
8977
/*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
8978
0
{
8979
0
#ifdef HAVE_LOGIN_TTY
8980
0
    if (login_tty(fd) == -1) {
8981
0
        return posix_error();
8982
0
    }
8983
#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
8984
    /* Establish a new session. */
8985
    if (setsid() == -1) {
8986
        return posix_error();
8987
    }
8988
8989
    /* The tty becomes the controlling terminal. */
8990
    if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
8991
        return posix_error();
8992
    }
8993
8994
    /* The tty becomes stdin/stdout/stderr */
8995
    if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
8996
        return posix_error();
8997
    }
8998
    if (fd > 2) {
8999
        close(fd);
9000
    }
9001
#endif /* HAVE_LOGIN_TTY */
9002
0
    Py_RETURN_NONE;
9003
0
}
9004
#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
9005
9006
9007
#ifdef HAVE_FORKPTY
9008
/*[clinic input]
9009
os.forkpty
9010
9011
Fork a new process with a new pseudo-terminal as controlling tty.
9012
9013
Returns a tuple of (pid, master_fd).
9014
Like fork(), return pid of 0 to the child process,
9015
and pid of child to the parent process.
9016
To both, return fd of newly opened pseudo-terminal.
9017
[clinic start generated code]*/
9018
9019
static PyObject *
9020
os_forkpty_impl(PyObject *module)
9021
/*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
9022
0
{
9023
0
    int master_fd = -1;
9024
0
    pid_t pid;
9025
9026
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
9027
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
9028
0
        PyErr_SetString(PyExc_PythonFinalizationError,
9029
0
                        "can't fork at interpreter shutdown");
9030
0
        return NULL;
9031
0
    }
9032
0
    if (!_Py_IsMainInterpreter(interp)) {
9033
0
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
9034
0
        return NULL;
9035
0
    }
9036
0
    if (PySys_Audit("os.forkpty", NULL) < 0) {
9037
0
        return NULL;
9038
0
    }
9039
0
    PyOS_BeforeFork();
9040
0
    pid = forkpty(&master_fd, NULL, NULL, NULL);
9041
0
    if (pid == 0) {
9042
        /* child: this clobbers and resets the import lock. */
9043
0
        PyOS_AfterFork_Child();
9044
0
    } else {
9045
        /* parent: release the import lock. */
9046
0
        PyOS_AfterFork_Parent();
9047
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
9048
0
        if (warn_about_fork_with_threads("forkpty") < 0)
9049
0
            return NULL;
9050
0
    }
9051
0
    if (pid == -1) {
9052
0
        return posix_error();
9053
0
    }
9054
0
    return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
9055
0
}
9056
#endif /* HAVE_FORKPTY */
9057
9058
9059
#ifdef HAVE_GETEGID
9060
/*[clinic input]
9061
os.getegid
9062
9063
Return the current process's effective group id.
9064
[clinic start generated code]*/
9065
9066
static PyObject *
9067
os_getegid_impl(PyObject *module)
9068
/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
9069
22
{
9070
22
    return _PyLong_FromGid(getegid());
9071
22
}
9072
#endif /* HAVE_GETEGID */
9073
9074
9075
#ifdef HAVE_GETEUID
9076
/*[clinic input]
9077
os.geteuid
9078
9079
Return the current process's effective user id.
9080
[clinic start generated code]*/
9081
9082
static PyObject *
9083
os_geteuid_impl(PyObject *module)
9084
/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
9085
22
{
9086
22
    return _PyLong_FromUid(geteuid());
9087
22
}
9088
#endif /* HAVE_GETEUID */
9089
9090
9091
#ifdef HAVE_GETGID
9092
/*[clinic input]
9093
os.getgid
9094
9095
Return the current process's group id.
9096
[clinic start generated code]*/
9097
9098
static PyObject *
9099
os_getgid_impl(PyObject *module)
9100
/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
9101
22
{
9102
22
    return _PyLong_FromGid(getgid());
9103
22
}
9104
#endif /* HAVE_GETGID */
9105
9106
9107
#if defined(HAVE_GETPID)
9108
/*[clinic input]
9109
os.getpid
9110
9111
Return the current process id.
9112
[clinic start generated code]*/
9113
9114
static PyObject *
9115
os_getpid_impl(PyObject *module)
9116
/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
9117
0
{
9118
0
#if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
9119
0
    return PyLong_FromPid(getpid());
9120
#else
9121
    return PyLong_FromUnsignedLong(GetCurrentProcessId());
9122
#endif
9123
0
}
9124
#endif /* defined(HAVE_GETPID) */
9125
9126
#ifdef NGROUPS_MAX
9127
0
#define MAX_GROUPS NGROUPS_MAX
9128
#else
9129
    /* defined to be 16 on Solaris7, so this should be a small number */
9130
#define MAX_GROUPS 64
9131
#endif
9132
9133
#ifdef HAVE_GETGROUPLIST
9134
9135
#ifdef __APPLE__
9136
/*[clinic input]
9137
os.getgrouplist
9138
9139
    user: str
9140
        username to lookup
9141
    group as basegid: int
9142
        base group id of the user
9143
    /
9144
9145
Returns a list of groups to which a user belongs.
9146
[clinic start generated code]*/
9147
9148
static PyObject *
9149
os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
9150
/*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
9151
#else
9152
/*[clinic input]
9153
os.getgrouplist
9154
9155
    user: str
9156
        username to lookup
9157
    group as basegid: gid_t
9158
        base group id of the user
9159
    /
9160
9161
Returns a list of groups to which a user belongs.
9162
[clinic start generated code]*/
9163
9164
static PyObject *
9165
os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
9166
/*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
9167
#endif
9168
0
{
9169
0
    int i, ngroups;
9170
0
    PyObject *list;
9171
#ifdef __APPLE__
9172
    int *groups;
9173
#else
9174
0
    gid_t *groups;
9175
0
#endif
9176
9177
    /*
9178
     * NGROUPS_MAX is defined by POSIX.1 as the maximum
9179
     * number of supplemental groups a users can belong to.
9180
     * We have to increment it by one because
9181
     * getgrouplist() returns both the supplemental groups
9182
     * and the primary group, i.e. all of the groups the
9183
     * user belongs to.
9184
     */
9185
0
    ngroups = 1 + MAX_GROUPS;
9186
9187
0
    while (1) {
9188
#ifdef __APPLE__
9189
        groups = PyMem_New(int, ngroups);
9190
#else
9191
0
        groups = PyMem_New(gid_t, ngroups);
9192
0
#endif
9193
0
        if (groups == NULL) {
9194
0
            return PyErr_NoMemory();
9195
0
        }
9196
9197
0
        int old_ngroups = ngroups;
9198
0
        if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
9199
            /* Success */
9200
0
            break;
9201
0
        }
9202
9203
        /* getgrouplist() fails if the group list is too small */
9204
0
        PyMem_Free(groups);
9205
9206
0
        if (ngroups > old_ngroups) {
9207
            /* If the group list is too small, the glibc implementation of
9208
               getgrouplist() sets ngroups to the total number of groups and
9209
               returns -1. */
9210
0
        }
9211
0
        else {
9212
            /* Double the group list size */
9213
0
            if (ngroups > INT_MAX / 2) {
9214
0
                return PyErr_NoMemory();
9215
0
            }
9216
0
            ngroups *= 2;
9217
0
        }
9218
9219
        /* Retry getgrouplist() with a larger group list */
9220
0
    }
9221
9222
#ifdef _Py_MEMORY_SANITIZER
9223
    /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
9224
    __msan_unpoison(&ngroups, sizeof(ngroups));
9225
    __msan_unpoison(groups, ngroups*sizeof(*groups));
9226
#endif
9227
9228
0
    list = PyList_New(ngroups);
9229
0
    if (list == NULL) {
9230
0
        PyMem_Free(groups);
9231
0
        return NULL;
9232
0
    }
9233
9234
0
    for (i = 0; i < ngroups; i++) {
9235
#ifdef __APPLE__
9236
        PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
9237
#else
9238
0
        PyObject *o = _PyLong_FromGid(groups[i]);
9239
0
#endif
9240
0
        if (o == NULL) {
9241
0
            Py_DECREF(list);
9242
0
            PyMem_Free(groups);
9243
0
            return NULL;
9244
0
        }
9245
0
        PyList_SET_ITEM(list, i, o);
9246
0
    }
9247
9248
0
    PyMem_Free(groups);
9249
9250
0
    return list;
9251
0
}
9252
#endif /* HAVE_GETGROUPLIST */
9253
9254
9255
#ifdef HAVE_GETGROUPS
9256
/*[clinic input]
9257
os.getgroups
9258
9259
Return list of supplemental group IDs for the process.
9260
[clinic start generated code]*/
9261
9262
static PyObject *
9263
os_getgroups_impl(PyObject *module)
9264
/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
9265
0
{
9266
    // Call getgroups with length 0 to get the actual number of groups
9267
0
    int n = getgroups(0, NULL);
9268
0
    if (n < 0) {
9269
0
        return posix_error();
9270
0
    }
9271
9272
0
    if (n == 0) {
9273
0
        return PyList_New(0);
9274
0
    }
9275
9276
0
    gid_t *grouplist = PyMem_New(gid_t, n);
9277
0
    if (grouplist == NULL) {
9278
0
        return PyErr_NoMemory();
9279
0
    }
9280
9281
0
    n = getgroups(n, grouplist);
9282
0
    if (n == -1) {
9283
0
        posix_error();
9284
0
        PyMem_Free(grouplist);
9285
0
        return NULL;
9286
0
    }
9287
9288
0
    PyObject *result = PyList_New(n);
9289
0
    if (result == NULL) {
9290
0
        goto error;
9291
0
    }
9292
9293
0
    for (int i = 0; i < n; ++i) {
9294
0
        PyObject *group = _PyLong_FromGid(grouplist[i]);
9295
0
        if (group == NULL) {
9296
0
            goto error;
9297
0
        }
9298
0
        PyList_SET_ITEM(result, i, group);
9299
0
    }
9300
0
    PyMem_Free(grouplist);
9301
9302
0
    return result;
9303
9304
0
error:
9305
0
    PyMem_Free(grouplist);
9306
0
    Py_XDECREF(result);
9307
0
    return NULL;
9308
0
}
9309
#endif /* HAVE_GETGROUPS */
9310
9311
#ifdef HAVE_INITGROUPS
9312
#ifdef __APPLE__
9313
/*[clinic input]
9314
os.initgroups
9315
9316
    username as oname: FSConverter
9317
    gid: int
9318
    /
9319
9320
Initialize the group access list.
9321
9322
Call the system initgroups() to initialize the group access list with all of
9323
the groups of which the specified username is a member, plus the specified
9324
group id.
9325
[clinic start generated code]*/
9326
9327
static PyObject *
9328
os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
9329
/*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/
9330
#else
9331
/*[clinic input]
9332
os.initgroups
9333
9334
    username as oname: FSConverter
9335
    gid: gid_t
9336
    /
9337
9338
Initialize the group access list.
9339
9340
Call the system initgroups() to initialize the group access list with all of
9341
the groups of which the specified username is a member, plus the specified
9342
group id.
9343
[clinic start generated code]*/
9344
9345
static PyObject *
9346
os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
9347
/*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/
9348
#endif
9349
0
{
9350
0
    const char *username = PyBytes_AS_STRING(oname);
9351
9352
0
    if (initgroups(username, gid) == -1)
9353
0
        return PyErr_SetFromErrno(PyExc_OSError);
9354
9355
0
    Py_RETURN_NONE;
9356
0
}
9357
#endif /* HAVE_INITGROUPS */
9358
9359
9360
#ifdef HAVE_GETPGID
9361
/*[clinic input]
9362
os.getpgid
9363
9364
    pid: pid_t
9365
9366
Call the system call getpgid(), and return the result.
9367
[clinic start generated code]*/
9368
9369
static PyObject *
9370
os_getpgid_impl(PyObject *module, pid_t pid)
9371
/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
9372
0
{
9373
0
    pid_t pgid = getpgid(pid);
9374
0
    if (pgid < 0)
9375
0
        return posix_error();
9376
0
    return PyLong_FromPid(pgid);
9377
0
}
9378
#endif /* HAVE_GETPGID */
9379
9380
9381
#ifdef HAVE_GETPGRP
9382
/*[clinic input]
9383
os.getpgrp
9384
9385
Return the current process group id.
9386
[clinic start generated code]*/
9387
9388
static PyObject *
9389
os_getpgrp_impl(PyObject *module)
9390
/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
9391
0
{
9392
#ifdef GETPGRP_HAVE_ARG
9393
    return PyLong_FromPid(getpgrp(0));
9394
#else /* GETPGRP_HAVE_ARG */
9395
0
    return PyLong_FromPid(getpgrp());
9396
0
#endif /* GETPGRP_HAVE_ARG */
9397
0
}
9398
#endif /* HAVE_GETPGRP */
9399
9400
9401
#ifdef HAVE_SETPGRP
9402
/*[clinic input]
9403
os.setpgrp
9404
9405
Make the current process the leader of its process group.
9406
[clinic start generated code]*/
9407
9408
static PyObject *
9409
os_setpgrp_impl(PyObject *module)
9410
/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
9411
0
{
9412
#ifdef SETPGRP_HAVE_ARG
9413
    if (setpgrp(0, 0) < 0)
9414
#else /* SETPGRP_HAVE_ARG */
9415
0
    if (setpgrp() < 0)
9416
0
#endif /* SETPGRP_HAVE_ARG */
9417
0
        return posix_error();
9418
0
    Py_RETURN_NONE;
9419
0
}
9420
#endif /* HAVE_SETPGRP */
9421
9422
#ifdef HAVE_GETPPID
9423
9424
#ifdef MS_WINDOWS
9425
#include <winternl.h>
9426
#include <ProcessSnapshot.h>
9427
9428
// The structure definition in winternl.h may be incomplete.
9429
// This structure is the full version from the MSDN documentation.
9430
typedef struct _PROCESS_BASIC_INFORMATION_FULL {
9431
    NTSTATUS ExitStatus;
9432
    PVOID PebBaseAddress;
9433
    ULONG_PTR AffinityMask;
9434
    LONG BasePriority;
9435
    ULONG_PTR UniqueProcessId;
9436
    ULONG_PTR InheritedFromUniqueProcessId;
9437
} PROCESS_BASIC_INFORMATION_FULL;
9438
9439
typedef NTSTATUS (NTAPI *PNT_QUERY_INFORMATION_PROCESS) (
9440
    IN    HANDLE           ProcessHandle,
9441
    IN    PROCESSINFOCLASS ProcessInformationClass,
9442
    OUT   PVOID            ProcessInformation,
9443
    IN    ULONG            ProcessInformationLength,
9444
    OUT   PULONG           ReturnLength OPTIONAL);
9445
9446
// This function returns the process ID of the parent process.
9447
// Returns 0 on failure.
9448
static ULONG
9449
win32_getppid_fast(void)
9450
{
9451
    NTSTATUS status;
9452
    HMODULE ntdll;
9453
    PNT_QUERY_INFORMATION_PROCESS pNtQueryInformationProcess;
9454
    PROCESS_BASIC_INFORMATION_FULL basic_information;
9455
    static ULONG cached_ppid = 0;
9456
9457
    if (cached_ppid) {
9458
        // No need to query the kernel again.
9459
        return cached_ppid;
9460
    }
9461
9462
    ntdll = GetModuleHandleW(L"ntdll.dll");
9463
    if (!ntdll) {
9464
        return 0;
9465
    }
9466
9467
    pNtQueryInformationProcess = (PNT_QUERY_INFORMATION_PROCESS) GetProcAddress(ntdll, "NtQueryInformationProcess");
9468
    if (!pNtQueryInformationProcess) {
9469
        return 0;
9470
    }
9471
9472
    status = pNtQueryInformationProcess(GetCurrentProcess(),
9473
                                        ProcessBasicInformation,
9474
                                        &basic_information,
9475
                                        sizeof(basic_information),
9476
                                        NULL);
9477
9478
    if (!NT_SUCCESS(status)) {
9479
        return 0;
9480
    }
9481
9482
    // Perform sanity check on the parent process ID we received from NtQueryInformationProcess.
9483
    // The check covers values which exceed the 32-bit range (if running on x64) as well as
9484
    // zero and (ULONG) -1.
9485
9486
    if (basic_information.InheritedFromUniqueProcessId == 0 ||
9487
        basic_information.InheritedFromUniqueProcessId >= ULONG_MAX)
9488
    {
9489
        return 0;
9490
    }
9491
9492
    // Now that we have reached this point, the BasicInformation.InheritedFromUniqueProcessId
9493
    // structure member contains a ULONG_PTR which represents the process ID of our parent
9494
    // process. This process ID will be correctly returned even if the parent process has
9495
    // exited or been terminated.
9496
9497
    cached_ppid = (ULONG) basic_information.InheritedFromUniqueProcessId;
9498
    return cached_ppid;
9499
}
9500
9501
static PyObject*
9502
win32_getppid(void)
9503
{
9504
    DWORD error;
9505
    PyObject* result = NULL;
9506
    HANDLE process = GetCurrentProcess();
9507
    HPSS snapshot = NULL;
9508
    ULONG pid;
9509
9510
    pid = win32_getppid_fast();
9511
    if (pid != 0) {
9512
        return PyLong_FromUnsignedLong(pid);
9513
    }
9514
9515
    // If failure occurs in win32_getppid_fast(), fall back to using the PSS API.
9516
9517
    error = PssCaptureSnapshot(process, PSS_CAPTURE_NONE, 0, &snapshot);
9518
    if (error != ERROR_SUCCESS) {
9519
        return PyErr_SetFromWindowsErr(error);
9520
    }
9521
9522
    PSS_PROCESS_INFORMATION info;
9523
    error = PssQuerySnapshot(snapshot, PSS_QUERY_PROCESS_INFORMATION, &info,
9524
                             sizeof(info));
9525
    if (error == ERROR_SUCCESS) {
9526
        result = PyLong_FromUnsignedLong(info.ParentProcessId);
9527
    }
9528
    else {
9529
        result = PyErr_SetFromWindowsErr(error);
9530
    }
9531
9532
    PssFreeSnapshot(process, snapshot);
9533
    return result;
9534
}
9535
#endif /*MS_WINDOWS*/
9536
9537
9538
/*[clinic input]
9539
os.getppid
9540
9541
Return the parent's process id.
9542
9543
If the parent process has already exited, Windows machines will still
9544
return its id; others systems will return the id of the 'init' process (1).
9545
[clinic start generated code]*/
9546
9547
static PyObject *
9548
os_getppid_impl(PyObject *module)
9549
/*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
9550
0
{
9551
#ifdef MS_WINDOWS
9552
    return win32_getppid();
9553
#else
9554
0
    return PyLong_FromPid(getppid());
9555
0
#endif
9556
0
}
9557
#endif /* HAVE_GETPPID */
9558
9559
9560
#ifdef HAVE_GETLOGIN
9561
/*[clinic input]
9562
os.getlogin
9563
9564
Return the actual login name.
9565
[clinic start generated code]*/
9566
9567
static PyObject *
9568
os_getlogin_impl(PyObject *module)
9569
/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
9570
0
{
9571
0
    PyObject *result = NULL;
9572
#ifdef MS_WINDOWS
9573
    wchar_t user_name[UNLEN + 1];
9574
    DWORD num_chars = Py_ARRAY_LENGTH(user_name);
9575
9576
    if (GetUserNameW(user_name, &num_chars)) {
9577
        /* num_chars is the number of unicode chars plus null terminator */
9578
        result = PyUnicode_FromWideChar(user_name, num_chars - 1);
9579
    }
9580
    else
9581
        result = PyErr_SetFromWindowsErr(GetLastError());
9582
#elif defined (HAVE_GETLOGIN_R)
9583
# if defined (HAVE_MAXLOGNAME)
9584
    char name[MAXLOGNAME + 1];
9585
# elif defined (HAVE_UT_NAMESIZE)
9586
    char name[UT_NAMESIZE + 1];
9587
# else
9588
    char name[256];
9589
# endif
9590
0
    int err = getlogin_r(name, sizeof(name));
9591
0
    if (err) {
9592
0
        int old_errno = errno;
9593
0
        errno = -err;
9594
0
        posix_error();
9595
0
        errno = old_errno;
9596
0
    }
9597
0
    else {
9598
0
        result = PyUnicode_DecodeFSDefault(name);
9599
0
    }
9600
#else
9601
    char *name;
9602
    int old_errno = errno;
9603
9604
    errno = 0;
9605
    name = getlogin();
9606
    if (name == NULL) {
9607
        if (errno)
9608
            posix_error();
9609
        else
9610
            PyErr_SetString(PyExc_OSError, "unable to determine login name");
9611
    }
9612
    else
9613
        result = PyUnicode_DecodeFSDefault(name);
9614
    errno = old_errno;
9615
#endif
9616
0
    return result;
9617
0
}
9618
#endif /* HAVE_GETLOGIN */
9619
9620
9621
#ifdef HAVE_GETUID
9622
/*[clinic input]
9623
os.getuid
9624
9625
Return the current process's user id.
9626
[clinic start generated code]*/
9627
9628
static PyObject *
9629
os_getuid_impl(PyObject *module)
9630
/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
9631
22
{
9632
22
    return _PyLong_FromUid(getuid());
9633
22
}
9634
#endif /* HAVE_GETUID */
9635
9636
9637
#ifdef MS_WINDOWS
9638
#define HAVE_KILL
9639
#endif /* MS_WINDOWS */
9640
9641
#ifdef HAVE_KILL
9642
/*[clinic input]
9643
os.kill
9644
9645
    pid: pid_t
9646
    signal: Py_ssize_t
9647
    /
9648
9649
Kill a process with a signal.
9650
[clinic start generated code]*/
9651
9652
static PyObject *
9653
os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
9654
/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
9655
0
{
9656
0
    if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
9657
0
        return NULL;
9658
0
    }
9659
0
#ifndef MS_WINDOWS
9660
0
    if (kill(pid, (int)signal) == -1) {
9661
0
        return posix_error();
9662
0
    }
9663
9664
    // Check immediately if the signal was sent to the current process.
9665
    // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
9666
    // is cheap.
9667
0
    if (PyErr_CheckSignals()) {
9668
0
        return NULL;
9669
0
    }
9670
9671
0
    Py_RETURN_NONE;
9672
#else /* !MS_WINDOWS */
9673
    DWORD sig = (DWORD)signal;
9674
9675
#ifdef HAVE_WINDOWS_CONSOLE_IO
9676
    /* Console processes which share a common console can be sent CTRL+C or
9677
       CTRL+BREAK events, provided they handle said events. */
9678
    if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
9679
        if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
9680
            return PyErr_SetFromWindowsErr(0);
9681
        }
9682
        Py_RETURN_NONE;
9683
    }
9684
#endif /* HAVE_WINDOWS_CONSOLE_IO */
9685
9686
    /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
9687
       attempt to open and terminate the process. */
9688
    HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
9689
    if (handle == NULL) {
9690
        return PyErr_SetFromWindowsErr(0);
9691
    }
9692
9693
    BOOL res = TerminateProcess(handle, sig);
9694
    CloseHandle(handle);
9695
    if (res == 0) {
9696
        return PyErr_SetFromWindowsErr(0);
9697
    }
9698
9699
    Py_RETURN_NONE;
9700
#endif /* !MS_WINDOWS */
9701
0
}
9702
#endif /* HAVE_KILL */
9703
9704
9705
#ifdef HAVE_KILLPG
9706
/*[clinic input]
9707
os.killpg
9708
9709
    pgid: pid_t
9710
    signal: int
9711
    /
9712
9713
Kill a process group with a signal.
9714
[clinic start generated code]*/
9715
9716
static PyObject *
9717
os_killpg_impl(PyObject *module, pid_t pgid, int signal)
9718
/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
9719
0
{
9720
0
    if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
9721
0
        return NULL;
9722
0
    }
9723
    /* XXX some man pages make the `pgid` parameter an int, others
9724
       a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
9725
       take the same type. Moreover, pid_t is always at least as wide as
9726
       int (else compilation of this module fails), which is safe. */
9727
0
    if (killpg(pgid, signal) == -1)
9728
0
        return posix_error();
9729
0
    Py_RETURN_NONE;
9730
0
}
9731
#endif /* HAVE_KILLPG */
9732
9733
9734
#ifdef HAVE_PLOCK
9735
#ifdef HAVE_SYS_LOCK_H
9736
#include <sys/lock.h>
9737
#endif
9738
9739
/*[clinic input]
9740
os.plock
9741
    op: int
9742
    /
9743
9744
Lock program segments into memory.");
9745
[clinic start generated code]*/
9746
9747
static PyObject *
9748
os_plock_impl(PyObject *module, int op)
9749
/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
9750
{
9751
    if (plock(op) == -1)
9752
        return posix_error();
9753
    Py_RETURN_NONE;
9754
}
9755
#endif /* HAVE_PLOCK */
9756
9757
9758
#ifdef HAVE_SETUID
9759
/*[clinic input]
9760
os.setuid
9761
9762
    uid: uid_t
9763
    /
9764
9765
Set the current process's user id.
9766
[clinic start generated code]*/
9767
9768
static PyObject *
9769
os_setuid_impl(PyObject *module, uid_t uid)
9770
/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
9771
0
{
9772
0
    if (setuid(uid) < 0)
9773
0
        return posix_error();
9774
0
    Py_RETURN_NONE;
9775
0
}
9776
#endif /* HAVE_SETUID */
9777
9778
9779
#ifdef HAVE_SETEUID
9780
/*[clinic input]
9781
os.seteuid
9782
9783
    euid: uid_t
9784
    /
9785
9786
Set the current process's effective user id.
9787
[clinic start generated code]*/
9788
9789
static PyObject *
9790
os_seteuid_impl(PyObject *module, uid_t euid)
9791
/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
9792
0
{
9793
0
    if (seteuid(euid) < 0)
9794
0
        return posix_error();
9795
0
    Py_RETURN_NONE;
9796
0
}
9797
#endif /* HAVE_SETEUID */
9798
9799
9800
#ifdef HAVE_SETEGID
9801
/*[clinic input]
9802
os.setegid
9803
9804
    egid: gid_t
9805
    /
9806
9807
Set the current process's effective group id.
9808
[clinic start generated code]*/
9809
9810
static PyObject *
9811
os_setegid_impl(PyObject *module, gid_t egid)
9812
/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
9813
0
{
9814
0
    if (setegid(egid) < 0)
9815
0
        return posix_error();
9816
0
    Py_RETURN_NONE;
9817
0
}
9818
#endif /* HAVE_SETEGID */
9819
9820
9821
#ifdef HAVE_SETREUID
9822
/*[clinic input]
9823
os.setreuid
9824
9825
    ruid: uid_t
9826
    euid: uid_t
9827
    /
9828
9829
Set the current process's real and effective user ids.
9830
[clinic start generated code]*/
9831
9832
static PyObject *
9833
os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
9834
/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
9835
0
{
9836
0
    if (setreuid(ruid, euid) < 0) {
9837
0
        return posix_error();
9838
0
    } else {
9839
0
        Py_RETURN_NONE;
9840
0
    }
9841
0
}
9842
#endif /* HAVE_SETREUID */
9843
9844
9845
#ifdef HAVE_SETREGID
9846
/*[clinic input]
9847
os.setregid
9848
9849
    rgid: gid_t
9850
    egid: gid_t
9851
    /
9852
9853
Set the current process's real and effective group ids.
9854
[clinic start generated code]*/
9855
9856
static PyObject *
9857
os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
9858
/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
9859
0
{
9860
0
    if (setregid(rgid, egid) < 0)
9861
0
        return posix_error();
9862
0
    Py_RETURN_NONE;
9863
0
}
9864
#endif /* HAVE_SETREGID */
9865
9866
9867
#ifdef HAVE_SETGID
9868
/*[clinic input]
9869
os.setgid
9870
    gid: gid_t
9871
    /
9872
9873
Set the current process's group id.
9874
[clinic start generated code]*/
9875
9876
static PyObject *
9877
os_setgid_impl(PyObject *module, gid_t gid)
9878
/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
9879
0
{
9880
0
    if (setgid(gid) < 0)
9881
0
        return posix_error();
9882
0
    Py_RETURN_NONE;
9883
0
}
9884
#endif /* HAVE_SETGID */
9885
9886
9887
#ifdef HAVE_SETGROUPS
9888
/*[clinic input]
9889
os.setgroups
9890
9891
    groups: object
9892
    /
9893
9894
Set the groups of the current process to list.
9895
[clinic start generated code]*/
9896
9897
static PyObject *
9898
os_setgroups(PyObject *module, PyObject *groups)
9899
/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
9900
0
{
9901
0
    if (!PySequence_Check(groups)) {
9902
0
        PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
9903
0
        return NULL;
9904
0
    }
9905
0
    Py_ssize_t len = PySequence_Size(groups);
9906
0
    if (len < 0) {
9907
0
        return NULL;
9908
0
    }
9909
0
    if (len > MAX_GROUPS) {
9910
0
        PyErr_SetString(PyExc_ValueError, "too many groups");
9911
0
        return NULL;
9912
0
    }
9913
9914
0
    gid_t *grouplist = PyMem_New(gid_t, len);
9915
0
    if (grouplist == NULL) {
9916
0
        PyErr_NoMemory();
9917
0
        return NULL;
9918
0
    }
9919
0
    for (Py_ssize_t i = 0; i < len; i++) {
9920
0
        PyObject *elem;
9921
0
        elem = PySequence_GetItem(groups, i);
9922
0
        if (!elem) {
9923
0
            PyMem_Free(grouplist);
9924
0
            return NULL;
9925
0
        }
9926
0
        if (!PyIndex_Check(elem)) {
9927
0
            PyErr_SetString(PyExc_TypeError,
9928
0
                            "groups must be integers");
9929
0
            Py_DECREF(elem);
9930
0
            PyMem_Free(grouplist);
9931
0
            return NULL;
9932
0
        } else {
9933
0
            if (!_Py_Gid_Converter(elem, &grouplist[i])) {
9934
0
                Py_DECREF(elem);
9935
0
                PyMem_Free(grouplist);
9936
0
                return NULL;
9937
0
            }
9938
0
        }
9939
0
        Py_DECREF(elem);
9940
0
    }
9941
9942
0
    if (setgroups(len, grouplist) < 0) {
9943
0
        posix_error();
9944
0
        PyMem_Free(grouplist);
9945
0
        return NULL;
9946
0
    }
9947
0
    PyMem_Free(grouplist);
9948
0
    Py_RETURN_NONE;
9949
0
}
9950
#endif /* HAVE_SETGROUPS */
9951
9952
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
9953
static PyObject *
9954
wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
9955
0
{
9956
0
    PyObject *result;
9957
0
    PyObject *struct_rusage;
9958
9959
0
    if (pid == -1)
9960
0
        return posix_error();
9961
9962
    // If wait succeeded but no child was ready to report status, ru will not
9963
    // have been populated.
9964
0
    if (pid == 0) {
9965
0
        memset(ru, 0, sizeof(*ru));
9966
0
    }
9967
9968
0
    struct_rusage = PyImport_ImportModuleAttrString("resource", "struct_rusage");
9969
0
    if (struct_rusage == NULL)
9970
0
        return NULL;
9971
9972
    /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
9973
0
    result = PyStructSequence_New((PyTypeObject*) struct_rusage);
9974
0
    Py_DECREF(struct_rusage);
9975
0
    if (!result)
9976
0
        return NULL;
9977
9978
0
    int pos = 0;
9979
9980
0
#ifndef doubletime
9981
0
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
9982
0
#endif
9983
9984
0
#define SET_RESULT(CALL)                                     \
9985
0
    do {                                                     \
9986
0
        PyObject *item = (CALL);                             \
9987
0
        if (item == NULL) {                                  \
9988
0
            Py_DECREF(result);                               \
9989
0
            return NULL;                                     \
9990
0
        }                                                    \
9991
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
9992
0
    } while(0)
9993
9994
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_utime)));
9995
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_stime)));
9996
0
    SET_RESULT(PyLong_FromLong(ru->ru_maxrss));
9997
0
    SET_RESULT(PyLong_FromLong(ru->ru_ixrss));
9998
0
    SET_RESULT(PyLong_FromLong(ru->ru_idrss));
9999
0
    SET_RESULT(PyLong_FromLong(ru->ru_isrss));
10000
0
    SET_RESULT(PyLong_FromLong(ru->ru_minflt));
10001
0
    SET_RESULT(PyLong_FromLong(ru->ru_majflt));
10002
0
    SET_RESULT(PyLong_FromLong(ru->ru_nswap));
10003
0
    SET_RESULT(PyLong_FromLong(ru->ru_inblock));
10004
0
    SET_RESULT(PyLong_FromLong(ru->ru_oublock));
10005
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgsnd));
10006
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgrcv));
10007
0
    SET_RESULT(PyLong_FromLong(ru->ru_nsignals));
10008
0
    SET_RESULT(PyLong_FromLong(ru->ru_nvcsw));
10009
0
    SET_RESULT(PyLong_FromLong(ru->ru_nivcsw));
10010
0
#undef SET_RESULT
10011
10012
0
    return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
10013
0
}
10014
#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
10015
10016
10017
#ifdef HAVE_WAIT3
10018
/*[clinic input]
10019
os.wait3
10020
10021
    options: int
10022
Wait for completion of a child process.
10023
10024
Returns a tuple of information about the child process:
10025
  (pid, status, rusage)
10026
[clinic start generated code]*/
10027
10028
static PyObject *
10029
os_wait3_impl(PyObject *module, int options)
10030
/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
10031
0
{
10032
0
    pid_t pid;
10033
0
    struct rusage ru;
10034
0
    int async_err = 0;
10035
0
    WAIT_TYPE status;
10036
0
    WAIT_STATUS_INT(status) = 0;
10037
10038
0
    do {
10039
0
        Py_BEGIN_ALLOW_THREADS
10040
0
        pid = wait3(&status, options, &ru);
10041
0
        Py_END_ALLOW_THREADS
10042
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10043
0
    if (pid < 0)
10044
0
        return (!async_err) ? posix_error() : NULL;
10045
10046
0
    return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
10047
0
}
10048
#endif /* HAVE_WAIT3 */
10049
10050
10051
#ifdef HAVE_WAIT4
10052
/*[clinic input]
10053
10054
os.wait4
10055
10056
    pid: pid_t
10057
    options: int
10058
10059
Wait for completion of a specific child process.
10060
10061
Returns a tuple of information about the child process:
10062
  (pid, status, rusage)
10063
[clinic start generated code]*/
10064
10065
static PyObject *
10066
os_wait4_impl(PyObject *module, pid_t pid, int options)
10067
/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
10068
0
{
10069
0
    pid_t res;
10070
0
    struct rusage ru;
10071
0
    int async_err = 0;
10072
0
    WAIT_TYPE status;
10073
0
    WAIT_STATUS_INT(status) = 0;
10074
10075
0
    do {
10076
0
        Py_BEGIN_ALLOW_THREADS
10077
0
        res = wait4(pid, &status, options, &ru);
10078
0
        Py_END_ALLOW_THREADS
10079
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10080
0
    if (res < 0)
10081
0
        return (!async_err) ? posix_error() : NULL;
10082
10083
0
    return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
10084
0
}
10085
#endif /* HAVE_WAIT4 */
10086
10087
10088
#if defined(HAVE_WAITID)
10089
/*[clinic input]
10090
os.waitid
10091
10092
    idtype: idtype_t
10093
        Must be one of be P_PID, P_PGID or P_ALL.
10094
    id: id_t
10095
        The id to wait on.
10096
    options: int
10097
        Constructed from the ORing of one or more of WEXITED, WSTOPPED
10098
        or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
10099
    /
10100
10101
Returns the result of waiting for a process or processes.
10102
10103
Returns either waitid_result or None if WNOHANG is specified and there are
10104
no children in a waitable state.
10105
[clinic start generated code]*/
10106
10107
static PyObject *
10108
os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
10109
/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
10110
0
{
10111
0
    PyObject *result;
10112
0
    int res;
10113
0
    int async_err = 0;
10114
0
    siginfo_t si;
10115
0
    si.si_pid = 0;
10116
10117
0
    do {
10118
0
        Py_BEGIN_ALLOW_THREADS
10119
0
        res = waitid(idtype, id, &si, options);
10120
0
        Py_END_ALLOW_THREADS
10121
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10122
0
    if (res < 0)
10123
0
        return (!async_err) ? posix_error() : NULL;
10124
10125
0
    if (si.si_pid == 0)
10126
0
        Py_RETURN_NONE;
10127
10128
0
    PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
10129
0
    result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
10130
0
    if (!result)
10131
0
        return NULL;
10132
10133
0
    int pos = 0;
10134
10135
0
#define SET_RESULT(CALL)                                     \
10136
0
    do {                                                     \
10137
0
        PyObject *item = (CALL);                             \
10138
0
        if (item == NULL) {                                  \
10139
0
            Py_DECREF(result);                               \
10140
0
            return NULL;                                     \
10141
0
        }                                                    \
10142
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10143
0
    } while(0)
10144
10145
0
    SET_RESULT(PyLong_FromPid(si.si_pid));
10146
0
    SET_RESULT(_PyLong_FromUid(si.si_uid));
10147
0
    SET_RESULT(PyLong_FromLong((long)(si.si_signo)));
10148
0
    SET_RESULT(PyLong_FromLong((long)(si.si_status)));
10149
0
    SET_RESULT(PyLong_FromLong((long)(si.si_code)));
10150
10151
0
#undef SET_RESULT
10152
10153
0
    return result;
10154
0
}
10155
#endif /* defined(HAVE_WAITID) */
10156
10157
10158
#if defined(HAVE_WAITPID)
10159
/*[clinic input]
10160
os.waitpid
10161
    pid: pid_t
10162
    options: int
10163
    /
10164
10165
Wait for completion of a given child process.
10166
10167
Returns a tuple of information regarding the child process:
10168
    (pid, status)
10169
10170
The options argument is ignored on Windows.
10171
[clinic start generated code]*/
10172
10173
static PyObject *
10174
os_waitpid_impl(PyObject *module, pid_t pid, int options)
10175
/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
10176
0
{
10177
0
    pid_t res;
10178
0
    int async_err = 0;
10179
0
    WAIT_TYPE status;
10180
0
    WAIT_STATUS_INT(status) = 0;
10181
10182
0
    do {
10183
0
        Py_BEGIN_ALLOW_THREADS
10184
0
        res = waitpid(pid, &status, options);
10185
0
        Py_END_ALLOW_THREADS
10186
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10187
0
    if (res < 0)
10188
0
        return (!async_err) ? posix_error() : NULL;
10189
10190
0
    return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
10191
0
}
10192
#elif defined(HAVE_CWAIT)
10193
/* MS C has a variant of waitpid() that's usable for most purposes. */
10194
/*[clinic input]
10195
os.waitpid
10196
    pid: intptr_t
10197
    options: int
10198
    /
10199
10200
Wait for completion of a given process.
10201
10202
Returns a tuple of information regarding the process:
10203
    (pid, status << 8)
10204
10205
The options argument is ignored on Windows.
10206
[clinic start generated code]*/
10207
10208
static PyObject *
10209
os_waitpid_impl(PyObject *module, intptr_t pid, int options)
10210
/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
10211
{
10212
    int status;
10213
    intptr_t res;
10214
    int async_err = 0;
10215
10216
    do {
10217
        Py_BEGIN_ALLOW_THREADS
10218
        _Py_BEGIN_SUPPRESS_IPH
10219
        res = _cwait(&status, pid, options);
10220
        _Py_END_SUPPRESS_IPH
10221
        Py_END_ALLOW_THREADS
10222
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10223
    if (res < 0)
10224
        return (!async_err) ? posix_error() : NULL;
10225
10226
    unsigned long long ustatus = (unsigned int)status;
10227
10228
    /* shift the status left a byte so this is more like the POSIX waitpid */
10229
    return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
10230
}
10231
#endif
10232
10233
10234
#ifdef HAVE_WAIT
10235
/*[clinic input]
10236
os.wait
10237
10238
Wait for completion of a child process.
10239
10240
Returns a tuple of information about the child process:
10241
    (pid, status)
10242
[clinic start generated code]*/
10243
10244
static PyObject *
10245
os_wait_impl(PyObject *module)
10246
/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
10247
0
{
10248
0
    pid_t pid;
10249
0
    int async_err = 0;
10250
0
    WAIT_TYPE status;
10251
0
    WAIT_STATUS_INT(status) = 0;
10252
10253
0
    do {
10254
0
        Py_BEGIN_ALLOW_THREADS
10255
0
        pid = wait(&status);
10256
0
        Py_END_ALLOW_THREADS
10257
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10258
0
    if (pid < 0)
10259
0
        return (!async_err) ? posix_error() : NULL;
10260
10261
0
    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
10262
0
}
10263
#endif /* HAVE_WAIT */
10264
10265
10266
// This system call always crashes on older Android versions.
10267
#if defined(__linux__) && defined(__NR_pidfd_open) && \
10268
    !(defined(__ANDROID__) && __ANDROID_API__ < 31)
10269
/*[clinic input]
10270
os.pidfd_open
10271
  pid: pid_t
10272
  flags: unsigned_int = 0
10273
10274
Return a file descriptor referring to the process *pid*.
10275
10276
The descriptor can be used to perform process management without races and
10277
signals.
10278
[clinic start generated code]*/
10279
10280
static PyObject *
10281
os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
10282
/*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
10283
0
{
10284
0
    int fd = syscall(__NR_pidfd_open, pid, flags);
10285
0
    if (fd < 0) {
10286
0
        return posix_error();
10287
0
    }
10288
0
    return PyLong_FromLong(fd);
10289
0
}
10290
#endif
10291
10292
10293
#ifdef HAVE_SETNS
10294
/*[clinic input]
10295
os.setns
10296
  fd: fildes
10297
    A file descriptor to a namespace.
10298
  nstype: int = 0
10299
    Type of namespace.
10300
10301
Move the calling thread into different namespaces.
10302
[clinic start generated code]*/
10303
10304
static PyObject *
10305
os_setns_impl(PyObject *module, int fd, int nstype)
10306
/*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/
10307
0
{
10308
0
    int res;
10309
10310
0
    Py_BEGIN_ALLOW_THREADS
10311
0
    res = setns(fd, nstype);
10312
0
    Py_END_ALLOW_THREADS
10313
10314
0
    if (res != 0) {
10315
0
        return posix_error();
10316
0
    }
10317
10318
0
    Py_RETURN_NONE;
10319
0
}
10320
#endif
10321
10322
10323
#ifdef HAVE_UNSHARE
10324
/*[clinic input]
10325
os.unshare
10326
  flags: int
10327
    Namespaces to be unshared.
10328
10329
Disassociate parts of a process (or thread) execution context.
10330
[clinic start generated code]*/
10331
10332
static PyObject *
10333
os_unshare_impl(PyObject *module, int flags)
10334
/*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/
10335
0
{
10336
0
    int res;
10337
10338
0
    Py_BEGIN_ALLOW_THREADS
10339
0
    res = unshare(flags);
10340
0
    Py_END_ALLOW_THREADS
10341
10342
0
    if (res != 0) {
10343
0
        return posix_error();
10344
0
    }
10345
10346
0
    Py_RETURN_NONE;
10347
0
}
10348
#endif
10349
10350
10351
#if defined(HAVE_READLINK) || defined(MS_WINDOWS)
10352
/*[clinic input]
10353
os.readlink
10354
10355
    path: path_t
10356
    *
10357
    dir_fd: dir_fd(requires='readlinkat') = None
10358
10359
Return a string representing the path to which the symbolic link points.
10360
10361
If dir_fd is not None, it should be a file descriptor open to a directory,
10362
and path should be relative; path will then be relative to that directory.
10363
10364
dir_fd may not be implemented on your platform.  If it is unavailable,
10365
using it will raise a NotImplementedError.
10366
[clinic start generated code]*/
10367
10368
static PyObject *
10369
os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
10370
/*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
10371
0
{
10372
0
#if defined(HAVE_READLINK)
10373
0
    char buffer[MAXPATHLEN+1];
10374
0
    ssize_t length;
10375
0
#ifdef HAVE_READLINKAT
10376
0
    int readlinkat_unavailable = 0;
10377
0
#endif
10378
10379
0
    Py_BEGIN_ALLOW_THREADS
10380
0
#ifdef HAVE_READLINKAT
10381
0
    if (dir_fd != DEFAULT_DIR_FD) {
10382
0
        if (HAVE_READLINKAT_RUNTIME) {
10383
0
            length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
10384
0
        } else {
10385
0
            readlinkat_unavailable = 1;
10386
0
        }
10387
0
    } else
10388
0
#endif
10389
0
        length = readlink(path->narrow, buffer, MAXPATHLEN);
10390
0
    Py_END_ALLOW_THREADS
10391
10392
0
#ifdef HAVE_READLINKAT
10393
0
    if (readlinkat_unavailable) {
10394
0
        argument_unavailable_error(NULL, "dir_fd");
10395
0
        return NULL;
10396
0
    }
10397
0
#endif
10398
10399
0
    if (length < 0) {
10400
0
        return path_error(path);
10401
0
    }
10402
0
    buffer[length] = '\0';
10403
10404
0
    if (PyUnicode_Check(path->object))
10405
0
        return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
10406
0
    else
10407
0
        return PyBytes_FromStringAndSize(buffer, length);
10408
#elif defined(MS_WINDOWS)
10409
    DWORD n_bytes_returned;
10410
    DWORD io_result = 0;
10411
    HANDLE reparse_point_handle;
10412
    char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
10413
    _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
10414
    PyObject *result = NULL;
10415
10416
    /* First get a handle to the reparse point */
10417
    Py_BEGIN_ALLOW_THREADS
10418
    reparse_point_handle = CreateFileW(
10419
        path->wide,
10420
        0,
10421
        0,
10422
        0,
10423
        OPEN_EXISTING,
10424
        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
10425
        0);
10426
    if (reparse_point_handle != INVALID_HANDLE_VALUE) {
10427
        /* New call DeviceIoControl to read the reparse point */
10428
        io_result = DeviceIoControl(
10429
            reparse_point_handle,
10430
            FSCTL_GET_REPARSE_POINT,
10431
            0, 0, /* in buffer */
10432
            target_buffer, sizeof(target_buffer),
10433
            &n_bytes_returned,
10434
            0 /* we're not using OVERLAPPED_IO */
10435
            );
10436
        CloseHandle(reparse_point_handle);
10437
    }
10438
    Py_END_ALLOW_THREADS
10439
10440
    if (io_result == 0) {
10441
        return path_error(path);
10442
    }
10443
10444
    wchar_t *name = NULL;
10445
    Py_ssize_t nameLen = 0;
10446
    if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
10447
    {
10448
        name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
10449
                           rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
10450
        nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10451
    }
10452
    else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
10453
    {
10454
        name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
10455
                           rdb->MountPointReparseBuffer.SubstituteNameOffset);
10456
        nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10457
    }
10458
    else
10459
    {
10460
        PyErr_SetString(PyExc_ValueError, "not a symbolic link");
10461
    }
10462
    if (name) {
10463
        if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
10464
            /* Our buffer is mutable, so this is okay */
10465
            name[1] = L'\\';
10466
        }
10467
        result = PyUnicode_FromWideChar(name, nameLen);
10468
        if (result && PyBytes_Check(path->object)) {
10469
            Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
10470
        }
10471
    }
10472
    return result;
10473
#endif
10474
0
}
10475
#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
10476
10477
#if defined(MS_WINDOWS)
10478
10479
/* Remove the last portion of the path - return 0 on success */
10480
static int
10481
_dirnameW(WCHAR *path)
10482
{
10483
    WCHAR *ptr;
10484
    size_t length = wcsnlen_s(path, MAX_PATH);
10485
    if (length == MAX_PATH) {
10486
        return -1;
10487
    }
10488
10489
    /* walk the path from the end until a backslash is encountered */
10490
    for(ptr = path + length; ptr != path; ptr--) {
10491
        if (*ptr == L'\\' || *ptr == L'/') {
10492
            break;
10493
        }
10494
    }
10495
    *ptr = 0;
10496
    return 0;
10497
}
10498
10499
#endif
10500
10501
#ifdef HAVE_SYMLINK
10502
10503
#if defined(MS_WINDOWS)
10504
10505
/* Is this path absolute? */
10506
static int
10507
_is_absW(const WCHAR *path)
10508
{
10509
    return path[0] == L'\\' || path[0] == L'/' ||
10510
        (path[0] && path[1] == L':');
10511
}
10512
10513
/* join root and rest with a backslash - return 0 on success */
10514
static int
10515
_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
10516
{
10517
    if (_is_absW(rest)) {
10518
        return wcscpy_s(dest_path, MAX_PATH, rest);
10519
    }
10520
10521
    if (wcscpy_s(dest_path, MAX_PATH, root)) {
10522
        return -1;
10523
    }
10524
10525
    if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
10526
        return -1;
10527
    }
10528
10529
    return wcscat_s(dest_path, MAX_PATH, rest);
10530
}
10531
10532
/* Return True if the path at src relative to dest is a directory */
10533
static int
10534
_check_dirW(LPCWSTR src, LPCWSTR dest)
10535
{
10536
    WIN32_FILE_ATTRIBUTE_DATA src_info;
10537
    WCHAR dest_parent[MAX_PATH];
10538
    WCHAR src_resolved[MAX_PATH] = L"";
10539
10540
    /* dest_parent = os.path.dirname(dest) */
10541
    if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
10542
        _dirnameW(dest_parent)) {
10543
        return 0;
10544
    }
10545
    /* src_resolved = os.path.join(dest_parent, src) */
10546
    if (_joinW(src_resolved, dest_parent, src)) {
10547
        return 0;
10548
    }
10549
    return (
10550
        GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
10551
        && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
10552
    );
10553
}
10554
#endif
10555
10556
10557
/*[clinic input]
10558
os.symlink
10559
    src: path_t
10560
    dst: path_t
10561
    target_is_directory: bool = False
10562
    *
10563
    dir_fd: dir_fd(requires='symlinkat')=None
10564
10565
# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
10566
10567
Create a symbolic link pointing to src named dst.
10568
10569
target_is_directory is required on Windows if the target is to be
10570
  interpreted as a directory.  (On Windows, symlink requires
10571
  Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
10572
  target_is_directory is ignored on non-Windows platforms.
10573
10574
If dir_fd is not None, it should be a file descriptor open to a directory,
10575
  and path should be relative; path will then be relative to that directory.
10576
dir_fd may not be implemented on your platform.
10577
  If it is unavailable, using it will raise a NotImplementedError.
10578
10579
[clinic start generated code]*/
10580
10581
static PyObject *
10582
os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
10583
                int target_is_directory, int dir_fd)
10584
/*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
10585
0
{
10586
#ifdef MS_WINDOWS
10587
    DWORD result;
10588
    DWORD flags = 0;
10589
10590
    /* Assumed true, set to false if detected to not be available. */
10591
    static int windows_has_symlink_unprivileged_flag = TRUE;
10592
#else
10593
0
    int result;
10594
0
#ifdef HAVE_SYMLINKAT
10595
0
    int symlinkat_unavailable = 0;
10596
0
#endif
10597
0
#endif
10598
10599
0
    if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
10600
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
10601
0
        return NULL;
10602
0
    }
10603
10604
#ifdef MS_WINDOWS
10605
10606
    if (windows_has_symlink_unprivileged_flag) {
10607
        /* Allow non-admin symlinks if system allows it. */
10608
        flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
10609
    }
10610
10611
    Py_BEGIN_ALLOW_THREADS
10612
    _Py_BEGIN_SUPPRESS_IPH
10613
    /* if src is a directory, ensure flags==1 (target_is_directory bit) */
10614
    if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
10615
        flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
10616
    }
10617
10618
    result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
10619
    _Py_END_SUPPRESS_IPH
10620
    Py_END_ALLOW_THREADS
10621
10622
    if (windows_has_symlink_unprivileged_flag && !result &&
10623
        ERROR_INVALID_PARAMETER == GetLastError()) {
10624
10625
        Py_BEGIN_ALLOW_THREADS
10626
        _Py_BEGIN_SUPPRESS_IPH
10627
        /* This error might be caused by
10628
        SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
10629
        Try again, and update windows_has_symlink_unprivileged_flag if we
10630
        are successful this time.
10631
10632
        NOTE: There is a risk of a race condition here if there are other
10633
        conditions than the flag causing ERROR_INVALID_PARAMETER, and
10634
        another process (or thread) changes that condition in between our
10635
        calls to CreateSymbolicLink.
10636
        */
10637
        flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
10638
        result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
10639
        _Py_END_SUPPRESS_IPH
10640
        Py_END_ALLOW_THREADS
10641
10642
        if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
10643
            windows_has_symlink_unprivileged_flag = FALSE;
10644
        }
10645
    }
10646
10647
    if (!result)
10648
        return path_error2(src, dst);
10649
10650
#else
10651
10652
0
    Py_BEGIN_ALLOW_THREADS
10653
0
#ifdef HAVE_SYMLINKAT
10654
0
    if (dir_fd != DEFAULT_DIR_FD) {
10655
0
        if (HAVE_SYMLINKAT_RUNTIME) {
10656
0
            result = symlinkat(src->narrow, dir_fd, dst->narrow);
10657
0
        } else {
10658
0
            symlinkat_unavailable = 1;
10659
0
        }
10660
0
    } else
10661
0
#endif
10662
0
        result = symlink(src->narrow, dst->narrow);
10663
0
    Py_END_ALLOW_THREADS
10664
10665
0
#ifdef HAVE_SYMLINKAT
10666
0
    if (symlinkat_unavailable) {
10667
0
          argument_unavailable_error(NULL, "dir_fd");
10668
0
          return NULL;
10669
0
    }
10670
0
#endif
10671
10672
0
    if (result)
10673
0
        return path_error2(src, dst);
10674
0
#endif
10675
10676
0
    Py_RETURN_NONE;
10677
0
}
10678
#endif /* HAVE_SYMLINK */
10679
10680
10681
static PyStructSequence_Field times_result_fields[] = {
10682
    {"user",    "user time"},
10683
    {"system",   "system time"},
10684
    {"children_user",    "user time of children"},
10685
    {"children_system",    "system time of children"},
10686
    {"elapsed",    "elapsed time since an arbitrary point in the past"},
10687
    {NULL}
10688
};
10689
10690
PyDoc_STRVAR(times_result__doc__,
10691
"times_result: Result from os.times().\n\n\
10692
This object may be accessed either as a tuple of\n\
10693
  (user, system, children_user, children_system, elapsed),\n\
10694
or via the attributes user, system, children_user, children_system,\n\
10695
and elapsed.\n\
10696
\n\
10697
See os.times for more information.");
10698
10699
static PyStructSequence_Desc times_result_desc = {
10700
    "times_result", /* name */
10701
    times_result__doc__, /* doc */
10702
    times_result_fields,
10703
    5
10704
};
10705
10706
static PyObject *
10707
build_times_result(PyObject *module, double user, double system,
10708
    double children_user, double children_system,
10709
    double elapsed)
10710
0
{
10711
0
    PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
10712
0
    PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
10713
0
    if (value == NULL)
10714
0
        return NULL;
10715
10716
0
#define SET(i, field) \
10717
0
    { \
10718
0
    PyObject *o = PyFloat_FromDouble(field); \
10719
0
    if (!o) { \
10720
0
        Py_DECREF(value); \
10721
0
        return NULL; \
10722
0
    } \
10723
0
    PyStructSequence_SET_ITEM(value, i, o); \
10724
0
    } \
10725
0
10726
0
    SET(0, user);
10727
0
    SET(1, system);
10728
0
    SET(2, children_user);
10729
0
    SET(3, children_system);
10730
0
    SET(4, elapsed);
10731
10732
0
#undef SET
10733
10734
0
    return value;
10735
0
}
10736
10737
10738
/*[clinic input]
10739
os.times
10740
10741
Return a collection containing process timing information.
10742
10743
The object returned behaves like a named tuple with these fields:
10744
  (utime, stime, cutime, cstime, elapsed_time)
10745
All fields are floating-point numbers.
10746
[clinic start generated code]*/
10747
10748
static PyObject *
10749
os_times_impl(PyObject *module)
10750
/*[clinic end generated code: output=35f640503557d32a input=8dbfe33a2dcc3df3]*/
10751
0
{
10752
#ifdef MS_WINDOWS
10753
    FILETIME create, exit, kernel, user;
10754
    HANDLE hProc;
10755
    hProc = GetCurrentProcess();
10756
    GetProcessTimes(hProc, &create, &exit, &kernel, &user);
10757
    /* The fields of a FILETIME structure are the hi and lo part
10758
       of a 64-bit value expressed in 100 nanosecond units.
10759
       1e7 is one second in such units; 1e-7 the inverse.
10760
       429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
10761
    */
10762
    return build_times_result(module,
10763
        (double)(user.dwHighDateTime*429.4967296 +
10764
                 user.dwLowDateTime*1e-7),
10765
        (double)(kernel.dwHighDateTime*429.4967296 +
10766
                 kernel.dwLowDateTime*1e-7),
10767
        (double)0,
10768
        (double)0,
10769
        (double)0);
10770
#else /* MS_WINDOWS */
10771
0
    _posixstate *state = get_posix_state(module);
10772
0
    long ticks_per_second = state->ticks_per_second;
10773
10774
0
    struct tms process;
10775
0
    clock_t elapsed;
10776
0
    errno = 0;
10777
0
    elapsed = times(&process);
10778
0
    if (elapsed == (clock_t) -1) {
10779
0
        return posix_error();
10780
0
    }
10781
10782
0
    return build_times_result(module,
10783
0
        (double)process.tms_utime / ticks_per_second,
10784
0
        (double)process.tms_stime / ticks_per_second,
10785
0
        (double)process.tms_cutime / ticks_per_second,
10786
0
        (double)process.tms_cstime / ticks_per_second,
10787
0
        (double)elapsed / ticks_per_second);
10788
0
#endif /* MS_WINDOWS */
10789
0
}
10790
10791
10792
#if defined(HAVE_TIMERFD_CREATE)
10793
#define ONE_SECOND_IN_NS (1000 * 1000 * 1000)
10794
#define EXTRACT_NSEC(value)  (long)( ( (double)(value) - (time_t)(value) ) * 1e9)
10795
0
#define CONVERT_SEC_AND_NSEC_TO_DOUBLE(sec, nsec) ( (double)(sec) + (double)(nsec) * 1e-9 )
10796
10797
static PyObject *
10798
build_itimerspec(const struct itimerspec* curr_value)
10799
0
{
10800
0
    double _value = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_value.tv_sec,
10801
0
                                                          curr_value->it_value.tv_nsec);
10802
0
    PyObject *value = PyFloat_FromDouble(_value);
10803
0
    if (value == NULL) {
10804
0
        return NULL;
10805
0
    }
10806
0
    double _interval = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_interval.tv_sec,
10807
0
                                                   curr_value->it_interval.tv_nsec);
10808
0
    PyObject *interval = PyFloat_FromDouble(_interval);
10809
0
    if (interval == NULL) {
10810
0
        Py_DECREF(value);
10811
0
        return NULL;
10812
0
    }
10813
0
    PyObject *tuple = PyTuple_Pack(2, value, interval);
10814
0
    Py_DECREF(interval);
10815
0
    Py_DECREF(value);
10816
0
    return tuple;
10817
0
}
10818
10819
static PyObject *
10820
build_itimerspec_ns(const struct itimerspec* curr_value)
10821
0
{
10822
0
    PyTime_t value, interval;
10823
0
    if (_PyTime_FromTimespec(&value, &curr_value->it_value) < 0) {
10824
0
        return NULL;
10825
0
    }
10826
0
    if (_PyTime_FromTimespec(&interval, &curr_value->it_interval) < 0) {
10827
0
        return NULL;
10828
0
    }
10829
0
    return Py_BuildValue("LL", value, interval);
10830
0
}
10831
10832
/*[clinic input]
10833
os.timerfd_create
10834
10835
    clockid: int
10836
        A valid clock ID constant as timer file descriptor.
10837
10838
        time.CLOCK_REALTIME
10839
        time.CLOCK_MONOTONIC
10840
        time.CLOCK_BOOTTIME
10841
    /
10842
    *
10843
    flags: int = 0
10844
        0 or a bit mask of os.TFD_NONBLOCK or os.TFD_CLOEXEC.
10845
10846
        os.TFD_NONBLOCK
10847
            If *TFD_NONBLOCK* is set as a flag, read doesn't blocks.
10848
            If *TFD_NONBLOCK* is not set as a flag, read block until the timer fires.
10849
10850
        os.TFD_CLOEXEC
10851
            If *TFD_CLOEXEC* is set as a flag, enable the close-on-exec flag
10852
10853
Create and return a timer file descriptor.
10854
[clinic start generated code]*/
10855
10856
static PyObject *
10857
os_timerfd_create_impl(PyObject *module, int clockid, int flags)
10858
/*[clinic end generated code: output=1caae80fb168004a input=64b7020c5ac0b8f4]*/
10859
10860
0
{
10861
0
    int fd;
10862
0
    Py_BEGIN_ALLOW_THREADS
10863
0
    flags |= TFD_CLOEXEC;  // PEP 446: always create non-inheritable FD
10864
0
    fd = timerfd_create(clockid, flags);
10865
0
    Py_END_ALLOW_THREADS
10866
0
    if (fd == -1) {
10867
0
        return PyErr_SetFromErrno(PyExc_OSError);
10868
0
    }
10869
0
    return PyLong_FromLong(fd);
10870
0
}
10871
10872
/*[clinic input]
10873
os.timerfd_settime
10874
10875
    fd: fildes
10876
        A timer file descriptor.
10877
    /
10878
    *
10879
    flags: int = 0
10880
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
10881
    initial as initial_double: double = 0.0
10882
        The initial expiration time, in seconds.
10883
    interval as interval_double: double = 0.0
10884
        The timer's interval, in seconds.
10885
10886
Alter a timer file descriptor's internal timer in seconds.
10887
[clinic start generated code]*/
10888
10889
static PyObject *
10890
os_timerfd_settime_impl(PyObject *module, int fd, int flags,
10891
                        double initial_double, double interval_double)
10892
/*[clinic end generated code: output=df4c1bce6859224e input=81d2c0d7e936e8a7]*/
10893
0
{
10894
0
    PyTime_t initial, interval;
10895
0
    if (_PyTime_FromSecondsDouble(initial_double, _PyTime_ROUND_FLOOR,
10896
0
                                  &initial) < 0) {
10897
0
        return NULL;
10898
0
    }
10899
0
    if (_PyTime_FromSecondsDouble(interval_double, _PyTime_ROUND_FLOOR,
10900
0
                                  &interval) < 0) {
10901
0
        return NULL;
10902
0
    }
10903
10904
0
    struct itimerspec new_value, old_value;
10905
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
10906
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
10907
0
        return NULL;
10908
0
    }
10909
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
10910
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
10911
0
        return NULL;
10912
0
    }
10913
10914
0
    int result;
10915
0
    Py_BEGIN_ALLOW_THREADS
10916
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
10917
0
    Py_END_ALLOW_THREADS
10918
0
    if (result == -1) {
10919
0
        return PyErr_SetFromErrno(PyExc_OSError);
10920
0
    }
10921
0
    return build_itimerspec(&old_value);
10922
0
}
10923
10924
10925
/*[clinic input]
10926
os.timerfd_settime_ns
10927
10928
    fd: fildes
10929
        A timer file descriptor.
10930
    /
10931
    *
10932
    flags: int = 0
10933
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
10934
    initial: long_long = 0
10935
        initial expiration timing in seconds.
10936
    interval: long_long = 0
10937
        interval for the timer in seconds.
10938
10939
Alter a timer file descriptor's internal timer in nanoseconds.
10940
[clinic start generated code]*/
10941
10942
static PyObject *
10943
os_timerfd_settime_ns_impl(PyObject *module, int fd, int flags,
10944
                           long long initial, long long interval)
10945
/*[clinic end generated code: output=6273ec7d7b4cc0b3 input=261e105d6e42f5bc]*/
10946
0
{
10947
0
    struct itimerspec new_value;
10948
0
    struct itimerspec old_value;
10949
0
    int result;
10950
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
10951
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
10952
0
        return NULL;
10953
0
    }
10954
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
10955
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
10956
0
        return NULL;
10957
0
    }
10958
0
    Py_BEGIN_ALLOW_THREADS
10959
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
10960
0
    Py_END_ALLOW_THREADS
10961
0
    if (result == -1) {
10962
0
        return PyErr_SetFromErrno(PyExc_OSError);
10963
0
    }
10964
0
    return build_itimerspec_ns(&old_value);
10965
0
}
10966
10967
/*[clinic input]
10968
@permit_long_summary
10969
os.timerfd_gettime
10970
10971
    fd: fildes
10972
        A timer file descriptor.
10973
    /
10974
10975
Return a tuple of a timer file descriptor's (interval, next expiration) in float seconds.
10976
[clinic start generated code]*/
10977
10978
static PyObject *
10979
os_timerfd_gettime_impl(PyObject *module, int fd)
10980
/*[clinic end generated code: output=ec5a94a66cfe6ab4 input=05f7d568a4820dc6]*/
10981
0
{
10982
0
    struct itimerspec curr_value;
10983
0
    int result;
10984
0
    Py_BEGIN_ALLOW_THREADS
10985
0
    result = timerfd_gettime(fd, &curr_value);
10986
0
    Py_END_ALLOW_THREADS
10987
0
    if (result == -1) {
10988
0
        return PyErr_SetFromErrno(PyExc_OSError);
10989
0
    }
10990
0
    return build_itimerspec(&curr_value);
10991
0
}
10992
10993
10994
/*[clinic input]
10995
@permit_long_summary
10996
os.timerfd_gettime_ns
10997
10998
    fd: fildes
10999
        A timer file descriptor.
11000
    /
11001
11002
Return a tuple of a timer file descriptor's (interval, next expiration) in nanoseconds.
11003
[clinic start generated code]*/
11004
11005
static PyObject *
11006
os_timerfd_gettime_ns_impl(PyObject *module, int fd)
11007
/*[clinic end generated code: output=580633a4465f39fe input=d0de95b9782179c5]*/
11008
0
{
11009
0
    struct itimerspec curr_value;
11010
0
    int result;
11011
0
    Py_BEGIN_ALLOW_THREADS
11012
0
    result = timerfd_gettime(fd, &curr_value);
11013
0
    Py_END_ALLOW_THREADS
11014
0
    if (result == -1) {
11015
0
        return PyErr_SetFromErrno(PyExc_OSError);
11016
0
    }
11017
0
    return build_itimerspec_ns(&curr_value);
11018
0
}
11019
11020
#undef ONE_SECOND_IN_NS
11021
#undef EXTRACT_NSEC
11022
11023
#endif  /* HAVE_TIMERFD_CREATE */
11024
11025
#ifdef HAVE_GETSID
11026
/*[clinic input]
11027
os.getsid
11028
11029
    pid: pid_t
11030
    /
11031
11032
Call the system call getsid(pid) and return the result.
11033
[clinic start generated code]*/
11034
11035
static PyObject *
11036
os_getsid_impl(PyObject *module, pid_t pid)
11037
/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
11038
0
{
11039
0
    int sid;
11040
0
    sid = getsid(pid);
11041
0
    if (sid < 0)
11042
0
        return posix_error();
11043
0
    return PyLong_FromLong((long)sid);
11044
0
}
11045
#endif /* HAVE_GETSID */
11046
11047
11048
#ifdef HAVE_SETSID
11049
/*[clinic input]
11050
os.setsid
11051
11052
Call the system call setsid().
11053
[clinic start generated code]*/
11054
11055
static PyObject *
11056
os_setsid_impl(PyObject *module)
11057
/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
11058
0
{
11059
0
    if (setsid() < 0)
11060
0
        return posix_error();
11061
0
    Py_RETURN_NONE;
11062
0
}
11063
#endif /* HAVE_SETSID */
11064
11065
11066
#ifdef HAVE_SETPGID
11067
/*[clinic input]
11068
os.setpgid
11069
11070
    pid: pid_t
11071
    pgrp: pid_t
11072
    /
11073
11074
Call the system call setpgid(pid, pgrp).
11075
[clinic start generated code]*/
11076
11077
static PyObject *
11078
os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
11079
/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
11080
0
{
11081
0
    if (setpgid(pid, pgrp) < 0)
11082
0
        return posix_error();
11083
0
    Py_RETURN_NONE;
11084
0
}
11085
#endif /* HAVE_SETPGID */
11086
11087
11088
#ifdef HAVE_TCGETPGRP
11089
/*[clinic input]
11090
os.tcgetpgrp
11091
11092
    fd: int
11093
    /
11094
11095
Return the process group associated with the terminal specified by fd.
11096
[clinic start generated code]*/
11097
11098
static PyObject *
11099
os_tcgetpgrp_impl(PyObject *module, int fd)
11100
/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
11101
0
{
11102
0
    pid_t pgid = tcgetpgrp(fd);
11103
0
    if (pgid < 0)
11104
0
        return posix_error();
11105
0
    return PyLong_FromPid(pgid);
11106
0
}
11107
#endif /* HAVE_TCGETPGRP */
11108
11109
11110
#ifdef HAVE_TCSETPGRP
11111
/*[clinic input]
11112
os.tcsetpgrp
11113
11114
    fd: int
11115
    pgid: pid_t
11116
    /
11117
11118
Set the process group associated with the terminal specified by fd.
11119
[clinic start generated code]*/
11120
11121
static PyObject *
11122
os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
11123
/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
11124
0
{
11125
0
    if (tcsetpgrp(fd, pgid) < 0)
11126
0
        return posix_error();
11127
0
    Py_RETURN_NONE;
11128
0
}
11129
#endif /* HAVE_TCSETPGRP */
11130
11131
/* Functions acting on file descriptors */
11132
11133
#ifdef O_CLOEXEC
11134
extern int _Py_open_cloexec_works;
11135
#endif
11136
11137
11138
/*[clinic input]
11139
os.open -> int
11140
    path: path_t
11141
    flags: int
11142
    mode: int = 0o777
11143
    *
11144
    dir_fd: dir_fd(requires='openat') = None
11145
11146
# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
11147
11148
Open a file for low level IO.  Returns a file descriptor (integer).
11149
11150
If dir_fd is not None, it should be a file descriptor open to a directory,
11151
  and path should be relative; path will then be relative to that directory.
11152
dir_fd may not be implemented on your platform.
11153
  If it is unavailable, using it will raise a NotImplementedError.
11154
[clinic start generated code]*/
11155
11156
static int
11157
os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
11158
/*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
11159
0
{
11160
0
    int fd;
11161
0
    int async_err = 0;
11162
0
#ifdef HAVE_OPENAT
11163
0
    int openat_unavailable = 0;
11164
0
#endif
11165
11166
0
#ifdef O_CLOEXEC
11167
0
    int *atomic_flag_works = &_Py_open_cloexec_works;
11168
#elif !defined(MS_WINDOWS)
11169
    int *atomic_flag_works = NULL;
11170
#endif
11171
11172
#ifdef MS_WINDOWS
11173
    flags |= O_NOINHERIT;
11174
#elif defined(O_CLOEXEC)
11175
    flags |= O_CLOEXEC;
11176
0
#endif
11177
11178
0
    if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
11179
0
        return -1;
11180
0
    }
11181
11182
0
    _Py_BEGIN_SUPPRESS_IPH
11183
0
    do {
11184
0
        Py_BEGIN_ALLOW_THREADS
11185
#ifdef MS_WINDOWS
11186
        fd = _wopen(path->wide, flags, mode);
11187
#else
11188
0
#ifdef HAVE_OPENAT
11189
0
        if (dir_fd != DEFAULT_DIR_FD) {
11190
0
            if (HAVE_OPENAT_RUNTIME) {
11191
0
                fd = openat(dir_fd, path->narrow, flags, mode);
11192
11193
0
            } else {
11194
0
                openat_unavailable = 1;
11195
0
                fd = -1;
11196
0
            }
11197
0
        } else
11198
0
#endif /* HAVE_OPENAT */
11199
0
            fd = open(path->narrow, flags, mode);
11200
0
#endif /* !MS_WINDOWS */
11201
0
        Py_END_ALLOW_THREADS
11202
0
    } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11203
0
    _Py_END_SUPPRESS_IPH
11204
11205
0
#ifdef HAVE_OPENAT
11206
0
    if (openat_unavailable) {
11207
0
        argument_unavailable_error(NULL, "dir_fd");
11208
0
        return -1;
11209
0
    }
11210
0
#endif
11211
11212
0
    if (fd < 0) {
11213
0
        if (!async_err)
11214
0
            PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
11215
0
        return -1;
11216
0
    }
11217
11218
0
#ifndef MS_WINDOWS
11219
0
    if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
11220
0
        close(fd);
11221
0
        return -1;
11222
0
    }
11223
0
#endif
11224
11225
0
    return fd;
11226
0
}
11227
11228
11229
/*[clinic input]
11230
os.close
11231
11232
    fd: int
11233
11234
Close a file descriptor.
11235
[clinic start generated code]*/
11236
11237
static PyObject *
11238
os_close_impl(PyObject *module, int fd)
11239
/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
11240
0
{
11241
0
    int res;
11242
    /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
11243
     * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
11244
     * for more details.
11245
     */
11246
0
    Py_BEGIN_ALLOW_THREADS
11247
0
    _Py_BEGIN_SUPPRESS_IPH
11248
0
    res = close(fd);
11249
0
    _Py_END_SUPPRESS_IPH
11250
0
    Py_END_ALLOW_THREADS
11251
0
    if (res < 0)
11252
0
        return posix_error();
11253
0
    Py_RETURN_NONE;
11254
0
}
11255
11256
/*[clinic input]
11257
os.closerange
11258
11259
    fd_low: int
11260
    fd_high: int
11261
    /
11262
11263
Closes all file descriptors in [fd_low, fd_high), ignoring errors.
11264
[clinic start generated code]*/
11265
11266
static PyObject *
11267
os_closerange_impl(PyObject *module, int fd_low, int fd_high)
11268
/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
11269
0
{
11270
0
    Py_BEGIN_ALLOW_THREADS
11271
0
    _Py_closerange(fd_low, fd_high - 1);
11272
0
    Py_END_ALLOW_THREADS
11273
0
    Py_RETURN_NONE;
11274
0
}
11275
11276
11277
/*[clinic input]
11278
os.dup -> int
11279
11280
    fd: int
11281
    /
11282
11283
Return a duplicate of a file descriptor.
11284
[clinic start generated code]*/
11285
11286
static int
11287
os_dup_impl(PyObject *module, int fd)
11288
/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
11289
0
{
11290
0
    return _Py_dup(fd);
11291
0
}
11292
11293
// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
11294
// dup2.c provides working dup2() if and only if F_DUPFD is available.
11295
#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
11296
/*[clinic input]
11297
os.dup2 -> int
11298
    fd: int
11299
    fd2: int
11300
    inheritable: bool=True
11301
11302
Duplicate file descriptor.
11303
[clinic start generated code]*/
11304
11305
static int
11306
os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
11307
/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
11308
0
{
11309
0
    int res = 0;
11310
0
#if defined(HAVE_DUP3) && \
11311
0
    !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
11312
    /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
11313
0
    static int dup3_works = -1;
11314
0
#endif
11315
11316
    /* dup2() can fail with EINTR if the target FD is already open, because it
11317
     * then has to be closed. See os_close_impl() for why we don't handle EINTR
11318
     * upon close(), and therefore below.
11319
     */
11320
#ifdef MS_WINDOWS
11321
    Py_BEGIN_ALLOW_THREADS
11322
    _Py_BEGIN_SUPPRESS_IPH
11323
    res = dup2(fd, fd2);
11324
    _Py_END_SUPPRESS_IPH
11325
    Py_END_ALLOW_THREADS
11326
    if (res < 0) {
11327
        posix_error();
11328
        return -1;
11329
    }
11330
    res = fd2; // msvcrt dup2 returns 0 on success.
11331
11332
    /* Character files like console cannot be make non-inheritable */
11333
    if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11334
        close(fd2);
11335
        return -1;
11336
    }
11337
11338
#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
11339
    Py_BEGIN_ALLOW_THREADS
11340
    if (!inheritable)
11341
        res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
11342
    else
11343
        res = dup2(fd, fd2);
11344
    Py_END_ALLOW_THREADS
11345
    if (res < 0) {
11346
        posix_error();
11347
        return -1;
11348
    }
11349
11350
#else
11351
11352
0
#ifdef HAVE_DUP3
11353
0
    if (!inheritable && dup3_works != 0) {
11354
0
        Py_BEGIN_ALLOW_THREADS
11355
0
        res = dup3(fd, fd2, O_CLOEXEC);
11356
0
        Py_END_ALLOW_THREADS
11357
0
        if (res < 0) {
11358
0
            if (dup3_works == -1)
11359
0
                dup3_works = (errno != ENOSYS);
11360
0
            if (dup3_works) {
11361
0
                posix_error();
11362
0
                return -1;
11363
0
            }
11364
0
        }
11365
0
    }
11366
11367
0
    if (inheritable || dup3_works == 0)
11368
0
    {
11369
0
#endif
11370
0
        Py_BEGIN_ALLOW_THREADS
11371
0
        res = dup2(fd, fd2);
11372
0
        Py_END_ALLOW_THREADS
11373
0
        if (res < 0) {
11374
0
            posix_error();
11375
0
            return -1;
11376
0
        }
11377
11378
0
        if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11379
0
            close(fd2);
11380
0
            return -1;
11381
0
        }
11382
0
#ifdef HAVE_DUP3
11383
0
    }
11384
0
#endif
11385
11386
0
#endif
11387
11388
0
    return res;
11389
0
}
11390
#endif
11391
11392
11393
#ifdef HAVE_LOCKF
11394
/*[clinic input]
11395
os.lockf
11396
11397
    fd: int
11398
        An open file descriptor.
11399
    command: int
11400
        One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
11401
    length: Py_off_t
11402
        The number of bytes to lock, starting at the current position.
11403
    /
11404
11405
Apply, test or remove a POSIX lock on an open file descriptor.
11406
11407
[clinic start generated code]*/
11408
11409
static PyObject *
11410
os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
11411
/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
11412
0
{
11413
0
    int res;
11414
11415
0
    if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
11416
0
        return NULL;
11417
0
    }
11418
11419
0
    Py_BEGIN_ALLOW_THREADS
11420
0
    res = lockf(fd, command, length);
11421
0
    Py_END_ALLOW_THREADS
11422
11423
0
    if (res < 0)
11424
0
        return posix_error();
11425
11426
0
    Py_RETURN_NONE;
11427
0
}
11428
#endif /* HAVE_LOCKF */
11429
11430
11431
/*[clinic input]
11432
@permit_long_docstring_body
11433
os.lseek -> Py_off_t
11434
11435
    fd: int
11436
        An open file descriptor, as returned by os.open().
11437
    position: Py_off_t
11438
        Position, interpreted relative to 'whence'.
11439
    whence as how: int
11440
        The relative position to seek from. Valid values are:
11441
        - SEEK_SET: seek from the start of the file.
11442
        - SEEK_CUR: seek from the current file position.
11443
        - SEEK_END: seek from the end of the file.
11444
    /
11445
11446
Set the position of a file descriptor.  Return the new position.
11447
11448
The return value is the number of bytes relative to the beginning of the file.
11449
[clinic start generated code]*/
11450
11451
static Py_off_t
11452
os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
11453
/*[clinic end generated code: output=971e1efb6b30bd2f input=4a3de549f07e1c40]*/
11454
0
{
11455
0
    Py_off_t result;
11456
11457
0
#ifdef SEEK_SET
11458
    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
11459
0
    switch (how) {
11460
0
        case 0: how = SEEK_SET; break;
11461
0
        case 1: how = SEEK_CUR; break;
11462
0
        case 2: how = SEEK_END; break;
11463
0
    }
11464
0
#endif /* SEEK_END */
11465
11466
0
    Py_BEGIN_ALLOW_THREADS
11467
0
    _Py_BEGIN_SUPPRESS_IPH
11468
#ifdef MS_WINDOWS
11469
    result = _lseeki64(fd, position, how);
11470
#else
11471
0
    result = lseek(fd, position, how);
11472
0
#endif
11473
0
    _Py_END_SUPPRESS_IPH
11474
0
    Py_END_ALLOW_THREADS
11475
0
    if (result < 0)
11476
0
        posix_error();
11477
11478
0
    return result;
11479
0
}
11480
11481
11482
/*[clinic input]
11483
os.read
11484
    fd: int
11485
    length: Py_ssize_t
11486
    /
11487
11488
Read from a file descriptor.  Returns a bytes object.
11489
[clinic start generated code]*/
11490
11491
static PyObject *
11492
os_read_impl(PyObject *module, int fd, Py_ssize_t length)
11493
/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
11494
0
{
11495
0
    Py_ssize_t n;
11496
0
    PyObject *buffer;
11497
11498
0
    if (length < 0) {
11499
0
        errno = EINVAL;
11500
0
        return posix_error();
11501
0
    }
11502
11503
0
    length = Py_MIN(length, _PY_READ_MAX);
11504
11505
0
    buffer = PyBytes_FromStringAndSize((char *)NULL, length);
11506
0
    if (buffer == NULL)
11507
0
        return NULL;
11508
11509
0
    n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
11510
0
    if (n == -1) {
11511
0
        Py_DECREF(buffer);
11512
0
        return NULL;
11513
0
    }
11514
11515
0
    if (n != length)
11516
0
        _PyBytes_Resize(&buffer, n);
11517
11518
0
    return buffer;
11519
0
}
11520
11521
/*[clinic input]
11522
@permit_long_docstring_body
11523
os.readinto -> Py_ssize_t
11524
    fd: int
11525
    buffer: Py_buffer(accept={rwbuffer})
11526
    /
11527
11528
Read into a buffer object from a file descriptor.
11529
11530
The buffer should be mutable and bytes-like. On success, returns the number of
11531
bytes read. Less bytes may be read than the size of the buffer. The underlying
11532
system call will be retried when interrupted by a signal, unless the signal
11533
handler raises an exception. Other errors will not be retried and an error will
11534
be raised.
11535
11536
Returns 0 if *fd* is at end of file or if the provided *buffer* has length 0
11537
(which can be used to check for errors without reading data). Never returns
11538
negative.
11539
[clinic start generated code]*/
11540
11541
static Py_ssize_t
11542
os_readinto_impl(PyObject *module, int fd, Py_buffer *buffer)
11543
/*[clinic end generated code: output=8091a3513c683a80 input=a770382bd3d32f9a]*/
11544
0
{
11545
0
    assert(buffer->len >= 0);
11546
0
    Py_ssize_t result = _Py_read(fd, buffer->buf, buffer->len);
11547
    /* Ensure negative is never returned without an error. Simplifies calling
11548
        code. _Py_read should succeed, possibly reading 0 bytes, _or_ set an
11549
        error. */
11550
0
    assert(result >= 0 || (result == -1 && PyErr_Occurred()));
11551
0
    return result;
11552
0
}
11553
11554
#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
11555
                                || defined(__APPLE__))) \
11556
    || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
11557
    || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
11558
static int
11559
iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
11560
0
{
11561
0
    Py_ssize_t i, j;
11562
11563
0
    *iov = PyMem_New(struct iovec, cnt);
11564
0
    if (*iov == NULL) {
11565
0
        PyErr_NoMemory();
11566
0
        return -1;
11567
0
    }
11568
11569
0
    *buf = PyMem_New(Py_buffer, cnt);
11570
0
    if (*buf == NULL) {
11571
0
        PyMem_Free(*iov);
11572
0
        PyErr_NoMemory();
11573
0
        return -1;
11574
0
    }
11575
11576
0
    for (i = 0; i < cnt; i++) {
11577
0
        PyObject *item = PySequence_GetItem(seq, i);
11578
0
        if (item == NULL)
11579
0
            goto fail;
11580
0
        if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
11581
0
            Py_DECREF(item);
11582
0
            goto fail;
11583
0
        }
11584
0
        Py_DECREF(item);
11585
0
        (*iov)[i].iov_base = (*buf)[i].buf;
11586
0
        (*iov)[i].iov_len = (*buf)[i].len;
11587
0
    }
11588
0
    return 0;
11589
11590
0
fail:
11591
0
    PyMem_Free(*iov);
11592
0
    for (j = 0; j < i; j++) {
11593
0
        PyBuffer_Release(&(*buf)[j]);
11594
0
    }
11595
0
    PyMem_Free(*buf);
11596
0
    return -1;
11597
0
}
11598
11599
static void
11600
iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
11601
0
{
11602
0
    int i;
11603
0
    PyMem_Free(iov);
11604
0
    for (i = 0; i < cnt; i++) {
11605
0
        PyBuffer_Release(&buf[i]);
11606
0
    }
11607
0
    PyMem_Free(buf);
11608
0
}
11609
#endif
11610
11611
11612
#ifdef HAVE_READV
11613
/*[clinic input]
11614
os.readv -> Py_ssize_t
11615
11616
    fd: int
11617
    buffers: object
11618
    /
11619
11620
Read from a file descriptor fd into an iterable of buffers.
11621
11622
The buffers should be mutable buffers accepting bytes.
11623
readv will transfer data into each buffer until it is full
11624
and then move on to the next buffer in the sequence to hold
11625
the rest of the data.
11626
11627
readv returns the total number of bytes read,
11628
which may be less than the total capacity of all the buffers.
11629
[clinic start generated code]*/
11630
11631
static Py_ssize_t
11632
os_readv_impl(PyObject *module, int fd, PyObject *buffers)
11633
/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
11634
0
{
11635
0
    Py_ssize_t cnt, n;
11636
0
    int async_err = 0;
11637
0
    struct iovec *iov;
11638
0
    Py_buffer *buf;
11639
11640
0
    if (!PySequence_Check(buffers)) {
11641
0
        PyErr_SetString(PyExc_TypeError,
11642
0
            "readv() arg 2 must be a sequence");
11643
0
        return -1;
11644
0
    }
11645
11646
0
    cnt = PySequence_Size(buffers);
11647
0
    if (cnt < 0)
11648
0
        return -1;
11649
11650
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
11651
0
        return -1;
11652
11653
0
    do {
11654
0
        Py_BEGIN_ALLOW_THREADS
11655
0
        n = readv(fd, iov, cnt);
11656
0
        Py_END_ALLOW_THREADS
11657
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11658
11659
0
    int saved_errno = errno;
11660
0
    iov_cleanup(iov, buf, cnt);
11661
0
    if (n < 0) {
11662
0
        if (!async_err) {
11663
0
            errno = saved_errno;
11664
0
            posix_error();
11665
0
        }
11666
0
        return -1;
11667
0
    }
11668
11669
0
    return n;
11670
0
}
11671
#endif /* HAVE_READV */
11672
11673
11674
#ifdef HAVE_PREAD
11675
/*[clinic input]
11676
@permit_long_summary
11677
os.pread
11678
11679
    fd: int
11680
    length: Py_ssize_t
11681
    offset: Py_off_t
11682
    /
11683
11684
Read a number of bytes from a file descriptor starting at a particular offset.
11685
11686
Read length bytes from file descriptor fd, starting at offset bytes from
11687
the beginning of the file.  The file offset remains unchanged.
11688
[clinic start generated code]*/
11689
11690
static PyObject *
11691
os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
11692
/*[clinic end generated code: output=3f875c1eef82e32f input=5943beb009d3da04]*/
11693
0
{
11694
0
    Py_ssize_t n;
11695
0
    int async_err = 0;
11696
0
    PyObject *buffer;
11697
11698
0
    if (length < 0) {
11699
0
        errno = EINVAL;
11700
0
        return posix_error();
11701
0
    }
11702
0
    buffer = PyBytes_FromStringAndSize((char *)NULL, length);
11703
0
    if (buffer == NULL)
11704
0
        return NULL;
11705
11706
0
    do {
11707
0
        Py_BEGIN_ALLOW_THREADS
11708
0
        _Py_BEGIN_SUPPRESS_IPH
11709
0
        n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
11710
0
        _Py_END_SUPPRESS_IPH
11711
0
        Py_END_ALLOW_THREADS
11712
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11713
11714
0
    if (n < 0) {
11715
0
        if (!async_err) {
11716
0
            posix_error();
11717
0
        }
11718
0
        Py_DECREF(buffer);
11719
0
        return NULL;
11720
0
    }
11721
0
    if (n != length)
11722
0
        _PyBytes_Resize(&buffer, n);
11723
0
    return buffer;
11724
0
}
11725
#endif /* HAVE_PREAD */
11726
11727
#if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
11728
/*[clinic input]
11729
@permit_long_docstring_body
11730
os.preadv -> Py_ssize_t
11731
11732
    fd: int
11733
    buffers: object
11734
    offset: Py_off_t
11735
    flags: int = 0
11736
    /
11737
11738
Reads from a file descriptor into a number of mutable bytes-like objects.
11739
11740
Combines the functionality of readv() and pread(). As readv(), it will
11741
transfer data into each buffer until it is full and then move on to the next
11742
buffer in the sequence to hold the rest of the data. Its fourth argument,
11743
specifies the file offset at which the input operation is to be performed. It
11744
will return the total number of bytes read (which can be less than the total
11745
capacity of all the objects).
11746
11747
The flags argument contains a bitwise OR of zero or more of the following flags:
11748
11749
- RWF_HIPRI
11750
- RWF_NOWAIT
11751
11752
Using non-zero flags requires Linux 4.6 or newer.
11753
[clinic start generated code]*/
11754
11755
static Py_ssize_t
11756
os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
11757
               int flags)
11758
/*[clinic end generated code: output=26fc9c6e58e7ada5 input=c1f876866fcd9d41]*/
11759
0
{
11760
0
    Py_ssize_t cnt, n;
11761
0
    int async_err = 0;
11762
0
    struct iovec *iov;
11763
0
    Py_buffer *buf;
11764
11765
0
    if (!PySequence_Check(buffers)) {
11766
0
        PyErr_SetString(PyExc_TypeError,
11767
0
            "preadv2() arg 2 must be a sequence");
11768
0
        return -1;
11769
0
    }
11770
11771
0
    cnt = PySequence_Size(buffers);
11772
0
    if (cnt < 0) {
11773
0
        return -1;
11774
0
    }
11775
11776
#ifndef HAVE_PREADV2
11777
    if(flags != 0) {
11778
        argument_unavailable_error("preadv2", "flags");
11779
        return -1;
11780
    }
11781
#endif
11782
11783
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
11784
0
        return -1;
11785
0
    }
11786
0
#ifdef HAVE_PREADV2
11787
0
    do {
11788
0
        Py_BEGIN_ALLOW_THREADS
11789
0
        _Py_BEGIN_SUPPRESS_IPH
11790
0
        n = preadv2(fd, iov, cnt, offset, flags);
11791
0
        _Py_END_SUPPRESS_IPH
11792
0
        Py_END_ALLOW_THREADS
11793
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11794
#else
11795
    do {
11796
#if defined(__APPLE__) && defined(__clang__)
11797
/* This entire function will be removed from the module dict when the API
11798
 * is not available.
11799
 */
11800
#pragma clang diagnostic push
11801
#pragma clang diagnostic ignored "-Wunguarded-availability"
11802
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
11803
#endif
11804
        Py_BEGIN_ALLOW_THREADS
11805
        _Py_BEGIN_SUPPRESS_IPH
11806
        n = preadv(fd, iov, cnt, offset);
11807
        _Py_END_SUPPRESS_IPH
11808
        Py_END_ALLOW_THREADS
11809
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11810
11811
#if defined(__APPLE__) && defined(__clang__)
11812
#pragma clang diagnostic pop
11813
#endif
11814
11815
#endif
11816
11817
0
    int saved_errno = errno;
11818
0
    iov_cleanup(iov, buf, cnt);
11819
0
    if (n < 0) {
11820
0
        if (!async_err) {
11821
0
            errno = saved_errno;
11822
0
            posix_error();
11823
0
        }
11824
0
        return -1;
11825
0
    }
11826
11827
0
    return n;
11828
0
}
11829
#endif /* HAVE_PREADV */
11830
11831
11832
/*[clinic input]
11833
os.write -> Py_ssize_t
11834
11835
    fd: int
11836
    data: Py_buffer
11837
    /
11838
11839
Write a bytes object to a file descriptor.
11840
[clinic start generated code]*/
11841
11842
static Py_ssize_t
11843
os_write_impl(PyObject *module, int fd, Py_buffer *data)
11844
/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
11845
0
{
11846
0
    return _Py_write(fd, data->buf, data->len);
11847
0
}
11848
11849
#ifdef HAVE_SENDFILE
11850
#ifdef __APPLE__
11851
/*[clinic input]
11852
os.sendfile
11853
11854
    out_fd: int
11855
    in_fd: int
11856
    offset: Py_off_t
11857
    count as sbytes: Py_off_t
11858
    headers: object(c_default="NULL") = ()
11859
    trailers: object(c_default="NULL") = ()
11860
    flags: int = 0
11861
11862
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
11863
[clinic start generated code]*/
11864
11865
static PyObject *
11866
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
11867
                 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
11868
                 int flags)
11869
/*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
11870
#elif defined(__FreeBSD__) || defined(__DragonFly__)
11871
/*[clinic input]
11872
os.sendfile
11873
11874
    out_fd: int
11875
    in_fd: int
11876
    offset: Py_off_t
11877
    count: Py_ssize_t
11878
    headers: object(c_default="NULL") = ()
11879
    trailers: object(c_default="NULL") = ()
11880
    flags: int = 0
11881
11882
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
11883
[clinic start generated code]*/
11884
11885
static PyObject *
11886
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
11887
                 Py_ssize_t count, PyObject *headers, PyObject *trailers,
11888
                 int flags)
11889
/*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/
11890
#else
11891
/*[clinic input]
11892
os.sendfile
11893
11894
    out_fd: int
11895
    in_fd: int
11896
    offset as offobj: object
11897
    count: Py_ssize_t
11898
11899
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
11900
[clinic start generated code]*/
11901
11902
static PyObject *
11903
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
11904
                 Py_ssize_t count)
11905
/*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/
11906
#endif
11907
0
{
11908
0
    Py_ssize_t ret;
11909
0
    int async_err = 0;
11910
11911
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
11912
#ifndef __APPLE__
11913
    off_t sbytes;
11914
#endif
11915
    Py_buffer *hbuf, *tbuf;
11916
    struct sf_hdtr sf;
11917
11918
    sf.headers = NULL;
11919
    sf.trailers = NULL;
11920
11921
    if (headers != NULL) {
11922
        if (!PySequence_Check(headers)) {
11923
            PyErr_SetString(PyExc_TypeError,
11924
                "sendfile() headers must be a sequence");
11925
            return NULL;
11926
        } else {
11927
            Py_ssize_t i = PySequence_Size(headers);
11928
            if (i < 0)
11929
                return NULL;
11930
            if (i > INT_MAX) {
11931
                PyErr_SetString(PyExc_OverflowError,
11932
                    "sendfile() header is too large");
11933
                return NULL;
11934
            }
11935
            if (i > 0) {
11936
                sf.hdr_cnt = (int)i;
11937
                if (iov_setup(&(sf.headers), &hbuf,
11938
                              headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
11939
                    return NULL;
11940
#ifdef __APPLE__
11941
                for (i = 0; i < sf.hdr_cnt; i++) {
11942
                    Py_ssize_t blen = sf.headers[i].iov_len;
11943
# define OFF_T_MAX 0x7fffffffffffffff
11944
                    if (sbytes >= OFF_T_MAX - blen) {
11945
                        PyErr_SetString(PyExc_OverflowError,
11946
                            "sendfile() header is too large");
11947
                        return NULL;
11948
                    }
11949
                    sbytes += blen;
11950
                }
11951
#endif
11952
            }
11953
        }
11954
    }
11955
    if (trailers != NULL) {
11956
        if (!PySequence_Check(trailers)) {
11957
            PyErr_SetString(PyExc_TypeError,
11958
                "sendfile() trailers must be a sequence");
11959
            return NULL;
11960
        } else {
11961
            Py_ssize_t i = PySequence_Size(trailers);
11962
            if (i < 0)
11963
                return NULL;
11964
            if (i > INT_MAX) {
11965
                PyErr_SetString(PyExc_OverflowError,
11966
                    "sendfile() trailer is too large");
11967
                return NULL;
11968
            }
11969
            if (i > 0) {
11970
                sf.trl_cnt = (int)i;
11971
                if (iov_setup(&(sf.trailers), &tbuf,
11972
                              trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
11973
                    return NULL;
11974
            }
11975
        }
11976
    }
11977
11978
    _Py_BEGIN_SUPPRESS_IPH
11979
    do {
11980
        Py_BEGIN_ALLOW_THREADS
11981
#ifdef __APPLE__
11982
        ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
11983
#else
11984
        ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
11985
#endif
11986
        Py_END_ALLOW_THREADS
11987
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11988
    _Py_END_SUPPRESS_IPH
11989
11990
    int saved_errno = errno;
11991
    if (sf.headers != NULL)
11992
        iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
11993
    if (sf.trailers != NULL)
11994
        iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
11995
11996
    if (ret < 0) {
11997
        if ((saved_errno == EAGAIN) || (saved_errno == EBUSY)) {
11998
            if (sbytes != 0) {
11999
                // some data has been sent
12000
                goto done;
12001
            }
12002
            // no data has been sent; upper application is supposed
12003
            // to retry on EAGAIN or EBUSY
12004
        }
12005
        if (!async_err) {
12006
            errno = saved_errno;
12007
            posix_error();
12008
        }
12009
        return NULL;
12010
    }
12011
    goto done;
12012
12013
done:
12014
    #if !defined(HAVE_LARGEFILE_SUPPORT)
12015
        return PyLong_FromLong(sbytes);
12016
    #else
12017
        return PyLong_FromLongLong(sbytes);
12018
    #endif
12019
12020
#else
12021
0
#ifdef __linux__
12022
0
    if (offobj == Py_None) {
12023
0
        do {
12024
0
            Py_BEGIN_ALLOW_THREADS
12025
0
            ret = sendfile(out_fd, in_fd, NULL, count);
12026
0
            Py_END_ALLOW_THREADS
12027
0
        } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12028
0
        if (ret < 0)
12029
0
            return (!async_err) ? posix_error() : NULL;
12030
0
        return PyLong_FromSsize_t(ret);
12031
0
    }
12032
0
#endif
12033
0
    off_t offset;
12034
0
    if (!Py_off_t_converter(offobj, &offset))
12035
0
        return NULL;
12036
12037
#if defined(__sun) && defined(__SVR4)
12038
    // On Solaris, sendfile raises EINVAL rather than returning 0
12039
    // when the offset is equal or bigger than the in_fd size.
12040
    struct stat st;
12041
12042
    do {
12043
        Py_BEGIN_ALLOW_THREADS
12044
        ret = fstat(in_fd, &st);
12045
        Py_END_ALLOW_THREADS
12046
    } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12047
    if (ret < 0)
12048
        return (!async_err) ? posix_error() : NULL;
12049
12050
    if (offset >= st.st_size) {
12051
        return PyLong_FromLong(0);
12052
    }
12053
12054
    // On illumos specifically sendfile() may perform a partial write but
12055
    // return -1/an error (in one confirmed case the destination socket
12056
    // had a 5 second timeout set and errno was EAGAIN) and it's on the client
12057
    // code to check if the offset parameter was modified by sendfile().
12058
    //
12059
    // We need this variable to track said change.
12060
    off_t original_offset = offset;
12061
#endif
12062
12063
0
    do {
12064
0
        Py_BEGIN_ALLOW_THREADS
12065
0
        ret = sendfile(out_fd, in_fd, &offset, count);
12066
#if defined(__sun) && defined(__SVR4)
12067
        // This handles illumos-specific sendfile() partial write behavior,
12068
        // see a comment above for more details.
12069
        if (ret < 0 && offset != original_offset) {
12070
            ret = offset - original_offset;
12071
        }
12072
#endif
12073
0
        Py_END_ALLOW_THREADS
12074
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12075
0
    if (ret < 0)
12076
0
        return (!async_err) ? posix_error() : NULL;
12077
0
    return PyLong_FromSsize_t(ret);
12078
0
#endif
12079
0
}
12080
#endif /* HAVE_SENDFILE */
12081
12082
12083
#if defined(__APPLE__)
12084
/*[clinic input]
12085
os._fcopyfile
12086
12087
    in_fd: int
12088
    out_fd: int
12089
    flags: int
12090
    /
12091
12092
Efficiently copy content or metadata of 2 regular file descriptors (macOS).
12093
[clinic start generated code]*/
12094
12095
static PyObject *
12096
os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
12097
/*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
12098
{
12099
    int ret;
12100
12101
    Py_BEGIN_ALLOW_THREADS
12102
    ret = fcopyfile(in_fd, out_fd, NULL, flags);
12103
    Py_END_ALLOW_THREADS
12104
    if (ret < 0)
12105
        return posix_error();
12106
    Py_RETURN_NONE;
12107
}
12108
#endif
12109
12110
12111
/*[clinic input]
12112
os.fstat
12113
12114
    fd : int
12115
12116
Perform a stat system call on the given file descriptor.
12117
12118
Like stat(), but for an open file descriptor.
12119
Equivalent to os.stat(fd).
12120
[clinic start generated code]*/
12121
12122
static PyObject *
12123
os_fstat_impl(PyObject *module, int fd)
12124
/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
12125
0
{
12126
0
    STRUCT_STAT st;
12127
0
    int res;
12128
0
    int async_err = 0;
12129
12130
0
    do {
12131
0
        Py_BEGIN_ALLOW_THREADS
12132
0
        res = FSTAT(fd, &st);
12133
0
        Py_END_ALLOW_THREADS
12134
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12135
0
    if (res != 0) {
12136
#ifdef MS_WINDOWS
12137
        return PyErr_SetFromWindowsErr(0);
12138
#else
12139
0
        return (!async_err) ? posix_error() : NULL;
12140
0
#endif
12141
0
    }
12142
12143
0
    return _pystat_fromstructstat(module, &st);
12144
0
}
12145
12146
12147
/*[clinic input]
12148
os.isatty -> bool
12149
    fd: int
12150
    /
12151
12152
Return True if the fd is connected to a terminal.
12153
12154
Return True if the file descriptor is an open file descriptor
12155
connected to the slave end of a terminal.
12156
[clinic start generated code]*/
12157
12158
static int
12159
os_isatty_impl(PyObject *module, int fd)
12160
/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
12161
0
{
12162
0
    int return_value;
12163
0
    Py_BEGIN_ALLOW_THREADS
12164
0
    _Py_BEGIN_SUPPRESS_IPH
12165
0
    return_value = isatty(fd);
12166
0
    _Py_END_SUPPRESS_IPH
12167
0
    Py_END_ALLOW_THREADS
12168
0
    return return_value;
12169
0
}
12170
12171
12172
#ifdef HAVE_PIPE
12173
/*[clinic input]
12174
os.pipe
12175
12176
Create a pipe.
12177
12178
Returns a tuple of two file descriptors:
12179
  (read_fd, write_fd)
12180
[clinic start generated code]*/
12181
12182
static PyObject *
12183
os_pipe_impl(PyObject *module)
12184
/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
12185
0
{
12186
0
    int fds[2];
12187
#ifdef MS_WINDOWS
12188
    HANDLE read, write;
12189
    SECURITY_ATTRIBUTES attr;
12190
    BOOL ok;
12191
#else
12192
0
    int res;
12193
0
#endif
12194
12195
#ifdef MS_WINDOWS
12196
    attr.nLength = sizeof(attr);
12197
    attr.lpSecurityDescriptor = NULL;
12198
    attr.bInheritHandle = FALSE;
12199
12200
    Py_BEGIN_ALLOW_THREADS
12201
    ok = CreatePipe(&read, &write, &attr, 0);
12202
    if (ok) {
12203
        fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY | _O_NOINHERIT);
12204
        fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY | _O_NOINHERIT);
12205
        if (fds[0] == -1 || fds[1] == -1) {
12206
            CloseHandle(read);
12207
            CloseHandle(write);
12208
            ok = 0;
12209
        }
12210
    }
12211
    Py_END_ALLOW_THREADS
12212
12213
    if (!ok)
12214
        return PyErr_SetFromWindowsErr(0);
12215
#else
12216
12217
0
#ifdef HAVE_PIPE2
12218
0
    Py_BEGIN_ALLOW_THREADS
12219
0
    res = pipe2(fds, O_CLOEXEC);
12220
0
    Py_END_ALLOW_THREADS
12221
12222
0
    if (res != 0 && errno == ENOSYS)
12223
0
    {
12224
0
#endif
12225
0
        Py_BEGIN_ALLOW_THREADS
12226
0
        res = pipe(fds);
12227
0
        Py_END_ALLOW_THREADS
12228
12229
0
        if (res == 0) {
12230
0
            if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
12231
0
                close(fds[0]);
12232
0
                close(fds[1]);
12233
0
                return NULL;
12234
0
            }
12235
0
            if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
12236
0
                close(fds[0]);
12237
0
                close(fds[1]);
12238
0
                return NULL;
12239
0
            }
12240
0
        }
12241
0
#ifdef HAVE_PIPE2
12242
0
    }
12243
0
#endif
12244
12245
0
    if (res != 0)
12246
0
        return PyErr_SetFromErrno(PyExc_OSError);
12247
0
#endif /* !MS_WINDOWS */
12248
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12249
0
}
12250
#endif  /* HAVE_PIPE */
12251
12252
12253
#ifdef HAVE_PIPE2
12254
/*[clinic input]
12255
os.pipe2
12256
12257
    flags: int
12258
    /
12259
12260
Create a pipe with flags set atomically.
12261
12262
Returns a tuple of two file descriptors:
12263
  (read_fd, write_fd)
12264
12265
flags can be constructed by ORing together one or more of these values:
12266
O_NONBLOCK, O_CLOEXEC.
12267
[clinic start generated code]*/
12268
12269
static PyObject *
12270
os_pipe2_impl(PyObject *module, int flags)
12271
/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
12272
0
{
12273
0
    int fds[2];
12274
0
    int res;
12275
12276
0
    res = pipe2(fds, flags);
12277
0
    if (res != 0)
12278
0
        return posix_error();
12279
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12280
0
}
12281
#endif /* HAVE_PIPE2 */
12282
12283
12284
#ifdef HAVE_WRITEV
12285
/*[clinic input]
12286
os.writev -> Py_ssize_t
12287
    fd: int
12288
    buffers: object
12289
    /
12290
12291
Iterate over buffers, and write the contents of each to a file descriptor.
12292
12293
Returns the total number of bytes written.
12294
buffers must be a sequence of bytes-like objects.
12295
[clinic start generated code]*/
12296
12297
static Py_ssize_t
12298
os_writev_impl(PyObject *module, int fd, PyObject *buffers)
12299
/*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
12300
0
{
12301
0
    Py_ssize_t cnt;
12302
0
    Py_ssize_t result;
12303
0
    int async_err = 0;
12304
0
    struct iovec *iov;
12305
0
    Py_buffer *buf;
12306
12307
0
    if (!PySequence_Check(buffers)) {
12308
0
        PyErr_SetString(PyExc_TypeError,
12309
0
            "writev() arg 2 must be a sequence");
12310
0
        return -1;
12311
0
    }
12312
0
    cnt = PySequence_Size(buffers);
12313
0
    if (cnt < 0)
12314
0
        return -1;
12315
12316
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12317
0
        return -1;
12318
0
    }
12319
12320
0
    do {
12321
0
        Py_BEGIN_ALLOW_THREADS
12322
0
        result = writev(fd, iov, cnt);
12323
0
        Py_END_ALLOW_THREADS
12324
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12325
12326
0
    if (result < 0 && !async_err)
12327
0
        posix_error();
12328
12329
0
    iov_cleanup(iov, buf, cnt);
12330
0
    return result;
12331
0
}
12332
#endif /* HAVE_WRITEV */
12333
12334
12335
#ifdef HAVE_PWRITE
12336
/*[clinic input]
12337
os.pwrite -> Py_ssize_t
12338
12339
    fd: int
12340
    buffer: Py_buffer
12341
    offset: Py_off_t
12342
    /
12343
12344
Write bytes to a file descriptor starting at a particular offset.
12345
12346
Write buffer to fd, starting at offset bytes from the beginning of
12347
the file.  Returns the number of bytes written.  Does not change the
12348
current file offset.
12349
[clinic start generated code]*/
12350
12351
static Py_ssize_t
12352
os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
12353
/*[clinic end generated code: output=c74da630758ee925 input=614acbc7e5a0339a]*/
12354
0
{
12355
0
    Py_ssize_t size;
12356
0
    int async_err = 0;
12357
12358
0
    do {
12359
0
        Py_BEGIN_ALLOW_THREADS
12360
0
        _Py_BEGIN_SUPPRESS_IPH
12361
0
        size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
12362
0
        _Py_END_SUPPRESS_IPH
12363
0
        Py_END_ALLOW_THREADS
12364
0
    } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12365
12366
0
    if (size < 0 && !async_err)
12367
0
        posix_error();
12368
0
    return size;
12369
0
}
12370
#endif /* HAVE_PWRITE */
12371
12372
#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12373
/*[clinic input]
12374
@permit_long_summary
12375
@permit_long_docstring_body
12376
os.pwritev -> Py_ssize_t
12377
12378
    fd: int
12379
    buffers: object
12380
    offset: Py_off_t
12381
    flags: int = 0
12382
    /
12383
12384
Writes the contents of bytes-like objects to a file descriptor at a given offset.
12385
12386
Combines the functionality of writev() and pwrite(). All buffers must be a sequence
12387
of bytes-like objects. Buffers are processed in array order. Entire contents of first
12388
buffer is written before proceeding to second, and so on. The operating system may
12389
set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
12390
This function writes the contents of each object to the file descriptor and returns
12391
the total number of bytes written.
12392
12393
The flags argument contains a bitwise OR of zero or more of the following flags:
12394
12395
- RWF_DSYNC
12396
- RWF_SYNC
12397
- RWF_APPEND
12398
12399
Using non-zero flags requires Linux 4.7 or newer.
12400
[clinic start generated code]*/
12401
12402
static Py_ssize_t
12403
os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12404
                int flags)
12405
/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=99d8a21493ff76ca]*/
12406
0
{
12407
0
    Py_ssize_t cnt;
12408
0
    Py_ssize_t result;
12409
0
    int async_err = 0;
12410
0
    struct iovec *iov;
12411
0
    Py_buffer *buf;
12412
12413
0
    if (!PySequence_Check(buffers)) {
12414
0
        PyErr_SetString(PyExc_TypeError,
12415
0
            "pwritev() arg 2 must be a sequence");
12416
0
        return -1;
12417
0
    }
12418
12419
0
    cnt = PySequence_Size(buffers);
12420
0
    if (cnt < 0) {
12421
0
        return -1;
12422
0
    }
12423
12424
#ifndef HAVE_PWRITEV2
12425
    if(flags != 0) {
12426
        argument_unavailable_error("pwritev2", "flags");
12427
        return -1;
12428
    }
12429
#endif
12430
12431
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12432
0
        return -1;
12433
0
    }
12434
0
#ifdef HAVE_PWRITEV2
12435
0
    do {
12436
0
        Py_BEGIN_ALLOW_THREADS
12437
0
        _Py_BEGIN_SUPPRESS_IPH
12438
0
        result = pwritev2(fd, iov, cnt, offset, flags);
12439
0
        _Py_END_SUPPRESS_IPH
12440
0
        Py_END_ALLOW_THREADS
12441
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12442
#else
12443
12444
#if defined(__APPLE__) && defined(__clang__)
12445
/* This entire function will be removed from the module dict when the API
12446
 * is not available.
12447
 */
12448
#pragma clang diagnostic push
12449
#pragma clang diagnostic ignored "-Wunguarded-availability"
12450
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12451
#endif
12452
    do {
12453
        Py_BEGIN_ALLOW_THREADS
12454
        _Py_BEGIN_SUPPRESS_IPH
12455
        result = pwritev(fd, iov, cnt, offset);
12456
        _Py_END_SUPPRESS_IPH
12457
        Py_END_ALLOW_THREADS
12458
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12459
12460
#if defined(__APPLE__) && defined(__clang__)
12461
#pragma clang diagnostic pop
12462
#endif
12463
12464
#endif
12465
12466
0
    if (result < 0) {
12467
0
        if (!async_err) {
12468
0
            posix_error();
12469
0
        }
12470
0
        result = -1;
12471
0
    }
12472
0
    iov_cleanup(iov, buf, cnt);
12473
12474
0
    return result;
12475
0
}
12476
#endif /* HAVE_PWRITEV */
12477
12478
#ifdef HAVE_COPY_FILE_RANGE
12479
/*[clinic input]
12480
12481
os.copy_file_range
12482
    src: int
12483
        Source file descriptor.
12484
    dst: int
12485
        Destination file descriptor.
12486
    count: Py_ssize_t
12487
        Number of bytes to copy.
12488
    offset_src: object = None
12489
        Starting offset in src.
12490
    offset_dst: object = None
12491
        Starting offset in dst.
12492
12493
Copy count bytes from one file descriptor to another.
12494
12495
If offset_src is None, then src is read from the current position;
12496
respectively for offset_dst.
12497
[clinic start generated code]*/
12498
12499
static PyObject *
12500
os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
12501
                        PyObject *offset_src, PyObject *offset_dst)
12502
/*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
12503
0
{
12504
0
    off_t offset_src_val, offset_dst_val;
12505
0
    off_t *p_offset_src = NULL;
12506
0
    off_t *p_offset_dst = NULL;
12507
0
    Py_ssize_t ret;
12508
0
    int async_err = 0;
12509
    /* The flags argument is provided to allow
12510
     * for future extensions and currently must be to 0. */
12511
0
    int flags = 0;
12512
12513
12514
0
    if (count < 0) {
12515
0
        PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
12516
0
        return NULL;
12517
0
    }
12518
12519
0
    if (offset_src != Py_None) {
12520
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
12521
0
            return NULL;
12522
0
        }
12523
0
        p_offset_src = &offset_src_val;
12524
0
    }
12525
12526
0
    if (offset_dst != Py_None) {
12527
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
12528
0
            return NULL;
12529
0
        }
12530
0
        p_offset_dst = &offset_dst_val;
12531
0
    }
12532
12533
0
    do {
12534
0
        Py_BEGIN_ALLOW_THREADS
12535
0
        ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
12536
0
        Py_END_ALLOW_THREADS
12537
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12538
12539
0
    if (ret < 0) {
12540
0
        return (!async_err) ? posix_error() : NULL;
12541
0
    }
12542
12543
0
    return PyLong_FromSsize_t(ret);
12544
0
}
12545
#endif /* HAVE_COPY_FILE_RANGE*/
12546
12547
#if (defined(HAVE_SPLICE) && !defined(_AIX))
12548
/*[clinic input]
12549
12550
os.splice
12551
    src: int
12552
        Source file descriptor.
12553
    dst: int
12554
        Destination file descriptor.
12555
    count: Py_ssize_t
12556
        Number of bytes to copy.
12557
    offset_src: object = None
12558
        Starting offset in src.
12559
    offset_dst: object = None
12560
        Starting offset in dst.
12561
    flags: unsigned_int = 0
12562
        Flags to modify the semantics of the call.
12563
12564
Transfer count bytes from one pipe to a descriptor or vice versa.
12565
12566
If offset_src is None, then src is read from the current position;
12567
respectively for offset_dst. The offset associated to the file
12568
descriptor that refers to a pipe must be None.
12569
[clinic start generated code]*/
12570
12571
static PyObject *
12572
os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
12573
               PyObject *offset_src, PyObject *offset_dst,
12574
               unsigned int flags)
12575
/*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/
12576
0
{
12577
0
    off_t offset_src_val, offset_dst_val;
12578
0
    off_t *p_offset_src = NULL;
12579
0
    off_t *p_offset_dst = NULL;
12580
0
    Py_ssize_t ret;
12581
0
    int async_err = 0;
12582
12583
0
    if (count < 0) {
12584
0
        PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
12585
0
        return NULL;
12586
0
    }
12587
12588
0
    if (offset_src != Py_None) {
12589
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
12590
0
            return NULL;
12591
0
        }
12592
0
        p_offset_src = &offset_src_val;
12593
0
    }
12594
12595
0
    if (offset_dst != Py_None) {
12596
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
12597
0
            return NULL;
12598
0
        }
12599
0
        p_offset_dst = &offset_dst_val;
12600
0
    }
12601
12602
0
    do {
12603
0
        Py_BEGIN_ALLOW_THREADS
12604
0
        ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
12605
0
        Py_END_ALLOW_THREADS
12606
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12607
12608
0
    if (ret < 0) {
12609
0
        return (!async_err) ? posix_error() : NULL;
12610
0
    }
12611
12612
0
    return PyLong_FromSsize_t(ret);
12613
0
}
12614
#endif /* HAVE_SPLICE*/
12615
12616
#ifdef HAVE_MKFIFO
12617
/*[clinic input]
12618
os.mkfifo
12619
12620
    path: path_t
12621
    mode: int=0o666
12622
    *
12623
    dir_fd: dir_fd(requires='mkfifoat')=None
12624
12625
Create a "fifo" (a POSIX named pipe).
12626
12627
If dir_fd is not None, it should be a file descriptor open to a directory,
12628
  and path should be relative; path will then be relative to that directory.
12629
dir_fd may not be implemented on your platform.
12630
  If it is unavailable, using it will raise a NotImplementedError.
12631
[clinic start generated code]*/
12632
12633
static PyObject *
12634
os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
12635
/*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
12636
0
{
12637
0
    int result;
12638
0
    int async_err = 0;
12639
0
#ifdef HAVE_MKFIFOAT
12640
0
    int mkfifoat_unavailable = 0;
12641
0
#endif
12642
12643
0
    do {
12644
0
        Py_BEGIN_ALLOW_THREADS
12645
0
#ifdef HAVE_MKFIFOAT
12646
0
        if (dir_fd != DEFAULT_DIR_FD) {
12647
0
            if (HAVE_MKFIFOAT_RUNTIME) {
12648
0
                result = mkfifoat(dir_fd, path->narrow, mode);
12649
12650
0
            } else {
12651
0
                mkfifoat_unavailable = 1;
12652
0
                result = 0;
12653
0
            }
12654
0
        } else
12655
0
#endif
12656
0
            result = mkfifo(path->narrow, mode);
12657
0
        Py_END_ALLOW_THREADS
12658
0
    } while (result != 0 && errno == EINTR &&
12659
0
             !(async_err = PyErr_CheckSignals()));
12660
12661
0
#ifdef HAVE_MKFIFOAT
12662
0
    if (mkfifoat_unavailable) {
12663
0
        argument_unavailable_error(NULL, "dir_fd");
12664
0
        return NULL;
12665
0
    }
12666
0
#endif
12667
12668
0
    if (result != 0)
12669
0
        return (!async_err) ? posix_error() : NULL;
12670
12671
0
    Py_RETURN_NONE;
12672
0
}
12673
#endif /* HAVE_MKFIFO */
12674
12675
12676
#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
12677
/*[clinic input]
12678
@permit_long_docstring_body
12679
os.mknod
12680
12681
    path: path_t
12682
    mode: int=0o600
12683
    device: dev_t=0
12684
    *
12685
    dir_fd: dir_fd(requires='mknodat')=None
12686
12687
Create a node in the file system.
12688
12689
Create a node in the file system (file, device special file or named pipe)
12690
at path.  mode specifies both the permissions to use and the
12691
type of node to be created, being combined (bitwise OR) with one of
12692
S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
12693
device defines the newly created device special file (probably using
12694
os.makedev()).  Otherwise device is ignored.
12695
12696
If dir_fd is not None, it should be a file descriptor open to a directory,
12697
  and path should be relative; path will then be relative to that directory.
12698
dir_fd may not be implemented on your platform.
12699
  If it is unavailable, using it will raise a NotImplementedError.
12700
[clinic start generated code]*/
12701
12702
static PyObject *
12703
os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
12704
              int dir_fd)
12705
/*[clinic end generated code: output=92e55d3ca8917461 input=7121c4723d22545b]*/
12706
0
{
12707
0
    int result;
12708
0
    int async_err = 0;
12709
0
#ifdef HAVE_MKNODAT
12710
0
    int mknodat_unavailable = 0;
12711
0
#endif
12712
12713
0
    do {
12714
0
        Py_BEGIN_ALLOW_THREADS
12715
0
#ifdef HAVE_MKNODAT
12716
0
        if (dir_fd != DEFAULT_DIR_FD) {
12717
0
            if (HAVE_MKNODAT_RUNTIME) {
12718
0
                result = mknodat(dir_fd, path->narrow, mode, device);
12719
12720
0
            } else {
12721
0
                mknodat_unavailable = 1;
12722
0
                result = 0;
12723
0
            }
12724
0
        } else
12725
0
#endif
12726
0
            result = mknod(path->narrow, mode, device);
12727
0
        Py_END_ALLOW_THREADS
12728
0
    } while (result != 0 && errno == EINTR &&
12729
0
             !(async_err = PyErr_CheckSignals()));
12730
0
#ifdef HAVE_MKNODAT
12731
0
    if (mknodat_unavailable) {
12732
0
        argument_unavailable_error(NULL, "dir_fd");
12733
0
        return NULL;
12734
0
    }
12735
0
#endif
12736
0
    if (result != 0)
12737
0
        return (!async_err) ? posix_error() : NULL;
12738
12739
0
    Py_RETURN_NONE;
12740
0
}
12741
#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
12742
12743
12744
#ifdef HAVE_DEVICE_MACROS
12745
static PyObject *
12746
major_minor_conv(unsigned int value)
12747
0
{
12748
0
#ifdef NODEV
12749
0
    if (value == (unsigned int)NODEV) {
12750
0
        return PyLong_FromLong((int)NODEV);
12751
0
    }
12752
0
#endif
12753
0
    return PyLong_FromUnsignedLong(value);
12754
0
}
12755
12756
static int
12757
major_minor_check(dev_t value)
12758
0
{
12759
0
#ifdef NODEV
12760
0
    if (value == NODEV) {
12761
0
        return 1;
12762
0
    }
12763
0
#endif
12764
0
    return (dev_t)(unsigned int)value == value;
12765
0
}
12766
12767
/*[clinic input]
12768
os.major
12769
12770
    device: dev_t
12771
    /
12772
12773
Extracts a device major number from a raw device number.
12774
[clinic start generated code]*/
12775
12776
static PyObject *
12777
os_major_impl(PyObject *module, dev_t device)
12778
/*[clinic end generated code: output=4071ffee17647891 input=b1a0a14ec9448229]*/
12779
0
{
12780
0
    return major_minor_conv(major(device));
12781
0
}
12782
12783
12784
/*[clinic input]
12785
os.minor
12786
12787
    device: dev_t
12788
    /
12789
12790
Extracts a device minor number from a raw device number.
12791
[clinic start generated code]*/
12792
12793
static PyObject *
12794
os_minor_impl(PyObject *module, dev_t device)
12795
/*[clinic end generated code: output=306cb78e3bc5004f input=2f686e463682a9da]*/
12796
0
{
12797
0
    return major_minor_conv(minor(device));
12798
0
}
12799
12800
12801
/*[clinic input]
12802
os.makedev -> dev_t
12803
12804
    major: dev_t
12805
    minor: dev_t
12806
    /
12807
12808
Composes a raw device number from the major and minor device numbers.
12809
[clinic start generated code]*/
12810
12811
static dev_t
12812
os_makedev_impl(PyObject *module, dev_t major, dev_t minor)
12813
/*[clinic end generated code: output=cad6125c51f5af80 input=2146126ec02e55c1]*/
12814
0
{
12815
0
    if (!major_minor_check(major) || !major_minor_check(minor)) {
12816
0
        PyErr_SetString(PyExc_OverflowError,
12817
0
                        "Python int too large to convert to C unsigned int");
12818
0
        return (dev_t)-1;
12819
0
    }
12820
0
    return makedev(major, minor);
12821
0
}
12822
#endif /* HAVE_DEVICE_MACROS */
12823
12824
12825
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
12826
/*[clinic input]
12827
os.ftruncate
12828
12829
    fd: int
12830
    length: Py_off_t
12831
    /
12832
12833
Truncate a file, specified by file descriptor, to a specific length.
12834
[clinic start generated code]*/
12835
12836
static PyObject *
12837
os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
12838
/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
12839
0
{
12840
0
    int result;
12841
0
    int async_err = 0;
12842
12843
0
    if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
12844
0
        return NULL;
12845
0
    }
12846
12847
0
    do {
12848
0
        Py_BEGIN_ALLOW_THREADS
12849
0
        _Py_BEGIN_SUPPRESS_IPH
12850
#ifdef MS_WINDOWS
12851
        result = _chsize_s(fd, length);
12852
#else
12853
0
        result = ftruncate(fd, length);
12854
0
#endif
12855
0
        _Py_END_SUPPRESS_IPH
12856
0
        Py_END_ALLOW_THREADS
12857
0
    } while (result != 0 && errno == EINTR &&
12858
0
             !(async_err = PyErr_CheckSignals()));
12859
0
    if (result != 0)
12860
0
        return (!async_err) ? posix_error() : NULL;
12861
0
    Py_RETURN_NONE;
12862
0
}
12863
#endif /* HAVE_FTRUNCATE || MS_WINDOWS */
12864
12865
12866
#if defined HAVE_TRUNCATE || defined MS_WINDOWS
12867
/*[clinic input]
12868
os.truncate
12869
    path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
12870
    length: Py_off_t
12871
12872
Truncate a file, specified by path, to a specific length.
12873
12874
On some platforms, path may also be specified as an open file descriptor.
12875
  If this functionality is unavailable, using it raises an exception.
12876
[clinic start generated code]*/
12877
12878
static PyObject *
12879
os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
12880
/*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
12881
0
{
12882
0
    int result;
12883
#ifdef MS_WINDOWS
12884
    int fd;
12885
#endif
12886
12887
0
    if (path->fd != -1)
12888
0
        return os_ftruncate_impl(module, path->fd, length);
12889
12890
0
    if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
12891
0
        return NULL;
12892
0
    }
12893
12894
0
    Py_BEGIN_ALLOW_THREADS
12895
0
    _Py_BEGIN_SUPPRESS_IPH
12896
#ifdef MS_WINDOWS
12897
    fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
12898
    if (fd < 0)
12899
        result = -1;
12900
    else {
12901
        result = _chsize_s(fd, length);
12902
        close(fd);
12903
        if (result < 0)
12904
            errno = result;
12905
    }
12906
#else
12907
0
    result = truncate(path->narrow, length);
12908
0
#endif
12909
0
    _Py_END_SUPPRESS_IPH
12910
0
    Py_END_ALLOW_THREADS
12911
0
    if (result < 0)
12912
0
        return posix_path_error(path);
12913
12914
0
    Py_RETURN_NONE;
12915
0
}
12916
#endif /* HAVE_TRUNCATE || MS_WINDOWS */
12917
12918
12919
/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
12920
   and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
12921
   defined, which is the case in Python on AIX. AIX bug report:
12922
   http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
12923
#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
12924
#  define POSIX_FADVISE_AIX_BUG
12925
#endif
12926
12927
12928
/* GH-111804: Due to posix_fallocate() not having consistent semantics across
12929
   OSs, support was dropped in WASI preview2. */
12930
#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) && \
12931
    !defined(__wasi__)
12932
/*[clinic input]
12933
os.posix_fallocate
12934
12935
    fd: int
12936
    offset: Py_off_t
12937
    length: Py_off_t
12938
    /
12939
12940
Ensure a file has allocated at least a particular number of bytes on disk.
12941
12942
Ensure that the file specified by fd encompasses a range of bytes
12943
starting at offset bytes from the beginning and continuing for length bytes.
12944
[clinic start generated code]*/
12945
12946
static PyObject *
12947
os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
12948
                        Py_off_t length)
12949
/*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
12950
0
{
12951
0
    int result;
12952
0
    int async_err = 0;
12953
12954
0
    do {
12955
0
        Py_BEGIN_ALLOW_THREADS
12956
0
        result = posix_fallocate(fd, offset, length);
12957
0
        Py_END_ALLOW_THREADS
12958
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
12959
12960
0
    if (result == 0)
12961
0
        Py_RETURN_NONE;
12962
12963
0
    if (async_err)
12964
0
        return NULL;
12965
12966
0
    errno = result;
12967
0
    return posix_error();
12968
0
}
12969
#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG && !defined(__wasi__) */
12970
12971
12972
#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
12973
/*[clinic input]
12974
os.posix_fadvise
12975
12976
    fd: int
12977
    offset: Py_off_t
12978
    length: Py_off_t
12979
    advice: int
12980
    /
12981
12982
Announce an intention to access data in a specific pattern.
12983
12984
Announce an intention to access data in a specific pattern, thus allowing
12985
the kernel to make optimizations.
12986
The advice applies to the region of the file specified by fd starting at
12987
offset and continuing for length bytes.
12988
advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
12989
POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
12990
POSIX_FADV_DONTNEED.
12991
[clinic start generated code]*/
12992
12993
static PyObject *
12994
os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
12995
                      Py_off_t length, int advice)
12996
/*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
12997
0
{
12998
0
    int result;
12999
0
    int async_err = 0;
13000
13001
0
    do {
13002
0
        Py_BEGIN_ALLOW_THREADS
13003
0
        result = posix_fadvise(fd, offset, length, advice);
13004
0
        Py_END_ALLOW_THREADS
13005
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13006
13007
0
    if (result == 0)
13008
0
        Py_RETURN_NONE;
13009
13010
0
    if (async_err)
13011
0
        return NULL;
13012
13013
0
    errno = result;
13014
0
    return posix_error();
13015
0
}
13016
#endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
13017
13018
13019
#ifdef MS_WINDOWS
13020
static PyObject*
13021
win32_putenv(PyObject *name, PyObject *value)
13022
{
13023
    /* Search from index 1 because on Windows starting '=' is allowed for
13024
       defining hidden environment variables. */
13025
    if (PyUnicode_GET_LENGTH(name) == 0 ||
13026
        PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
13027
    {
13028
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13029
        return NULL;
13030
    }
13031
    PyObject *unicode;
13032
    if (value != NULL) {
13033
        unicode = PyUnicode_FromFormat("%U=%U", name, value);
13034
    }
13035
    else {
13036
        unicode = PyUnicode_FromFormat("%U=", name);
13037
    }
13038
    if (unicode == NULL) {
13039
        return NULL;
13040
    }
13041
13042
    Py_ssize_t size;
13043
    wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
13044
    Py_DECREF(unicode);
13045
13046
    if (env == NULL) {
13047
        return NULL;
13048
    }
13049
    if (size > _MAX_ENV) {
13050
        PyErr_Format(PyExc_ValueError,
13051
                     "the environment variable is longer than %u characters",
13052
                     _MAX_ENV);
13053
        PyMem_Free(env);
13054
        return NULL;
13055
    }
13056
    if (wcslen(env) != (size_t)size) {
13057
        PyErr_SetString(PyExc_ValueError,
13058
                        "embedded null character");
13059
        PyMem_Free(env);
13060
        return NULL;
13061
    }
13062
13063
    /* _wputenv() and SetEnvironmentVariableW() update the environment in the
13064
       Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
13065
       and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
13066
13067
       Prefer _wputenv() to be compatible with C libraries using CRT
13068
       variables and CRT functions using these variables (ex: getenv()). */
13069
    int err = _wputenv(env);
13070
13071
    if (err) {
13072
        posix_error();
13073
        PyMem_Free(env);
13074
        return NULL;
13075
    }
13076
    PyMem_Free(env);
13077
13078
    Py_RETURN_NONE;
13079
}
13080
#endif
13081
13082
13083
#ifdef MS_WINDOWS
13084
/*[clinic input]
13085
os.putenv
13086
13087
    name: unicode
13088
    value: unicode
13089
    /
13090
13091
Change or add an environment variable.
13092
[clinic start generated code]*/
13093
13094
static PyObject *
13095
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13096
/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
13097
{
13098
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13099
        return NULL;
13100
    }
13101
    return win32_putenv(name, value);
13102
}
13103
#else
13104
/*[clinic input]
13105
os.putenv
13106
13107
    name: FSConverter
13108
    value: FSConverter
13109
    /
13110
13111
Change or add an environment variable.
13112
[clinic start generated code]*/
13113
13114
static PyObject *
13115
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13116
/*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
13117
0
{
13118
0
    const char *name_string = PyBytes_AS_STRING(name);
13119
0
    const char *value_string = PyBytes_AS_STRING(value);
13120
13121
0
    if (strchr(name_string, '=') != NULL) {
13122
0
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13123
0
        return NULL;
13124
0
    }
13125
13126
0
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13127
0
        return NULL;
13128
0
    }
13129
13130
0
    if (setenv(name_string, value_string, 1)) {
13131
0
        return posix_error();
13132
0
    }
13133
0
    Py_RETURN_NONE;
13134
0
}
13135
#endif  /* !defined(MS_WINDOWS) */
13136
13137
13138
#ifdef MS_WINDOWS
13139
/*[clinic input]
13140
os.unsetenv
13141
    name: unicode
13142
    /
13143
13144
Delete an environment variable.
13145
[clinic start generated code]*/
13146
13147
static PyObject *
13148
os_unsetenv_impl(PyObject *module, PyObject *name)
13149
/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
13150
{
13151
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13152
        return NULL;
13153
    }
13154
    return win32_putenv(name, NULL);
13155
}
13156
#else
13157
/*[clinic input]
13158
os.unsetenv
13159
    name: FSConverter
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=2bb5288a599c7107]*/
13168
0
{
13169
0
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13170
0
        return NULL;
13171
0
    }
13172
#ifdef HAVE_BROKEN_UNSETENV
13173
    unsetenv(PyBytes_AS_STRING(name));
13174
#else
13175
0
    int err = unsetenv(PyBytes_AS_STRING(name));
13176
0
    if (err) {
13177
0
        return posix_error();
13178
0
    }
13179
0
#endif
13180
13181
0
    Py_RETURN_NONE;
13182
0
}
13183
#endif /* !MS_WINDOWS */
13184
13185
13186
/*[clinic input]
13187
os.strerror
13188
13189
    code: int
13190
    /
13191
13192
Translate an error code to a message string.
13193
[clinic start generated code]*/
13194
13195
static PyObject *
13196
os_strerror_impl(PyObject *module, int code)
13197
/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
13198
0
{
13199
0
    char *message = strerror(code);
13200
0
    if (message == NULL) {
13201
0
        PyErr_SetString(PyExc_ValueError,
13202
0
                        "strerror() argument out of range");
13203
0
        return NULL;
13204
0
    }
13205
0
    return PyUnicode_DecodeLocale(message, "surrogateescape");
13206
0
}
13207
13208
13209
#ifdef HAVE_SYS_WAIT_H
13210
#ifdef WCOREDUMP
13211
/*[clinic input]
13212
os.WCOREDUMP -> bool
13213
13214
    status: int
13215
    /
13216
13217
Return True if the process returning status was dumped to a core file.
13218
[clinic start generated code]*/
13219
13220
static int
13221
os_WCOREDUMP_impl(PyObject *module, int status)
13222
/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
13223
0
{
13224
0
    WAIT_TYPE wait_status;
13225
0
    WAIT_STATUS_INT(wait_status) = status;
13226
0
    return WCOREDUMP(wait_status);
13227
0
}
13228
#endif /* WCOREDUMP */
13229
13230
13231
#ifdef WIFCONTINUED
13232
/*[clinic input]
13233
os.WIFCONTINUED -> bool
13234
13235
    status: int
13236
13237
Return True if a particular process was continued from a job control stop.
13238
13239
Return True if the process returning status was continued from a
13240
job control stop.
13241
[clinic start generated code]*/
13242
13243
static int
13244
os_WIFCONTINUED_impl(PyObject *module, int status)
13245
/*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
13246
0
{
13247
0
    WAIT_TYPE wait_status;
13248
0
    WAIT_STATUS_INT(wait_status) = status;
13249
0
    return WIFCONTINUED(wait_status);
13250
0
}
13251
#endif /* WIFCONTINUED */
13252
13253
13254
#ifdef WIFSTOPPED
13255
/*[clinic input]
13256
os.WIFSTOPPED -> bool
13257
13258
    status: int
13259
13260
Return True if the process returning status was stopped.
13261
[clinic start generated code]*/
13262
13263
static int
13264
os_WIFSTOPPED_impl(PyObject *module, int status)
13265
/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
13266
0
{
13267
0
    WAIT_TYPE wait_status;
13268
0
    WAIT_STATUS_INT(wait_status) = status;
13269
0
    return WIFSTOPPED(wait_status);
13270
0
}
13271
#endif /* WIFSTOPPED */
13272
13273
13274
#ifdef WIFSIGNALED
13275
/*[clinic input]
13276
os.WIFSIGNALED -> bool
13277
13278
    status: int
13279
13280
Return True if the process returning status was terminated by a signal.
13281
[clinic start generated code]*/
13282
13283
static int
13284
os_WIFSIGNALED_impl(PyObject *module, int status)
13285
/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
13286
0
{
13287
0
    WAIT_TYPE wait_status;
13288
0
    WAIT_STATUS_INT(wait_status) = status;
13289
0
    return WIFSIGNALED(wait_status);
13290
0
}
13291
#endif /* WIFSIGNALED */
13292
13293
13294
#ifdef WIFEXITED
13295
/*[clinic input]
13296
@permit_long_summary
13297
os.WIFEXITED -> bool
13298
13299
    status: int
13300
13301
Return True if the process returning status exited via the exit() system call.
13302
[clinic start generated code]*/
13303
13304
static int
13305
os_WIFEXITED_impl(PyObject *module, int status)
13306
/*[clinic end generated code: output=01c09d6ebfeea397 input=8c24a82148709b30]*/
13307
0
{
13308
0
    WAIT_TYPE wait_status;
13309
0
    WAIT_STATUS_INT(wait_status) = status;
13310
0
    return WIFEXITED(wait_status);
13311
0
}
13312
#endif /* WIFEXITED */
13313
13314
13315
#ifdef WEXITSTATUS
13316
/*[clinic input]
13317
os.WEXITSTATUS -> int
13318
13319
    status: int
13320
13321
Return the process return code from status.
13322
[clinic start generated code]*/
13323
13324
static int
13325
os_WEXITSTATUS_impl(PyObject *module, int status)
13326
/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
13327
0
{
13328
0
    WAIT_TYPE wait_status;
13329
0
    WAIT_STATUS_INT(wait_status) = status;
13330
0
    return WEXITSTATUS(wait_status);
13331
0
}
13332
#endif /* WEXITSTATUS */
13333
13334
13335
#ifdef WTERMSIG
13336
/*[clinic input]
13337
@permit_long_summary
13338
os.WTERMSIG -> int
13339
13340
    status: int
13341
13342
Return the signal that terminated the process that provided the status value.
13343
[clinic start generated code]*/
13344
13345
static int
13346
os_WTERMSIG_impl(PyObject *module, int status)
13347
/*[clinic end generated code: output=172f7dfc8dcfc3ad input=89072f6cbf3f8050]*/
13348
0
{
13349
0
    WAIT_TYPE wait_status;
13350
0
    WAIT_STATUS_INT(wait_status) = status;
13351
0
    return WTERMSIG(wait_status);
13352
0
}
13353
#endif /* WTERMSIG */
13354
13355
13356
#ifdef WSTOPSIG
13357
/*[clinic input]
13358
os.WSTOPSIG -> int
13359
13360
    status: int
13361
13362
Return the signal that stopped the process that provided the status value.
13363
[clinic start generated code]*/
13364
13365
static int
13366
os_WSTOPSIG_impl(PyObject *module, int status)
13367
/*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
13368
0
{
13369
0
    WAIT_TYPE wait_status;
13370
0
    WAIT_STATUS_INT(wait_status) = status;
13371
0
    return WSTOPSIG(wait_status);
13372
0
}
13373
#endif /* WSTOPSIG */
13374
#endif /* HAVE_SYS_WAIT_H */
13375
13376
13377
#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
13378
#ifdef _SCO_DS
13379
/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
13380
   needed definitions in sys/statvfs.h */
13381
#define _SVID3
13382
#endif
13383
#include <sys/statvfs.h>
13384
13385
#ifdef __APPLE__
13386
/* On macOS struct statvfs uses 32-bit integers for block counts,
13387
 * resulting in overflow when filesystems are larger than 4TB. Therefore
13388
 * os.statvfs is implemented in terms of statfs(2).
13389
 */
13390
13391
static PyObject*
13392
_pystatvfs_fromstructstatfs(PyObject *module, struct statfs st) {
13393
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13394
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13395
    if (v == NULL) {
13396
        return NULL;
13397
    }
13398
13399
    long flags = 0;
13400
    if (st.f_flags & MNT_RDONLY) {
13401
        flags |= ST_RDONLY;
13402
    }
13403
    if (st.f_flags & MNT_NOSUID) {
13404
        flags |= ST_NOSUID;
13405
    }
13406
13407
    _Static_assert(sizeof(st.f_blocks) == sizeof(long long), "assuming large file");
13408
13409
#define SET_ITEM(SEQ, INDEX, EXPR)                       \
13410
    do {                                                 \
13411
        PyObject *obj = (EXPR);                          \
13412
        if (obj == NULL) {                               \
13413
            Py_DECREF((SEQ));                            \
13414
            return NULL;                                 \
13415
        }                                                \
13416
        PyStructSequence_SET_ITEM((SEQ), (INDEX), obj);  \
13417
    } while (0)
13418
13419
    SET_ITEM(v, 0, PyLong_FromLong((long) st.f_iosize));
13420
    SET_ITEM(v, 1, PyLong_FromLong((long) st.f_bsize));
13421
    SET_ITEM(v, 2, PyLong_FromLongLong((long long) st.f_blocks));
13422
    SET_ITEM(v, 3, PyLong_FromLongLong((long long) st.f_bfree));
13423
    SET_ITEM(v, 4, PyLong_FromLongLong((long long) st.f_bavail));
13424
    SET_ITEM(v, 5, PyLong_FromLongLong((long long) st.f_files));
13425
    SET_ITEM(v, 6, PyLong_FromLongLong((long long) st.f_ffree));
13426
    SET_ITEM(v, 7, PyLong_FromLongLong((long long) st.f_ffree));
13427
    SET_ITEM(v, 8, PyLong_FromLong((long) flags));
13428
13429
    SET_ITEM(v, 9, PyLong_FromLong((long) NAME_MAX));
13430
    SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13431
13432
#undef SET_ITEM
13433
13434
    return v;
13435
}
13436
13437
#else
13438
13439
13440
13441
static PyObject*
13442
0
_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
13443
0
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13444
0
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13445
0
    if (v == NULL)
13446
0
        return NULL;
13447
13448
0
    int pos = 0;
13449
13450
0
#define SET_RESULT(CALL)                                     \
13451
0
    do {                                                     \
13452
0
        PyObject *item = (CALL);                             \
13453
0
        if (item == NULL) {                                  \
13454
0
            Py_DECREF(v);                                    \
13455
0
            return NULL;                                     \
13456
0
        }                                                    \
13457
0
        PyStructSequence_SET_ITEM(v, pos++, item);           \
13458
0
    } while(0)
13459
13460
0
#if !defined(HAVE_LARGEFILE_SUPPORT)
13461
0
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13462
0
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13463
0
    SET_RESULT(PyLong_FromLong((long) st.f_blocks));
13464
0
    SET_RESULT(PyLong_FromLong((long) st.f_bfree));
13465
0
    SET_RESULT(PyLong_FromLong((long) st.f_bavail));
13466
0
    SET_RESULT(PyLong_FromLong((long) st.f_files));
13467
0
    SET_RESULT(PyLong_FromLong((long) st.f_ffree));
13468
0
    SET_RESULT(PyLong_FromLong((long) st.f_favail));
13469
0
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13470
0
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13471
#else
13472
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13473
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13474
    SET_RESULT(PyLong_FromLongLong((long long) st.f_blocks));
13475
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bfree));
13476
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bavail));
13477
    SET_RESULT(PyLong_FromLongLong((long long) st.f_files));
13478
    SET_RESULT(PyLong_FromLongLong((long long) st.f_ffree));
13479
    SET_RESULT(PyLong_FromLongLong((long long) st.f_favail));
13480
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13481
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13482
#endif
13483
/* The _ALL_SOURCE feature test macro defines f_fsid as a structure
13484
 * (issue #32390). */
13485
#if defined(_AIX) && defined(_ALL_SOURCE)
13486
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13487
#else
13488
0
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid));
13489
0
#endif
13490
13491
0
#undef SET_RESULT
13492
13493
0
    return v;
13494
0
}
13495
13496
#endif
13497
13498
13499
/*[clinic input]
13500
os.fstatvfs
13501
    fd: int
13502
    /
13503
13504
Perform an fstatvfs system call on the given fd.
13505
13506
Equivalent to statvfs(fd).
13507
[clinic start generated code]*/
13508
13509
static PyObject *
13510
os_fstatvfs_impl(PyObject *module, int fd)
13511
/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
13512
0
{
13513
0
    int result;
13514
0
    int async_err = 0;
13515
#ifdef __APPLE__
13516
    struct statfs st;
13517
    /* On macOS os.fstatvfs is implemented using fstatfs(2) because
13518
     * the former uses 32-bit values for block counts.
13519
     */
13520
    do {
13521
        Py_BEGIN_ALLOW_THREADS
13522
        result = fstatfs(fd, &st);
13523
        Py_END_ALLOW_THREADS
13524
    } while (result != 0 && errno == EINTR &&
13525
             !(async_err = PyErr_CheckSignals()));
13526
    if (result != 0)
13527
        return (!async_err) ? posix_error() : NULL;
13528
13529
    return _pystatvfs_fromstructstatfs(module, st);
13530
#else
13531
0
    struct statvfs st;
13532
13533
0
    do {
13534
0
        Py_BEGIN_ALLOW_THREADS
13535
0
        result = fstatvfs(fd, &st);
13536
0
        Py_END_ALLOW_THREADS
13537
0
    } while (result != 0 && errno == EINTR &&
13538
0
             !(async_err = PyErr_CheckSignals()));
13539
0
    if (result != 0)
13540
0
        return (!async_err) ? posix_error() : NULL;
13541
13542
0
    return _pystatvfs_fromstructstatvfs(module, st);
13543
0
#endif
13544
0
}
13545
#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
13546
13547
13548
#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
13549
#include <sys/statvfs.h>
13550
/*[clinic input]
13551
os.statvfs
13552
13553
    path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
13554
13555
Perform a statvfs system call on the given path.
13556
13557
path may always be specified as a string.
13558
On some platforms, path may also be specified as an open file descriptor.
13559
  If this functionality is unavailable, using it raises an exception.
13560
[clinic start generated code]*/
13561
13562
static PyObject *
13563
os_statvfs_impl(PyObject *module, path_t *path)
13564
/*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
13565
0
{
13566
0
    int result;
13567
13568
#ifdef __APPLE__
13569
    /* On macOS os.statvfs is implemented using statfs(2)/fstatfs(2) because
13570
     * the former uses 32-bit values for block counts.
13571
     */
13572
    struct statfs st;
13573
13574
    Py_BEGIN_ALLOW_THREADS
13575
    if (path->fd != -1) {
13576
        result = fstatfs(path->fd, &st);
13577
    }
13578
    else
13579
        result = statfs(path->narrow, &st);
13580
    Py_END_ALLOW_THREADS
13581
13582
    if (result) {
13583
        return path_error(path);
13584
    }
13585
13586
    return _pystatvfs_fromstructstatfs(module, st);
13587
13588
#else
13589
0
    struct statvfs st;
13590
13591
0
    Py_BEGIN_ALLOW_THREADS
13592
0
#ifdef HAVE_FSTATVFS
13593
0
    if (path->fd != -1) {
13594
0
        result = fstatvfs(path->fd, &st);
13595
0
    }
13596
0
    else
13597
0
#endif
13598
0
        result = statvfs(path->narrow, &st);
13599
0
    Py_END_ALLOW_THREADS
13600
13601
0
    if (result) {
13602
0
        return path_error(path);
13603
0
    }
13604
13605
0
    return _pystatvfs_fromstructstatvfs(module, st);
13606
0
#endif
13607
0
}
13608
#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
13609
13610
13611
#ifdef MS_WINDOWS
13612
/*[clinic input]
13613
os._getdiskusage
13614
13615
    path: path_t
13616
13617
Return disk usage statistics about the given path as a (total, free) tuple.
13618
[clinic start generated code]*/
13619
13620
static PyObject *
13621
os__getdiskusage_impl(PyObject *module, path_t *path)
13622
/*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
13623
{
13624
    BOOL retval;
13625
    ULARGE_INTEGER _, total, free;
13626
    DWORD err = 0;
13627
13628
    Py_BEGIN_ALLOW_THREADS
13629
    retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
13630
    Py_END_ALLOW_THREADS
13631
    if (retval == 0) {
13632
        if (GetLastError() == ERROR_DIRECTORY) {
13633
            wchar_t *dir_path = NULL;
13634
13635
            dir_path = PyMem_New(wchar_t, path->length + 1);
13636
            if (dir_path == NULL) {
13637
                return PyErr_NoMemory();
13638
            }
13639
13640
            wcscpy_s(dir_path, path->length + 1, path->wide);
13641
13642
            if (_dirnameW(dir_path) != -1) {
13643
                Py_BEGIN_ALLOW_THREADS
13644
                retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
13645
                Py_END_ALLOW_THREADS
13646
            }
13647
            /* Record the last error in case it's modified by PyMem_Free. */
13648
            err = GetLastError();
13649
            PyMem_Free(dir_path);
13650
            if (retval) {
13651
                goto success;
13652
            }
13653
        }
13654
        return PyErr_SetFromWindowsErr(err);
13655
    }
13656
13657
success:
13658
    return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
13659
}
13660
#endif /* MS_WINDOWS */
13661
13662
13663
/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
13664
 * It maps strings representing configuration variable names to
13665
 * integer values, allowing those functions to be called with the
13666
 * magic names instead of polluting the module's namespace with tons of
13667
 * rarely-used constants.  There are three separate tables that use
13668
 * these definitions.
13669
 *
13670
 * This code is always included, even if none of the interfaces that
13671
 * need it are included.  The #if hackery needed to avoid it would be
13672
 * sufficiently pervasive that it's not worth the loss of readability.
13673
 */
13674
struct constdef {
13675
    const char *name;
13676
    int value;
13677
};
13678
13679
static int
13680
conv_confname(PyObject *module, PyObject *arg, int *valuep, const char *tablename)
13681
0
{
13682
0
    if (PyUnicode_Check(arg)) {
13683
0
        PyObject *table = PyObject_GetAttrString(module, tablename);
13684
0
        if (table == NULL) {
13685
0
            return 0;
13686
0
        }
13687
13688
0
        arg = PyObject_GetItem(table, arg);
13689
0
        Py_DECREF(table);
13690
0
        if (arg == NULL) {
13691
0
            PyErr_SetString(
13692
0
                PyExc_ValueError, "unrecognized configuration name");
13693
0
            return 0;
13694
0
        }
13695
0
    } else {
13696
0
        Py_INCREF(arg);  // Match the Py_DECREF below.
13697
0
    }
13698
13699
0
    int success = 0;
13700
0
    if (!PyIndex_Check(arg)) {
13701
0
        PyErr_SetString(PyExc_TypeError,
13702
0
            "configuration names must be strings or integers");
13703
0
    } else {
13704
0
        int value = PyLong_AsInt(arg);
13705
0
        if (!(value == -1 && PyErr_Occurred())) {
13706
0
            *valuep = value;
13707
0
            success = 1;
13708
0
        }
13709
0
    }
13710
0
    Py_DECREF(arg);
13711
0
    return success;
13712
0
}
13713
13714
13715
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
13716
static struct constdef  posix_constants_pathconf[] = {
13717
#ifdef _PC_ABI_AIO_XFER_MAX
13718
    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
13719
#endif
13720
#ifdef _PC_ABI_ASYNC_IO
13721
    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
13722
#endif
13723
#ifdef _PC_ASYNC_IO
13724
    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
13725
#endif
13726
#ifdef _PC_CHOWN_RESTRICTED
13727
    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
13728
#endif
13729
#ifdef _PC_FILESIZEBITS
13730
    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
13731
#endif
13732
#ifdef _PC_LAST
13733
    {"PC_LAST", _PC_LAST},
13734
#endif
13735
#ifdef _PC_LINK_MAX
13736
    {"PC_LINK_MAX",     _PC_LINK_MAX},
13737
#endif
13738
#ifdef _PC_MAX_CANON
13739
    {"PC_MAX_CANON",    _PC_MAX_CANON},
13740
#endif
13741
#ifdef _PC_MAX_INPUT
13742
    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
13743
#endif
13744
#ifdef _PC_NAME_MAX
13745
    {"PC_NAME_MAX",     _PC_NAME_MAX},
13746
#endif
13747
#ifdef _PC_NO_TRUNC
13748
    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
13749
#endif
13750
#ifdef _PC_PATH_MAX
13751
    {"PC_PATH_MAX",     _PC_PATH_MAX},
13752
#endif
13753
#ifdef _PC_PIPE_BUF
13754
    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
13755
#endif
13756
#ifdef _PC_PRIO_IO
13757
    {"PC_PRIO_IO",      _PC_PRIO_IO},
13758
#endif
13759
#ifdef _PC_SOCK_MAXBUF
13760
    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
13761
#endif
13762
#ifdef _PC_SYNC_IO
13763
    {"PC_SYNC_IO",      _PC_SYNC_IO},
13764
#endif
13765
#ifdef _PC_VDISABLE
13766
    {"PC_VDISABLE",     _PC_VDISABLE},
13767
#endif
13768
#ifdef _PC_ACL_ENABLED
13769
    {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
13770
#endif
13771
#ifdef _PC_MIN_HOLE_SIZE
13772
    {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
13773
#endif
13774
#ifdef _PC_ALLOC_SIZE_MIN
13775
    {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
13776
#endif
13777
#ifdef _PC_REC_INCR_XFER_SIZE
13778
    {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
13779
#endif
13780
#ifdef _PC_REC_MAX_XFER_SIZE
13781
    {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
13782
#endif
13783
#ifdef _PC_REC_MIN_XFER_SIZE
13784
    {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
13785
#endif
13786
#ifdef _PC_REC_XFER_ALIGN
13787
    {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
13788
#endif
13789
#ifdef _PC_SYMLINK_MAX
13790
    {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
13791
#endif
13792
#ifdef _PC_XATTR_ENABLED
13793
    {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
13794
#endif
13795
#ifdef _PC_XATTR_EXISTS
13796
    {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
13797
#endif
13798
#ifdef _PC_TIMESTAMP_RESOLUTION
13799
    {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
13800
#endif
13801
};
13802
#endif
13803
13804
13805
#ifdef HAVE_FPATHCONF
13806
/*[clinic input]
13807
os.fpathconf -> long
13808
13809
    fd: fildes
13810
    name: confname(table="pathconf_names")
13811
    /
13812
13813
Return the configuration limit name for the file descriptor fd.
13814
13815
If there is no limit, return -1.
13816
[clinic start generated code]*/
13817
13818
static long
13819
os_fpathconf_impl(PyObject *module, int fd, int name)
13820
/*[clinic end generated code: output=d5b7042425fc3e21 input=023d44589c9ed6aa]*/
13821
0
{
13822
0
    long limit;
13823
13824
0
    errno = 0;
13825
0
    limit = fpathconf(fd, name);
13826
0
    if (limit == -1 && errno != 0)
13827
0
        posix_error();
13828
13829
0
    return limit;
13830
0
}
13831
#endif /* HAVE_FPATHCONF */
13832
13833
13834
#ifdef HAVE_PATHCONF
13835
/*[clinic input]
13836
os.pathconf -> long
13837
    path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
13838
    name: confname(table="pathconf_names")
13839
13840
Return the configuration limit name for the file or directory path.
13841
13842
If there is no limit, return -1.
13843
On some platforms, path may also be specified as an open file descriptor.
13844
  If this functionality is unavailable, using it raises an exception.
13845
[clinic start generated code]*/
13846
13847
static long
13848
os_pathconf_impl(PyObject *module, path_t *path, int name)
13849
/*[clinic end generated code: output=5bedee35b293a089 input=6f6072f57b10c787]*/
13850
0
{
13851
0
    long limit;
13852
13853
0
    errno = 0;
13854
0
#ifdef HAVE_FPATHCONF
13855
0
    if (path->fd != -1)
13856
0
        limit = fpathconf(path->fd, name);
13857
0
    else
13858
0
#endif
13859
0
        limit = pathconf(path->narrow, name);
13860
0
    if (limit == -1 && errno != 0) {
13861
0
        if (errno == EINVAL)
13862
            /* could be a path or name problem */
13863
0
            posix_error();
13864
0
        else
13865
0
            path_error(path);
13866
0
    }
13867
13868
0
    return limit;
13869
0
}
13870
#endif /* HAVE_PATHCONF */
13871
13872
#ifdef HAVE_CONFSTR
13873
static struct constdef posix_constants_confstr[] = {
13874
#ifdef _CS_ARCHITECTURE
13875
    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
13876
#endif
13877
#ifdef _CS_GNU_LIBC_VERSION
13878
    {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
13879
#endif
13880
#ifdef _CS_GNU_LIBPTHREAD_VERSION
13881
    {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
13882
#endif
13883
#ifdef _CS_HOSTNAME
13884
    {"CS_HOSTNAME",     _CS_HOSTNAME},
13885
#endif
13886
#ifdef _CS_HW_PROVIDER
13887
    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
13888
#endif
13889
#ifdef _CS_HW_SERIAL
13890
    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
13891
#endif
13892
#ifdef _CS_INITTAB_NAME
13893
    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
13894
#endif
13895
#ifdef _CS_LFS64_CFLAGS
13896
    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
13897
#endif
13898
#ifdef _CS_LFS64_LDFLAGS
13899
    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
13900
#endif
13901
#ifdef _CS_LFS64_LIBS
13902
    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
13903
#endif
13904
#ifdef _CS_LFS64_LINTFLAGS
13905
    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
13906
#endif
13907
#ifdef _CS_LFS_CFLAGS
13908
    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
13909
#endif
13910
#ifdef _CS_LFS_LDFLAGS
13911
    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
13912
#endif
13913
#ifdef _CS_LFS_LIBS
13914
    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
13915
#endif
13916
#ifdef _CS_LFS_LINTFLAGS
13917
    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
13918
#endif
13919
#ifdef _CS_MACHINE
13920
    {"CS_MACHINE",      _CS_MACHINE},
13921
#endif
13922
#ifdef _CS_PATH
13923
    {"CS_PATH", _CS_PATH},
13924
#endif
13925
#ifdef _CS_RELEASE
13926
    {"CS_RELEASE",      _CS_RELEASE},
13927
#endif
13928
#ifdef _CS_SRPC_DOMAIN
13929
    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
13930
#endif
13931
#ifdef _CS_SYSNAME
13932
    {"CS_SYSNAME",      _CS_SYSNAME},
13933
#endif
13934
#ifdef _CS_VERSION
13935
    {"CS_VERSION",      _CS_VERSION},
13936
#endif
13937
#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
13938
    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
13939
#endif
13940
#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
13941
    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
13942
#endif
13943
#ifdef _CS_XBS5_ILP32_OFF32_LIBS
13944
    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
13945
#endif
13946
#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
13947
    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
13948
#endif
13949
#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
13950
    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
13951
#endif
13952
#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
13953
    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
13954
#endif
13955
#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
13956
    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
13957
#endif
13958
#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
13959
    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
13960
#endif
13961
#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
13962
    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
13963
#endif
13964
#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
13965
    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
13966
#endif
13967
#ifdef _CS_XBS5_LP64_OFF64_LIBS
13968
    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
13969
#endif
13970
#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
13971
    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
13972
#endif
13973
#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
13974
    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
13975
#endif
13976
#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
13977
    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
13978
#endif
13979
#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
13980
    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
13981
#endif
13982
#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
13983
    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
13984
#endif
13985
#ifdef _MIPS_CS_AVAIL_PROCESSORS
13986
    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
13987
#endif
13988
#ifdef _MIPS_CS_BASE
13989
    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
13990
#endif
13991
#ifdef _MIPS_CS_HOSTID
13992
    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
13993
#endif
13994
#ifdef _MIPS_CS_HW_NAME
13995
    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
13996
#endif
13997
#ifdef _MIPS_CS_NUM_PROCESSORS
13998
    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
13999
#endif
14000
#ifdef _MIPS_CS_OSREL_MAJ
14001
    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
14002
#endif
14003
#ifdef _MIPS_CS_OSREL_MIN
14004
    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
14005
#endif
14006
#ifdef _MIPS_CS_OSREL_PATCH
14007
    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
14008
#endif
14009
#ifdef _MIPS_CS_OS_NAME
14010
    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
14011
#endif
14012
#ifdef _MIPS_CS_OS_PROVIDER
14013
    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
14014
#endif
14015
#ifdef _MIPS_CS_PROCESSORS
14016
    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
14017
#endif
14018
#ifdef _MIPS_CS_SERIAL
14019
    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
14020
#endif
14021
#ifdef _MIPS_CS_VENDOR
14022
    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
14023
#endif
14024
};
14025
14026
14027
/*[clinic input]
14028
os.confstr
14029
14030
    name: confname(table="confstr_names")
14031
    /
14032
14033
Return a string-valued system configuration variable.
14034
[clinic start generated code]*/
14035
14036
static PyObject *
14037
os_confstr_impl(PyObject *module, int name)
14038
/*[clinic end generated code: output=bfb0b1b1e49b9383 input=4c6ffca2837ec959]*/
14039
0
{
14040
0
    PyObject *result = NULL;
14041
0
    char buffer[255];
14042
0
    size_t len;
14043
14044
0
    errno = 0;
14045
0
    len = confstr(name, buffer, sizeof(buffer));
14046
0
    if (len == 0) {
14047
0
        if (errno) {
14048
0
            posix_error();
14049
0
            return NULL;
14050
0
        }
14051
0
        else {
14052
0
            Py_RETURN_NONE;
14053
0
        }
14054
0
    }
14055
14056
0
    if (len >= sizeof(buffer)) {
14057
0
        size_t len2;
14058
0
        char *buf = PyMem_Malloc(len);
14059
0
        if (buf == NULL)
14060
0
            return PyErr_NoMemory();
14061
0
        len2 = confstr(name, buf, len);
14062
0
        assert(len == len2);
14063
0
        result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
14064
0
        PyMem_Free(buf);
14065
0
    }
14066
0
    else
14067
0
        result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
14068
0
    return result;
14069
0
}
14070
#endif /* HAVE_CONFSTR */
14071
14072
14073
#ifdef HAVE_SYSCONF
14074
static struct constdef posix_constants_sysconf[] = {
14075
#ifdef _SC_2_CHAR_TERM
14076
    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
14077
#endif
14078
#ifdef _SC_2_C_BIND
14079
    {"SC_2_C_BIND",     _SC_2_C_BIND},
14080
#endif
14081
#ifdef _SC_2_C_DEV
14082
    {"SC_2_C_DEV",      _SC_2_C_DEV},
14083
#endif
14084
#ifdef _SC_2_C_VERSION
14085
    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
14086
#endif
14087
#ifdef _SC_2_FORT_DEV
14088
    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
14089
#endif
14090
#ifdef _SC_2_FORT_RUN
14091
    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
14092
#endif
14093
#ifdef _SC_2_LOCALEDEF
14094
    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
14095
#endif
14096
#ifdef _SC_2_SW_DEV
14097
    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
14098
#endif
14099
#ifdef _SC_2_UPE
14100
    {"SC_2_UPE",        _SC_2_UPE},
14101
#endif
14102
#ifdef _SC_2_VERSION
14103
    {"SC_2_VERSION",    _SC_2_VERSION},
14104
#endif
14105
#ifdef _SC_ABI_ASYNCHRONOUS_IO
14106
    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
14107
#endif
14108
#ifdef _SC_ACL
14109
    {"SC_ACL",  _SC_ACL},
14110
#endif
14111
#ifdef _SC_AIO_LISTIO_MAX
14112
    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
14113
#endif
14114
#ifdef _SC_AIO_MAX
14115
    {"SC_AIO_MAX",      _SC_AIO_MAX},
14116
#endif
14117
#ifdef _SC_AIO_PRIO_DELTA_MAX
14118
    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
14119
#endif
14120
#ifdef _SC_ARG_MAX
14121
    {"SC_ARG_MAX",      _SC_ARG_MAX},
14122
#endif
14123
#ifdef _SC_ASYNCHRONOUS_IO
14124
    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
14125
#endif
14126
#ifdef _SC_ATEXIT_MAX
14127
    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
14128
#endif
14129
#ifdef _SC_AUDIT
14130
    {"SC_AUDIT",        _SC_AUDIT},
14131
#endif
14132
#ifdef _SC_AVPHYS_PAGES
14133
    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
14134
#endif
14135
#ifdef _SC_BC_BASE_MAX
14136
    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
14137
#endif
14138
#ifdef _SC_BC_DIM_MAX
14139
    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
14140
#endif
14141
#ifdef _SC_BC_SCALE_MAX
14142
    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
14143
#endif
14144
#ifdef _SC_BC_STRING_MAX
14145
    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
14146
#endif
14147
#ifdef _SC_CAP
14148
    {"SC_CAP",  _SC_CAP},
14149
#endif
14150
#ifdef _SC_CHARCLASS_NAME_MAX
14151
    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
14152
#endif
14153
#ifdef _SC_CHAR_BIT
14154
    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
14155
#endif
14156
#ifdef _SC_CHAR_MAX
14157
    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
14158
#endif
14159
#ifdef _SC_CHAR_MIN
14160
    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
14161
#endif
14162
#ifdef _SC_CHILD_MAX
14163
    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
14164
#endif
14165
#ifdef _SC_CLK_TCK
14166
    {"SC_CLK_TCK",      _SC_CLK_TCK},
14167
#endif
14168
#ifdef _SC_COHER_BLKSZ
14169
    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
14170
#endif
14171
#ifdef _SC_COLL_WEIGHTS_MAX
14172
    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
14173
#endif
14174
#ifdef _SC_DCACHE_ASSOC
14175
    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
14176
#endif
14177
#ifdef _SC_DCACHE_BLKSZ
14178
    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
14179
#endif
14180
#ifdef _SC_DCACHE_LINESZ
14181
    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
14182
#endif
14183
#ifdef _SC_DCACHE_SZ
14184
    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
14185
#endif
14186
#ifdef _SC_DCACHE_TBLKSZ
14187
    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
14188
#endif
14189
#ifdef _SC_DELAYTIMER_MAX
14190
    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
14191
#endif
14192
#ifdef _SC_EQUIV_CLASS_MAX
14193
    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
14194
#endif
14195
#ifdef _SC_EXPR_NEST_MAX
14196
    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
14197
#endif
14198
#ifdef _SC_FSYNC
14199
    {"SC_FSYNC",        _SC_FSYNC},
14200
#endif
14201
#ifdef _SC_GETGR_R_SIZE_MAX
14202
    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
14203
#endif
14204
#ifdef _SC_GETPW_R_SIZE_MAX
14205
    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
14206
#endif
14207
#ifdef _SC_ICACHE_ASSOC
14208
    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
14209
#endif
14210
#ifdef _SC_ICACHE_BLKSZ
14211
    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
14212
#endif
14213
#ifdef _SC_ICACHE_LINESZ
14214
    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
14215
#endif
14216
#ifdef _SC_ICACHE_SZ
14217
    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
14218
#endif
14219
#ifdef _SC_INF
14220
    {"SC_INF",  _SC_INF},
14221
#endif
14222
#ifdef _SC_INT_MAX
14223
    {"SC_INT_MAX",      _SC_INT_MAX},
14224
#endif
14225
#ifdef _SC_INT_MIN
14226
    {"SC_INT_MIN",      _SC_INT_MIN},
14227
#endif
14228
#ifdef _SC_IOV_MAX
14229
    {"SC_IOV_MAX",      _SC_IOV_MAX},
14230
#endif
14231
#ifdef _SC_IP_SECOPTS
14232
    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
14233
#endif
14234
#ifdef _SC_JOB_CONTROL
14235
    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
14236
#endif
14237
#ifdef _SC_KERN_POINTERS
14238
    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
14239
#endif
14240
#ifdef _SC_KERN_SIM
14241
    {"SC_KERN_SIM",     _SC_KERN_SIM},
14242
#endif
14243
#ifdef _SC_LINE_MAX
14244
    {"SC_LINE_MAX",     _SC_LINE_MAX},
14245
#endif
14246
#ifdef _SC_LOGIN_NAME_MAX
14247
    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
14248
#endif
14249
#ifdef _SC_LOGNAME_MAX
14250
    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
14251
#endif
14252
#ifdef _SC_LONG_BIT
14253
    {"SC_LONG_BIT",     _SC_LONG_BIT},
14254
#endif
14255
#ifdef _SC_MAC
14256
    {"SC_MAC",  _SC_MAC},
14257
#endif
14258
#ifdef _SC_MAPPED_FILES
14259
    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
14260
#endif
14261
#ifdef _SC_MAXPID
14262
    {"SC_MAXPID",       _SC_MAXPID},
14263
#endif
14264
#ifdef _SC_MB_LEN_MAX
14265
    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
14266
#endif
14267
#ifdef _SC_MEMLOCK
14268
    {"SC_MEMLOCK",      _SC_MEMLOCK},
14269
#endif
14270
#ifdef _SC_MEMLOCK_RANGE
14271
    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
14272
#endif
14273
#ifdef _SC_MEMORY_PROTECTION
14274
    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
14275
#endif
14276
#ifdef _SC_MESSAGE_PASSING
14277
    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
14278
#endif
14279
#ifdef _SC_MMAP_FIXED_ALIGNMENT
14280
    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
14281
#endif
14282
#ifdef _SC_MQ_OPEN_MAX
14283
    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
14284
#endif
14285
#ifdef _SC_MQ_PRIO_MAX
14286
    {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
14287
#endif
14288
#ifdef _SC_NACLS_MAX
14289
    {"SC_NACLS_MAX",    _SC_NACLS_MAX},
14290
#endif
14291
#ifdef _SC_NGROUPS_MAX
14292
    {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
14293
#endif
14294
#ifdef _SC_NL_ARGMAX
14295
    {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
14296
#endif
14297
#ifdef _SC_NL_LANGMAX
14298
    {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
14299
#endif
14300
#ifdef _SC_NL_MSGMAX
14301
    {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
14302
#endif
14303
#ifdef _SC_NL_NMAX
14304
    {"SC_NL_NMAX",      _SC_NL_NMAX},
14305
#endif
14306
#ifdef _SC_NL_SETMAX
14307
    {"SC_NL_SETMAX",    _SC_NL_SETMAX},
14308
#endif
14309
#ifdef _SC_NL_TEXTMAX
14310
    {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
14311
#endif
14312
#ifdef _SC_NPROCESSORS_CONF
14313
    {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
14314
#endif
14315
#ifdef _SC_NPROCESSORS_ONLN
14316
    {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
14317
#endif
14318
#ifdef _SC_NPROC_CONF
14319
    {"SC_NPROC_CONF",   _SC_NPROC_CONF},
14320
#endif
14321
#ifdef _SC_NPROC_ONLN
14322
    {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
14323
#endif
14324
#ifdef _SC_NZERO
14325
    {"SC_NZERO",        _SC_NZERO},
14326
#endif
14327
#ifdef _SC_OPEN_MAX
14328
    {"SC_OPEN_MAX",     _SC_OPEN_MAX},
14329
#endif
14330
#ifdef _SC_PAGESIZE
14331
    {"SC_PAGESIZE",     _SC_PAGESIZE},
14332
#endif
14333
#ifdef _SC_PAGE_SIZE
14334
    {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
14335
#endif
14336
#ifdef _SC_AIX_REALMEM
14337
    {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
14338
#endif
14339
#ifdef _SC_PASS_MAX
14340
    {"SC_PASS_MAX",     _SC_PASS_MAX},
14341
#endif
14342
#ifdef _SC_PHYS_PAGES
14343
    {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
14344
#endif
14345
#ifdef _SC_PII
14346
    {"SC_PII",  _SC_PII},
14347
#endif
14348
#ifdef _SC_PII_INTERNET
14349
    {"SC_PII_INTERNET", _SC_PII_INTERNET},
14350
#endif
14351
#ifdef _SC_PII_INTERNET_DGRAM
14352
    {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
14353
#endif
14354
#ifdef _SC_PII_INTERNET_STREAM
14355
    {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
14356
#endif
14357
#ifdef _SC_PII_OSI
14358
    {"SC_PII_OSI",      _SC_PII_OSI},
14359
#endif
14360
#ifdef _SC_PII_OSI_CLTS
14361
    {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
14362
#endif
14363
#ifdef _SC_PII_OSI_COTS
14364
    {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
14365
#endif
14366
#ifdef _SC_PII_OSI_M
14367
    {"SC_PII_OSI_M",    _SC_PII_OSI_M},
14368
#endif
14369
#ifdef _SC_PII_SOCKET
14370
    {"SC_PII_SOCKET",   _SC_PII_SOCKET},
14371
#endif
14372
#ifdef _SC_PII_XTI
14373
    {"SC_PII_XTI",      _SC_PII_XTI},
14374
#endif
14375
#ifdef _SC_POLL
14376
    {"SC_POLL", _SC_POLL},
14377
#endif
14378
#ifdef _SC_PRIORITIZED_IO
14379
    {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
14380
#endif
14381
#ifdef _SC_PRIORITY_SCHEDULING
14382
    {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
14383
#endif
14384
#ifdef _SC_REALTIME_SIGNALS
14385
    {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
14386
#endif
14387
#ifdef _SC_RE_DUP_MAX
14388
    {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
14389
#endif
14390
#ifdef _SC_RTSIG_MAX
14391
    {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
14392
#endif
14393
#ifdef _SC_SAVED_IDS
14394
    {"SC_SAVED_IDS",    _SC_SAVED_IDS},
14395
#endif
14396
#ifdef _SC_SCHAR_MAX
14397
    {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
14398
#endif
14399
#ifdef _SC_SCHAR_MIN
14400
    {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
14401
#endif
14402
#ifdef _SC_SELECT
14403
    {"SC_SELECT",       _SC_SELECT},
14404
#endif
14405
#ifdef _SC_SEMAPHORES
14406
    {"SC_SEMAPHORES",   _SC_SEMAPHORES},
14407
#endif
14408
#ifdef _SC_SEM_NSEMS_MAX
14409
    {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
14410
#endif
14411
#ifdef _SC_SEM_VALUE_MAX
14412
    {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
14413
#endif
14414
#ifdef _SC_SHARED_MEMORY_OBJECTS
14415
    {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
14416
#endif
14417
#ifdef _SC_SHRT_MAX
14418
    {"SC_SHRT_MAX",     _SC_SHRT_MAX},
14419
#endif
14420
#ifdef _SC_SHRT_MIN
14421
    {"SC_SHRT_MIN",     _SC_SHRT_MIN},
14422
#endif
14423
#ifdef _SC_SIGQUEUE_MAX
14424
    {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
14425
#endif
14426
#ifdef _SC_SIGRT_MAX
14427
    {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
14428
#endif
14429
#ifdef _SC_SIGRT_MIN
14430
    {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
14431
#endif
14432
#ifdef _SC_SOFTPOWER
14433
    {"SC_SOFTPOWER",    _SC_SOFTPOWER},
14434
#endif
14435
#ifdef _SC_SPLIT_CACHE
14436
    {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
14437
#endif
14438
#ifdef _SC_SSIZE_MAX
14439
    {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
14440
#endif
14441
#ifdef _SC_STACK_PROT
14442
    {"SC_STACK_PROT",   _SC_STACK_PROT},
14443
#endif
14444
#ifdef _SC_STREAM_MAX
14445
    {"SC_STREAM_MAX",   _SC_STREAM_MAX},
14446
#endif
14447
#ifdef _SC_SYNCHRONIZED_IO
14448
    {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
14449
#endif
14450
#ifdef _SC_THREADS
14451
    {"SC_THREADS",      _SC_THREADS},
14452
#endif
14453
#ifdef _SC_THREAD_ATTR_STACKADDR
14454
    {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
14455
#endif
14456
#ifdef _SC_THREAD_ATTR_STACKSIZE
14457
    {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
14458
#endif
14459
#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
14460
    {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
14461
#endif
14462
#ifdef _SC_THREAD_KEYS_MAX
14463
    {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
14464
#endif
14465
#ifdef _SC_THREAD_PRIORITY_SCHEDULING
14466
    {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
14467
#endif
14468
#ifdef _SC_THREAD_PRIO_INHERIT
14469
    {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
14470
#endif
14471
#ifdef _SC_THREAD_PRIO_PROTECT
14472
    {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
14473
#endif
14474
#ifdef _SC_THREAD_PROCESS_SHARED
14475
    {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
14476
#endif
14477
#ifdef _SC_THREAD_SAFE_FUNCTIONS
14478
    {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
14479
#endif
14480
#ifdef _SC_THREAD_STACK_MIN
14481
    {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
14482
#endif
14483
#ifdef _SC_THREAD_THREADS_MAX
14484
    {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
14485
#endif
14486
#ifdef _SC_TIMERS
14487
    {"SC_TIMERS",       _SC_TIMERS},
14488
#endif
14489
#ifdef _SC_TIMER_MAX
14490
    {"SC_TIMER_MAX",    _SC_TIMER_MAX},
14491
#endif
14492
#ifdef _SC_TTY_NAME_MAX
14493
    {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
14494
#endif
14495
#ifdef _SC_TZNAME_MAX
14496
    {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
14497
#endif
14498
#ifdef _SC_T_IOV_MAX
14499
    {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
14500
#endif
14501
#ifdef _SC_UCHAR_MAX
14502
    {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
14503
#endif
14504
#ifdef _SC_UINT_MAX
14505
    {"SC_UINT_MAX",     _SC_UINT_MAX},
14506
#endif
14507
#ifdef _SC_UIO_MAXIOV
14508
    {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
14509
#endif
14510
#ifdef _SC_ULONG_MAX
14511
    {"SC_ULONG_MAX",    _SC_ULONG_MAX},
14512
#endif
14513
#ifdef _SC_USHRT_MAX
14514
    {"SC_USHRT_MAX",    _SC_USHRT_MAX},
14515
#endif
14516
#ifdef _SC_VERSION
14517
    {"SC_VERSION",      _SC_VERSION},
14518
#endif
14519
#ifdef _SC_WORD_BIT
14520
    {"SC_WORD_BIT",     _SC_WORD_BIT},
14521
#endif
14522
#ifdef _SC_XBS5_ILP32_OFF32
14523
    {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
14524
#endif
14525
#ifdef _SC_XBS5_ILP32_OFFBIG
14526
    {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
14527
#endif
14528
#ifdef _SC_XBS5_LP64_OFF64
14529
    {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
14530
#endif
14531
#ifdef _SC_XBS5_LPBIG_OFFBIG
14532
    {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
14533
#endif
14534
#ifdef _SC_XOPEN_CRYPT
14535
    {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
14536
#endif
14537
#ifdef _SC_XOPEN_ENH_I18N
14538
    {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
14539
#endif
14540
#ifdef _SC_XOPEN_LEGACY
14541
    {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
14542
#endif
14543
#ifdef _SC_XOPEN_REALTIME
14544
    {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
14545
#endif
14546
#ifdef _SC_XOPEN_REALTIME_THREADS
14547
    {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
14548
#endif
14549
#ifdef _SC_XOPEN_SHM
14550
    {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
14551
#endif
14552
#ifdef _SC_XOPEN_UNIX
14553
    {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
14554
#endif
14555
#ifdef _SC_XOPEN_VERSION
14556
    {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
14557
#endif
14558
#ifdef _SC_XOPEN_XCU_VERSION
14559
    {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
14560
#endif
14561
#ifdef _SC_XOPEN_XPG2
14562
    {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
14563
#endif
14564
#ifdef _SC_XOPEN_XPG3
14565
    {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
14566
#endif
14567
#ifdef _SC_XOPEN_XPG4
14568
    {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
14569
#endif
14570
#ifdef _SC_MINSIGSTKSZ
14571
    {"SC_MINSIGSTKSZ",   _SC_MINSIGSTKSZ},
14572
#endif
14573
};
14574
14575
14576
/*[clinic input]
14577
os.sysconf -> long
14578
    name: confname(table="sysconf_names")
14579
    /
14580
14581
Return an integer-valued system configuration variable.
14582
[clinic start generated code]*/
14583
14584
static long
14585
os_sysconf_impl(PyObject *module, int name)
14586
/*[clinic end generated code: output=3662f945fc0cc756 input=930b8f23b5d15086]*/
14587
0
{
14588
0
    long value;
14589
14590
0
    errno = 0;
14591
0
    value = sysconf(name);
14592
0
    if (value == -1 && errno != 0)
14593
0
        posix_error();
14594
0
    return value;
14595
0
}
14596
#endif /* HAVE_SYSCONF */
14597
14598
14599
static int
14600
setup_confname_table(struct constdef *table, size_t tablesize,
14601
                     const char *tablename, PyObject *module)
14602
66
{
14603
66
    PyObject *d = PyDict_New();
14604
66
    if (d == NULL)
14605
0
        return -1;
14606
14607
4.04k
    for (size_t i=0; i < tablesize; ++i) {
14608
3.98k
        PyObject *o = PyLong_FromLong(table[i].value);
14609
3.98k
        if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
14610
0
            Py_XDECREF(o);
14611
0
            Py_DECREF(d);
14612
0
            return -1;
14613
0
        }
14614
3.98k
        Py_DECREF(o);
14615
3.98k
    }
14616
66
    return PyModule_Add(module, tablename, d);
14617
66
}
14618
14619
/* Return -1 on failure, 0 on success. */
14620
static int
14621
setup_confname_tables(PyObject *module)
14622
22
{
14623
22
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
14624
22
    if (setup_confname_table(posix_constants_pathconf,
14625
22
                             sizeof(posix_constants_pathconf)
14626
22
                               / sizeof(struct constdef),
14627
22
                             "pathconf_names", module))
14628
0
        return -1;
14629
22
#endif
14630
22
#ifdef HAVE_CONFSTR
14631
22
    if (setup_confname_table(posix_constants_confstr,
14632
22
                             sizeof(posix_constants_confstr)
14633
22
                               / sizeof(struct constdef),
14634
22
                             "confstr_names", module))
14635
0
        return -1;
14636
22
#endif
14637
22
#ifdef HAVE_SYSCONF
14638
22
    if (setup_confname_table(posix_constants_sysconf,
14639
22
                             sizeof(posix_constants_sysconf)
14640
22
                               / sizeof(struct constdef),
14641
22
                             "sysconf_names", module))
14642
0
        return -1;
14643
22
#endif
14644
22
    return 0;
14645
22
}
14646
14647
14648
/*[clinic input]
14649
os.abort
14650
14651
Abort the interpreter immediately.
14652
14653
This function 'dumps core' or otherwise fails in the hardest way possible
14654
on the hosting operating system.  This function never returns.
14655
[clinic start generated code]*/
14656
14657
static PyObject *
14658
os_abort_impl(PyObject *module)
14659
/*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
14660
0
{
14661
0
    abort();
14662
    /*NOTREACHED*/
14663
#ifndef __clang__
14664
    /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
14665
       GCC emits a warning without "return NULL;" (compiler bug?), but Clang
14666
       is smarter and emits a warning on the return. */
14667
    Py_FatalError("abort() called from Python code didn't abort!");
14668
    return NULL;
14669
#endif
14670
0
}
14671
14672
#ifdef MS_WINDOWS
14673
/* Grab ShellExecute dynamically from shell32 */
14674
static int has_ShellExecute = -1;
14675
static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
14676
                                              LPCWSTR, INT);
14677
static int
14678
check_ShellExecute(void)
14679
{
14680
    HINSTANCE hShell32;
14681
14682
    /* only recheck */
14683
    if (-1 == has_ShellExecute) {
14684
        Py_BEGIN_ALLOW_THREADS
14685
        /* Security note: this call is not vulnerable to "DLL hijacking".
14686
           SHELL32 is part of "KnownDLLs" and so Windows always load
14687
           the system SHELL32.DLL, even if there is another SHELL32.DLL
14688
           in the DLL search path. */
14689
        hShell32 = LoadLibraryW(L"SHELL32");
14690
        if (hShell32) {
14691
            *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
14692
                                            "ShellExecuteW");
14693
            has_ShellExecute = Py_ShellExecuteW != NULL;
14694
        } else {
14695
            has_ShellExecute = 0;
14696
        }
14697
        Py_END_ALLOW_THREADS
14698
    }
14699
    return has_ShellExecute;
14700
}
14701
14702
14703
/*[clinic input]
14704
os.startfile
14705
    filepath: path_t
14706
    operation: Py_UNICODE = NULL
14707
    arguments: Py_UNICODE = NULL
14708
    cwd: path_t(nullable=True) = None
14709
    show_cmd: int = 1
14710
14711
Start a file with its associated application.
14712
14713
When "operation" is not specified or "open", this acts like
14714
double-clicking the file in Explorer, or giving the file name as an
14715
argument to the DOS "start" command: the file is opened with whatever
14716
application (if any) its extension is associated.
14717
When another "operation" is given, it specifies what should be done with
14718
the file.  A typical operation is "print".
14719
14720
"arguments" is passed to the application, but should be omitted if the
14721
file is a document.
14722
14723
"cwd" is the working directory for the operation. If "filepath" is
14724
relative, it will be resolved against this directory. This argument
14725
should usually be an absolute path.
14726
14727
"show_cmd" can be used to override the recommended visibility option.
14728
See the Windows ShellExecute documentation for values.
14729
14730
startfile returns as soon as the associated application is launched.
14731
There is no option to wait for the application to close, and no way
14732
to retrieve the application's exit status.
14733
14734
The filepath is relative to the current directory.  If you want to use
14735
an absolute path, make sure the first character is not a slash ("/");
14736
the underlying Win32 ShellExecute function doesn't work if it is.
14737
[clinic start generated code]*/
14738
14739
static PyObject *
14740
os_startfile_impl(PyObject *module, path_t *filepath,
14741
                  const wchar_t *operation, const wchar_t *arguments,
14742
                  path_t *cwd, int show_cmd)
14743
/*[clinic end generated code: output=1c6f2f3340e31ffa input=8248997b80669622]*/
14744
{
14745
    HINSTANCE rc;
14746
14747
    if(!check_ShellExecute()) {
14748
        /* If the OS doesn't have ShellExecute, return a
14749
           NotImplementedError. */
14750
        return PyErr_Format(PyExc_NotImplementedError,
14751
            "startfile not available on this platform");
14752
    }
14753
14754
    if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
14755
        return NULL;
14756
    }
14757
    if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
14758
                    arguments, cwd->object ? cwd->object : Py_None,
14759
                    show_cmd) < 0) {
14760
        return NULL;
14761
    }
14762
14763
    Py_BEGIN_ALLOW_THREADS
14764
    rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
14765
                          arguments, cwd->wide, show_cmd);
14766
    Py_END_ALLOW_THREADS
14767
14768
    if (rc <= (HINSTANCE)32) {
14769
        win32_error_object("startfile", filepath->object);
14770
        return NULL;
14771
    }
14772
    Py_RETURN_NONE;
14773
}
14774
#endif /* MS_WINDOWS */
14775
14776
14777
#ifdef HAVE_GETLOADAVG
14778
/*[clinic input]
14779
os.getloadavg
14780
14781
Return average recent system load information.
14782
14783
Return the number of processes in the system run queue averaged over
14784
the last 1, 5, and 15 minutes as a tuple of three floats.
14785
Raises OSError if the load average was unobtainable.
14786
[clinic start generated code]*/
14787
14788
static PyObject *
14789
os_getloadavg_impl(PyObject *module)
14790
/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
14791
0
{
14792
0
    double loadavg[3];
14793
0
    if (getloadavg(loadavg, 3)!=3) {
14794
0
        PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
14795
0
        return NULL;
14796
0
    } else
14797
0
        return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
14798
0
}
14799
#endif /* HAVE_GETLOADAVG */
14800
14801
14802
/*[clinic input]
14803
os.device_encoding
14804
    fd: int
14805
14806
Return a string describing the encoding of a terminal's file descriptor.
14807
14808
The file descriptor must be attached to a terminal.
14809
If the device is not a terminal, return None.
14810
[clinic start generated code]*/
14811
14812
static PyObject *
14813
os_device_encoding_impl(PyObject *module, int fd)
14814
/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
14815
0
{
14816
0
    return _Py_device_encoding(fd);
14817
0
}
14818
14819
14820
#ifdef HAVE_SETRESUID
14821
/*[clinic input]
14822
os.setresuid
14823
14824
    ruid: uid_t
14825
    euid: uid_t
14826
    suid: uid_t
14827
    /
14828
14829
Set the current process's real, effective, and saved user ids.
14830
[clinic start generated code]*/
14831
14832
static PyObject *
14833
os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
14834
/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
14835
0
{
14836
0
    if (setresuid(ruid, euid, suid) < 0)
14837
0
        return posix_error();
14838
0
    Py_RETURN_NONE;
14839
0
}
14840
#endif /* HAVE_SETRESUID */
14841
14842
14843
#ifdef HAVE_SETRESGID
14844
/*[clinic input]
14845
os.setresgid
14846
14847
    rgid: gid_t
14848
    egid: gid_t
14849
    sgid: gid_t
14850
    /
14851
14852
Set the current process's real, effective, and saved group ids.
14853
[clinic start generated code]*/
14854
14855
static PyObject *
14856
os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
14857
/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
14858
0
{
14859
0
    if (setresgid(rgid, egid, sgid) < 0)
14860
0
        return posix_error();
14861
0
    Py_RETURN_NONE;
14862
0
}
14863
#endif /* HAVE_SETRESGID */
14864
14865
14866
#ifdef HAVE_GETRESUID
14867
/*[clinic input]
14868
os.getresuid
14869
14870
Return a tuple of the current process's real, effective, and saved user ids.
14871
[clinic start generated code]*/
14872
14873
static PyObject *
14874
os_getresuid_impl(PyObject *module)
14875
/*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
14876
0
{
14877
0
    uid_t ruid, euid, suid;
14878
0
    if (getresuid(&ruid, &euid, &suid) < 0)
14879
0
        return posix_error();
14880
0
    return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
14881
0
                                  _PyLong_FromUid(euid),
14882
0
                                  _PyLong_FromUid(suid));
14883
0
}
14884
#endif /* HAVE_GETRESUID */
14885
14886
14887
#ifdef HAVE_GETRESGID
14888
/*[clinic input]
14889
@permit_long_summary
14890
os.getresgid
14891
14892
Return a tuple of the current process's real, effective, and saved group ids.
14893
[clinic start generated code]*/
14894
14895
static PyObject *
14896
os_getresgid_impl(PyObject *module)
14897
/*[clinic end generated code: output=2719c4bfcf27fb9f input=ad9adadc86fbdb17]*/
14898
0
{
14899
0
    gid_t rgid, egid, sgid;
14900
0
    if (getresgid(&rgid, &egid, &sgid) < 0)
14901
0
        return posix_error();
14902
0
    return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
14903
0
                                  _PyLong_FromGid(egid),
14904
0
                                  _PyLong_FromGid(sgid));
14905
0
}
14906
#endif /* HAVE_GETRESGID */
14907
14908
14909
#ifdef USE_XATTRS
14910
/*[clinic input]
14911
os.getxattr
14912
14913
    path: path_t(allow_fd=True)
14914
    attribute: path_t
14915
    *
14916
    follow_symlinks: bool = True
14917
14918
Return the value of extended attribute attribute on path.
14919
14920
path may be either a string, a path-like object, or an open file descriptor.
14921
If follow_symlinks is False, and the last element of the path is a symbolic
14922
  link, getxattr will examine the symbolic link itself instead of the file
14923
  the link points to.
14924
14925
[clinic start generated code]*/
14926
14927
static PyObject *
14928
os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
14929
                 int follow_symlinks)
14930
/*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
14931
0
{
14932
0
    Py_ssize_t i;
14933
0
    PyObject *buffer = NULL;
14934
14935
0
    if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
14936
0
        return NULL;
14937
14938
0
    if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
14939
0
        return NULL;
14940
0
    }
14941
14942
0
    for (i = 0; ; i++) {
14943
0
        void *ptr;
14944
0
        ssize_t result;
14945
0
        static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
14946
0
        Py_ssize_t buffer_size = buffer_sizes[i];
14947
0
        if (!buffer_size) {
14948
0
            path_error(path);
14949
0
            return NULL;
14950
0
        }
14951
0
        buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
14952
0
        if (!buffer)
14953
0
            return NULL;
14954
0
        ptr = PyBytes_AS_STRING(buffer);
14955
14956
0
        Py_BEGIN_ALLOW_THREADS;
14957
0
        if (path->fd >= 0)
14958
0
            result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
14959
0
        else if (follow_symlinks)
14960
0
            result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
14961
0
        else
14962
0
            result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
14963
0
        Py_END_ALLOW_THREADS;
14964
14965
0
        if (result < 0) {
14966
0
            if (errno == ERANGE) {
14967
0
                Py_DECREF(buffer);
14968
0
                continue;
14969
0
            }
14970
0
            path_error(path);
14971
0
            Py_DECREF(buffer);
14972
0
            return NULL;
14973
0
        }
14974
14975
0
        if (result != buffer_size) {
14976
            /* Can only shrink. */
14977
0
            _PyBytes_Resize(&buffer, result);
14978
0
        }
14979
0
        break;
14980
0
    }
14981
14982
0
    return buffer;
14983
0
}
14984
14985
14986
/*[clinic input]
14987
@permit_long_docstring_body
14988
os.setxattr
14989
14990
    path: path_t(allow_fd=True)
14991
    attribute: path_t
14992
    value: Py_buffer
14993
    flags: int = 0
14994
    *
14995
    follow_symlinks: bool = True
14996
14997
Set extended attribute attribute on path to value.
14998
14999
path may be either a string, a path-like object,  or an open file descriptor.
15000
If follow_symlinks is False, and the last element of the path is a symbolic
15001
  link, setxattr will modify the symbolic link itself instead of the file
15002
  the link points to.
15003
15004
[clinic start generated code]*/
15005
15006
static PyObject *
15007
os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15008
                 Py_buffer *value, int flags, int follow_symlinks)
15009
/*[clinic end generated code: output=98b83f63fdde26bb input=4098e6f68699f3d7]*/
15010
0
{
15011
0
    ssize_t result;
15012
15013
0
    if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
15014
0
        return NULL;
15015
15016
0
    if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
15017
0
                    value->buf, value->len, flags) < 0) {
15018
0
        return NULL;
15019
0
    }
15020
15021
0
    Py_BEGIN_ALLOW_THREADS;
15022
0
    if (path->fd > -1)
15023
0
        result = fsetxattr(path->fd, attribute->narrow,
15024
0
                           value->buf, value->len, flags);
15025
0
    else if (follow_symlinks)
15026
0
        result = setxattr(path->narrow, attribute->narrow,
15027
0
                           value->buf, value->len, flags);
15028
0
    else
15029
0
        result = lsetxattr(path->narrow, attribute->narrow,
15030
0
                           value->buf, value->len, flags);
15031
0
    Py_END_ALLOW_THREADS;
15032
15033
0
    if (result) {
15034
0
        path_error(path);
15035
0
        return NULL;
15036
0
    }
15037
15038
0
    Py_RETURN_NONE;
15039
0
}
15040
15041
15042
/*[clinic input]
15043
os.removexattr
15044
15045
    path: path_t(allow_fd=True)
15046
    attribute: path_t
15047
    *
15048
    follow_symlinks: bool = True
15049
15050
Remove extended attribute attribute on path.
15051
15052
path may be either a string, a path-like object, or an open file descriptor.
15053
If follow_symlinks is False, and the last element of the path is a symbolic
15054
  link, removexattr will modify the symbolic link itself instead of the file
15055
  the link points to.
15056
15057
[clinic start generated code]*/
15058
15059
static PyObject *
15060
os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
15061
                    int follow_symlinks)
15062
/*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
15063
0
{
15064
0
    ssize_t result;
15065
15066
0
    if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
15067
0
        return NULL;
15068
15069
0
    if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
15070
0
        return NULL;
15071
0
    }
15072
15073
0
    Py_BEGIN_ALLOW_THREADS;
15074
0
    if (path->fd > -1)
15075
0
        result = fremovexattr(path->fd, attribute->narrow);
15076
0
    else if (follow_symlinks)
15077
0
        result = removexattr(path->narrow, attribute->narrow);
15078
0
    else
15079
0
        result = lremovexattr(path->narrow, attribute->narrow);
15080
0
    Py_END_ALLOW_THREADS;
15081
15082
0
    if (result) {
15083
0
        return path_error(path);
15084
0
    }
15085
15086
0
    Py_RETURN_NONE;
15087
0
}
15088
15089
15090
/*[clinic input]
15091
@permit_long_docstring_body
15092
os.listxattr
15093
15094
    path: path_t(allow_fd=True, nullable=True) = None
15095
    *
15096
    follow_symlinks: bool = True
15097
15098
Return a list of extended attributes on path.
15099
15100
path may be either None, a string, a path-like object, or an open file descriptor.
15101
if path is None, listxattr will examine the current directory.
15102
If follow_symlinks is False, and the last element of the path is a symbolic
15103
  link, listxattr will examine the symbolic link itself instead of the file
15104
  the link points to.
15105
[clinic start generated code]*/
15106
15107
static PyObject *
15108
os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
15109
/*[clinic end generated code: output=bebdb4e2ad0ce435 input=48aa9ac8be47dea1]*/
15110
0
{
15111
0
    Py_ssize_t i;
15112
0
    PyObject *result = NULL;
15113
0
    const char *name;
15114
0
    char *buffer = NULL;
15115
15116
0
    if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
15117
0
        goto exit;
15118
15119
0
    if (PySys_Audit("os.listxattr", "(O)",
15120
0
                    path->object ? path->object : Py_None) < 0) {
15121
0
        return NULL;
15122
0
    }
15123
15124
0
    name = path->narrow ? path->narrow : ".";
15125
15126
0
    for (i = 0; ; i++) {
15127
0
        const char *start, *trace, *end;
15128
0
        ssize_t length;
15129
0
        static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
15130
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15131
0
        if (!buffer_size) {
15132
            /* ERANGE */
15133
0
            path_error(path);
15134
0
            break;
15135
0
        }
15136
0
        buffer = PyMem_Malloc(buffer_size);
15137
0
        if (!buffer) {
15138
0
            PyErr_NoMemory();
15139
0
            break;
15140
0
        }
15141
15142
0
        Py_BEGIN_ALLOW_THREADS;
15143
0
        if (path->fd > -1)
15144
0
            length = flistxattr(path->fd, buffer, buffer_size);
15145
0
        else if (follow_symlinks)
15146
0
            length = listxattr(name, buffer, buffer_size);
15147
0
        else
15148
0
            length = llistxattr(name, buffer, buffer_size);
15149
0
        Py_END_ALLOW_THREADS;
15150
15151
0
        if (length < 0) {
15152
0
            if (errno == ERANGE) {
15153
0
                PyMem_Free(buffer);
15154
0
                buffer = NULL;
15155
0
                continue;
15156
0
            }
15157
0
            path_error(path);
15158
0
            break;
15159
0
        }
15160
15161
0
        result = PyList_New(0);
15162
0
        if (!result) {
15163
0
            goto exit;
15164
0
        }
15165
15166
0
        end = buffer + length;
15167
0
        for (trace = start = buffer; trace != end; trace++) {
15168
0
            if (!*trace) {
15169
0
                int error;
15170
0
                PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
15171
0
                                                                 trace - start);
15172
0
                if (!attribute) {
15173
0
                    Py_SETREF(result, NULL);
15174
0
                    goto exit;
15175
0
                }
15176
0
                error = PyList_Append(result, attribute);
15177
0
                Py_DECREF(attribute);
15178
0
                if (error) {
15179
0
                    Py_SETREF(result, NULL);
15180
0
                    goto exit;
15181
0
                }
15182
0
                start = trace + 1;
15183
0
            }
15184
0
        }
15185
0
    break;
15186
0
    }
15187
0
exit:
15188
0
    if (buffer)
15189
0
        PyMem_Free(buffer);
15190
0
    return result;
15191
0
}
15192
#endif /* USE_XATTRS */
15193
15194
15195
/*[clinic input]
15196
@permit_long_summary
15197
os.urandom
15198
15199
    size: Py_ssize_t
15200
    /
15201
15202
Return a bytes object containing random bytes suitable for cryptographic use.
15203
[clinic start generated code]*/
15204
15205
static PyObject *
15206
os_urandom_impl(PyObject *module, Py_ssize_t size)
15207
/*[clinic end generated code: output=42c5cca9d18068e9 input=ade19e6b362e7388]*/
15208
0
{
15209
0
    PyObject *bytes;
15210
0
    int result;
15211
15212
0
    if (size < 0)
15213
0
        return PyErr_Format(PyExc_ValueError,
15214
0
                            "negative argument not allowed");
15215
0
    bytes = PyBytes_FromStringAndSize(NULL, size);
15216
0
    if (bytes == NULL)
15217
0
        return NULL;
15218
15219
0
    result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
15220
0
    if (result == -1) {
15221
0
        Py_DECREF(bytes);
15222
0
        return NULL;
15223
0
    }
15224
0
    return bytes;
15225
0
}
15226
15227
#ifdef HAVE_MEMFD_CREATE
15228
/*[clinic input]
15229
os.memfd_create
15230
15231
    name: FSConverter
15232
    flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
15233
15234
[clinic start generated code]*/
15235
15236
static PyObject *
15237
os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
15238
/*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
15239
0
{
15240
0
    int fd;
15241
0
    const char *bytes = PyBytes_AS_STRING(name);
15242
0
    Py_BEGIN_ALLOW_THREADS
15243
0
    fd = memfd_create(bytes, flags);
15244
0
    Py_END_ALLOW_THREADS
15245
0
    if (fd == -1) {
15246
0
        return PyErr_SetFromErrno(PyExc_OSError);
15247
0
    }
15248
0
    return PyLong_FromLong(fd);
15249
0
}
15250
#endif
15251
15252
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
15253
/*[clinic input]
15254
os.eventfd
15255
15256
    initval: unsigned_int
15257
    flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
15258
15259
Creates and returns an event notification file descriptor.
15260
[clinic start generated code]*/
15261
15262
static PyObject *
15263
os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
15264
/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
15265
15266
0
{
15267
    /* initval is limited to uint32_t, internal counter is uint64_t */
15268
0
    int fd;
15269
0
    Py_BEGIN_ALLOW_THREADS
15270
0
    fd = eventfd(initval, 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
15278
/*[clinic input]
15279
os.eventfd_read
15280
15281
    fd: fildes
15282
15283
Read eventfd value
15284
[clinic start generated code]*/
15285
15286
static PyObject *
15287
os_eventfd_read_impl(PyObject *module, int fd)
15288
/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
15289
0
{
15290
0
    eventfd_t value;
15291
0
    int result;
15292
0
    Py_BEGIN_ALLOW_THREADS
15293
0
    result = eventfd_read(fd, &value);
15294
0
    Py_END_ALLOW_THREADS
15295
0
    if (result == -1) {
15296
0
        return PyErr_SetFromErrno(PyExc_OSError);
15297
0
    }
15298
0
    return PyLong_FromUnsignedLongLong(value);
15299
0
}
15300
15301
/*[clinic input]
15302
os.eventfd_write
15303
15304
    fd: fildes
15305
    value: unsigned_long_long
15306
15307
Write eventfd value.
15308
[clinic start generated code]*/
15309
15310
static PyObject *
15311
os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
15312
/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
15313
0
{
15314
0
    int result;
15315
0
    Py_BEGIN_ALLOW_THREADS
15316
0
    result = eventfd_write(fd, value);
15317
0
    Py_END_ALLOW_THREADS
15318
0
    if (result == -1) {
15319
0
        return PyErr_SetFromErrno(PyExc_OSError);
15320
0
    }
15321
0
    Py_RETURN_NONE;
15322
0
}
15323
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
15324
15325
/* Terminal size querying */
15326
15327
PyDoc_STRVAR(TerminalSize_docstring,
15328
    "A tuple of (columns, lines) for holding terminal window size");
15329
15330
static PyStructSequence_Field TerminalSize_fields[] = {
15331
    {"columns", "width of the terminal window in characters"},
15332
    {"lines", "height of the terminal window in characters"},
15333
    {NULL, NULL}
15334
};
15335
15336
static PyStructSequence_Desc TerminalSize_desc = {
15337
    "os.terminal_size",
15338
    TerminalSize_docstring,
15339
    TerminalSize_fields,
15340
    2,
15341
};
15342
15343
#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
15344
/*[clinic input]
15345
os.get_terminal_size
15346
15347
    fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
15348
    /
15349
15350
Return the size of the terminal window as (columns, lines).
15351
15352
The optional argument fd (default standard output) specifies
15353
which file descriptor should be queried.
15354
15355
If the file descriptor is not connected to a terminal, an OSError
15356
is thrown.
15357
15358
This function will only be defined if an implementation is
15359
available for this system.
15360
15361
shutil.get_terminal_size is the high-level function which should
15362
normally be used, os.get_terminal_size is the low-level implementation.
15363
[clinic start generated code]*/
15364
15365
static PyObject *
15366
os_get_terminal_size_impl(PyObject *module, int fd)
15367
/*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
15368
0
{
15369
0
    int columns, lines;
15370
0
    PyObject *termsize;
15371
15372
    /* Under some conditions stdout may not be connected and
15373
     * fileno(stdout) may point to an invalid file descriptor. For example
15374
     * GUI apps don't have valid standard streams by default.
15375
     *
15376
     * If this happens, and the optional fd argument is not present,
15377
     * the ioctl below will fail returning EBADF. This is what we want.
15378
     */
15379
15380
0
#ifdef TERMSIZE_USE_IOCTL
15381
0
    {
15382
0
        struct winsize w;
15383
0
        if (ioctl(fd, TIOCGWINSZ, &w))
15384
0
            return PyErr_SetFromErrno(PyExc_OSError);
15385
0
        columns = w.ws_col;
15386
0
        lines = w.ws_row;
15387
0
    }
15388
0
#endif /* TERMSIZE_USE_IOCTL */
15389
15390
#ifdef TERMSIZE_USE_CONIO
15391
    {
15392
        HANDLE handle;
15393
        CONSOLE_SCREEN_BUFFER_INFO csbi;
15394
        handle = _Py_get_osfhandle(fd);
15395
        if (handle == INVALID_HANDLE_VALUE)
15396
            return NULL;
15397
15398
        if (!GetConsoleScreenBufferInfo(handle, &csbi))
15399
            return PyErr_SetFromWindowsErr(0);
15400
15401
        columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
15402
        lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
15403
    }
15404
#endif /* TERMSIZE_USE_CONIO */
15405
15406
0
    PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
15407
0
    termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
15408
0
    if (termsize == NULL)
15409
0
        return NULL;
15410
15411
0
    int pos = 0;
15412
15413
0
#define SET_TERMSIZE(CALL)                                   \
15414
0
    do {                                                     \
15415
0
        PyObject *item = (CALL);                             \
15416
0
        if (item == NULL) {                                  \
15417
0
            Py_DECREF(termsize);                             \
15418
0
            return NULL;                                     \
15419
0
        }                                                    \
15420
0
        PyStructSequence_SET_ITEM(termsize, pos++, item);    \
15421
0
    } while(0)
15422
15423
0
    SET_TERMSIZE(PyLong_FromLong(columns));
15424
0
    SET_TERMSIZE(PyLong_FromLong(lines));
15425
0
#undef SET_TERMSIZE
15426
15427
0
    return termsize;
15428
0
}
15429
#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
15430
15431
/*[clinic input]
15432
os.cpu_count
15433
15434
Return the number of logical CPUs in the system.
15435
15436
Return None if indeterminable.
15437
[clinic start generated code]*/
15438
15439
static PyObject *
15440
os_cpu_count_impl(PyObject *module)
15441
/*[clinic end generated code: output=5fc29463c3936a9c input=ba2f6f8980a0e2eb]*/
15442
0
{
15443
0
    const PyConfig *config = _Py_GetConfig();
15444
0
    if (config->cpu_count > 0) {
15445
0
        return PyLong_FromLong(config->cpu_count);
15446
0
    }
15447
15448
0
    int ncpu = 0;
15449
#ifdef MS_WINDOWS
15450
# ifdef MS_WINDOWS_DESKTOP
15451
    ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
15452
# else
15453
    ncpu = 0;
15454
# endif
15455
15456
#elif defined(__hpux)
15457
    ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
15458
15459
#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
15460
    ncpu = sysconf(_SC_NPROCESSORS_ONLN);
15461
15462
#elif defined(__VXWORKS__)
15463
    ncpu = _Py_popcount32(vxCpuEnabledGet());
15464
15465
#elif defined(__DragonFly__) || \
15466
      defined(__OpenBSD__)   || \
15467
      defined(__FreeBSD__)   || \
15468
      defined(__NetBSD__)    || \
15469
      defined(__APPLE__)
15470
    ncpu = 0;
15471
    size_t len = sizeof(ncpu);
15472
    int mib[2] = {CTL_HW, HW_NCPU};
15473
    if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) {
15474
        ncpu = 0;
15475
    }
15476
#endif
15477
15478
0
    if (ncpu < 1) {
15479
0
        Py_RETURN_NONE;
15480
0
    }
15481
0
    return PyLong_FromLong(ncpu);
15482
0
}
15483
15484
15485
/*[clinic input]
15486
os.get_inheritable -> bool
15487
15488
    fd: int
15489
    /
15490
15491
Get the close-on-exe flag of the specified file descriptor.
15492
[clinic start generated code]*/
15493
15494
static int
15495
os_get_inheritable_impl(PyObject *module, int fd)
15496
/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
15497
0
{
15498
0
    int return_value;
15499
0
    _Py_BEGIN_SUPPRESS_IPH
15500
0
    return_value = _Py_get_inheritable(fd);
15501
0
    _Py_END_SUPPRESS_IPH
15502
0
    return return_value;
15503
0
}
15504
15505
15506
/*[clinic input]
15507
os.set_inheritable
15508
    fd: int
15509
    inheritable: int
15510
    /
15511
15512
Set the inheritable flag of the specified file descriptor.
15513
[clinic start generated code]*/
15514
15515
static PyObject *
15516
os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
15517
/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
15518
0
{
15519
0
    int result;
15520
15521
0
    _Py_BEGIN_SUPPRESS_IPH
15522
0
    result = _Py_set_inheritable(fd, inheritable, NULL);
15523
0
    _Py_END_SUPPRESS_IPH
15524
0
    if (result < 0)
15525
0
        return NULL;
15526
0
    Py_RETURN_NONE;
15527
0
}
15528
15529
15530
#ifdef MS_WINDOWS
15531
#ifndef HANDLE_FLAG_INHERIT
15532
#define HANDLE_FLAG_INHERIT 0x00000001
15533
#endif
15534
15535
/*[clinic input]
15536
os.get_handle_inheritable -> bool
15537
    handle: intptr_t
15538
    /
15539
15540
Get the close-on-exe flag of the specified file descriptor.
15541
[clinic start generated code]*/
15542
15543
static int
15544
os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
15545
/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
15546
{
15547
    DWORD flags;
15548
15549
    if (!GetHandleInformation((HANDLE)handle, &flags)) {
15550
        PyErr_SetFromWindowsErr(0);
15551
        return -1;
15552
    }
15553
15554
    return flags & HANDLE_FLAG_INHERIT;
15555
}
15556
15557
15558
/*[clinic input]
15559
os.set_handle_inheritable
15560
    handle: intptr_t
15561
    inheritable: bool
15562
    /
15563
15564
Set the inheritable flag of the specified handle.
15565
[clinic start generated code]*/
15566
15567
static PyObject *
15568
os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
15569
                               int inheritable)
15570
/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
15571
{
15572
    DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
15573
    if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
15574
        PyErr_SetFromWindowsErr(0);
15575
        return NULL;
15576
    }
15577
    Py_RETURN_NONE;
15578
}
15579
#endif /* MS_WINDOWS */
15580
15581
/*[clinic input]
15582
os.get_blocking -> bool
15583
    fd: int
15584
    /
15585
15586
Get the blocking mode of the file descriptor.
15587
15588
Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
15589
[clinic start generated code]*/
15590
15591
static int
15592
os_get_blocking_impl(PyObject *module, int fd)
15593
/*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
15594
0
{
15595
0
    int blocking;
15596
15597
0
    _Py_BEGIN_SUPPRESS_IPH
15598
0
    blocking = _Py_get_blocking(fd);
15599
0
    _Py_END_SUPPRESS_IPH
15600
0
    return blocking;
15601
0
}
15602
15603
/*[clinic input]
15604
os.set_blocking
15605
    fd: int
15606
    blocking: bool
15607
    /
15608
15609
Set the blocking mode of the specified file descriptor.
15610
15611
Set the O_NONBLOCK flag if blocking is False,
15612
clear the O_NONBLOCK flag otherwise.
15613
[clinic start generated code]*/
15614
15615
static PyObject *
15616
os_set_blocking_impl(PyObject *module, int fd, int blocking)
15617
/*[clinic end generated code: output=384eb43aa0762a9d input=7e9dfc9b14804dd4]*/
15618
0
{
15619
0
    int result;
15620
15621
0
    _Py_BEGIN_SUPPRESS_IPH
15622
0
    result = _Py_set_blocking(fd, blocking);
15623
0
    _Py_END_SUPPRESS_IPH
15624
0
    if (result < 0)
15625
0
        return NULL;
15626
0
    Py_RETURN_NONE;
15627
0
}
15628
15629
15630
/*[clinic input]
15631
class os.DirEntry "DirEntry *" "DirEntryType"
15632
[clinic start generated code]*/
15633
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
15634
15635
typedef struct {
15636
    PyObject_HEAD
15637
    PyObject *name;
15638
    PyObject *path;
15639
    PyObject *stat;
15640
    PyObject *lstat;
15641
#ifdef MS_WINDOWS
15642
    struct _Py_stat_struct win32_lstat;
15643
    uint64_t win32_file_index;
15644
    uint64_t win32_file_index_high;
15645
    int got_file_index;
15646
#else /* POSIX */
15647
#ifdef HAVE_DIRENT_D_TYPE
15648
    unsigned char d_type;
15649
#endif
15650
    ino_t d_ino;
15651
    int dir_fd;
15652
#endif
15653
} DirEntry;
15654
15655
0
#define DirEntry_CAST(op)   ((DirEntry *)(op))
15656
15657
static void
15658
DirEntry_dealloc(PyObject *op)
15659
0
{
15660
0
    DirEntry *entry = DirEntry_CAST(op);
15661
0
    PyTypeObject *tp = Py_TYPE(entry);
15662
0
    Py_XDECREF(entry->name);
15663
0
    Py_XDECREF(entry->path);
15664
0
    Py_XDECREF(entry->stat);
15665
0
    Py_XDECREF(entry->lstat);
15666
0
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
15667
0
    free_func(entry);
15668
0
    Py_DECREF(tp);
15669
0
}
15670
15671
/* Forward reference */
15672
static int
15673
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
15674
                   int follow_symlinks, unsigned short mode_bits);
15675
15676
/*[clinic input]
15677
os.DirEntry.is_symlink -> bool
15678
    defining_class: defining_class
15679
    /
15680
15681
Return True if the entry is a symbolic link; cached per entry.
15682
[clinic start generated code]*/
15683
15684
static int
15685
os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
15686
/*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
15687
0
{
15688
#ifdef MS_WINDOWS
15689
    return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
15690
#elif defined(HAVE_DIRENT_D_TYPE)
15691
    /* POSIX */
15692
0
    if (self->d_type != DT_UNKNOWN)
15693
0
        return self->d_type == DT_LNK;
15694
0
    else
15695
0
        return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
15696
#else
15697
    /* POSIX without d_type */
15698
    return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
15699
#endif
15700
0
}
15701
15702
/*[clinic input]
15703
os.DirEntry.is_junction -> bool
15704
15705
Return True if the entry is a junction; cached per entry.
15706
[clinic start generated code]*/
15707
15708
static int
15709
os_DirEntry_is_junction_impl(DirEntry *self)
15710
/*[clinic end generated code: output=97f64d5d99eeccb5 input=4fc8e701eea118a1]*/
15711
0
{
15712
#ifdef MS_WINDOWS
15713
    return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
15714
#else
15715
0
    return 0;
15716
0
#endif
15717
0
}
15718
15719
static PyObject *
15720
DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
15721
0
{
15722
0
    int result;
15723
0
    STRUCT_STAT st;
15724
0
    PyObject *ub;
15725
15726
#ifdef MS_WINDOWS
15727
    if (!PyUnicode_FSDecoder(self->path, &ub))
15728
        return NULL;
15729
    wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
15730
    Py_DECREF(ub);
15731
#else /* POSIX */
15732
0
    if (!PyUnicode_FSConverter(self->path, &ub))
15733
0
        return NULL;
15734
0
    const char *path = PyBytes_AS_STRING(ub);
15735
0
    if (self->dir_fd != DEFAULT_DIR_FD) {
15736
0
#ifdef HAVE_FSTATAT
15737
0
      if (HAVE_FSTATAT_RUNTIME) {
15738
0
        Py_BEGIN_ALLOW_THREADS
15739
0
        result = fstatat(self->dir_fd, path, &st,
15740
0
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
15741
0
        Py_END_ALLOW_THREADS
15742
0
      } else
15743
15744
0
#endif /* HAVE_FSTATAT */
15745
0
      {
15746
0
        Py_DECREF(ub);
15747
0
        PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
15748
0
        return NULL;
15749
0
      }
15750
0
    }
15751
0
    else
15752
0
#endif
15753
0
    {
15754
0
        Py_BEGIN_ALLOW_THREADS
15755
0
        if (follow_symlinks) {
15756
0
            result = STAT(path, &st);
15757
0
        }
15758
0
        else {
15759
0
            result = LSTAT(path, &st);
15760
0
        }
15761
0
        Py_END_ALLOW_THREADS
15762
0
    }
15763
15764
0
    int saved_errno = errno;
15765
#if defined(MS_WINDOWS)
15766
    PyMem_Free(path);
15767
#else
15768
0
    Py_DECREF(ub);
15769
0
#endif
15770
15771
0
    if (result != 0) {
15772
0
        errno = saved_errno;
15773
0
        path_object_error(self->path);
15774
0
        return NULL;
15775
0
    }
15776
15777
0
    return _pystat_fromstructstat(module, &st);
15778
0
}
15779
15780
static PyObject *
15781
DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
15782
0
{
15783
0
    if (!self->lstat) {
15784
0
        PyObject *module = PyType_GetModule(defining_class);
15785
#ifdef MS_WINDOWS
15786
        self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
15787
#else /* POSIX */
15788
0
        self->lstat = DirEntry_fetch_stat(module, self, 0);
15789
0
#endif
15790
0
    }
15791
0
    return Py_XNewRef(self->lstat);
15792
0
}
15793
15794
/*[clinic input]
15795
os.DirEntry.stat
15796
    defining_class: defining_class
15797
    /
15798
    *
15799
    follow_symlinks: bool = True
15800
15801
Return stat_result object for the entry; cached per entry.
15802
[clinic start generated code]*/
15803
15804
static PyObject *
15805
os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
15806
                      int follow_symlinks)
15807
/*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
15808
0
{
15809
0
    if (!follow_symlinks) {
15810
0
        return DirEntry_get_lstat(defining_class, self);
15811
0
    }
15812
15813
0
    if (!self->stat) {
15814
0
        int result = os_DirEntry_is_symlink_impl(self, defining_class);
15815
0
        if (result == -1) {
15816
0
            return NULL;
15817
0
        }
15818
0
        if (result) {
15819
0
            PyObject *module = PyType_GetModule(defining_class);
15820
0
            self->stat = DirEntry_fetch_stat(module, self, 1);
15821
0
        }
15822
0
        else {
15823
0
            self->stat = DirEntry_get_lstat(defining_class, self);
15824
0
        }
15825
0
    }
15826
15827
0
    return Py_XNewRef(self->stat);
15828
0
}
15829
15830
/* Set exception and return -1 on error, 0 for False, 1 for True */
15831
static int
15832
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
15833
                   int follow_symlinks, unsigned short mode_bits)
15834
0
{
15835
0
    PyObject *stat = NULL;
15836
0
    PyObject *st_mode = NULL;
15837
0
    long mode;
15838
0
    int result;
15839
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
15840
0
    int is_symlink;
15841
0
    int need_stat;
15842
0
#endif
15843
#ifdef MS_WINDOWS
15844
    unsigned long dir_bits;
15845
#endif
15846
15847
#ifdef MS_WINDOWS
15848
    is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
15849
    need_stat = follow_symlinks && is_symlink;
15850
#elif defined(HAVE_DIRENT_D_TYPE)
15851
    is_symlink = self->d_type == DT_LNK;
15852
0
    need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
15853
0
#endif
15854
15855
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
15856
0
    if (need_stat) {
15857
0
#endif
15858
0
        stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
15859
0
        if (!stat) {
15860
0
            if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
15861
                /* If file doesn't exist (anymore), then return False
15862
                   (i.e., say it's not a file/directory) */
15863
0
                PyErr_Clear();
15864
0
                return 0;
15865
0
            }
15866
0
            goto error;
15867
0
        }
15868
0
        _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
15869
0
        st_mode = PyObject_GetAttr(stat, state->st_mode);
15870
0
        if (!st_mode)
15871
0
            goto error;
15872
15873
0
        mode = PyLong_AsLong(st_mode);
15874
0
        if (mode == -1 && PyErr_Occurred())
15875
0
            goto error;
15876
0
        Py_CLEAR(st_mode);
15877
0
        Py_CLEAR(stat);
15878
0
        result = (mode & S_IFMT) == mode_bits;
15879
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
15880
0
    }
15881
0
    else if (is_symlink) {
15882
0
        assert(mode_bits != S_IFLNK);
15883
0
        result = 0;
15884
0
    }
15885
0
    else {
15886
0
        assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
15887
#ifdef MS_WINDOWS
15888
        dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
15889
        if (mode_bits == S_IFDIR)
15890
            result = dir_bits != 0;
15891
        else
15892
            result = dir_bits == 0;
15893
#else /* POSIX */
15894
0
        if (mode_bits == S_IFDIR)
15895
0
            result = self->d_type == DT_DIR;
15896
0
        else
15897
0
            result = self->d_type == DT_REG;
15898
0
#endif
15899
0
    }
15900
0
#endif
15901
15902
0
    return result;
15903
15904
0
error:
15905
0
    Py_XDECREF(st_mode);
15906
0
    Py_XDECREF(stat);
15907
0
    return -1;
15908
0
}
15909
15910
/*[clinic input]
15911
os.DirEntry.is_dir -> bool
15912
    defining_class: defining_class
15913
    /
15914
    *
15915
    follow_symlinks: bool = True
15916
15917
Return True if the entry is a directory; cached per entry.
15918
[clinic start generated code]*/
15919
15920
static int
15921
os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
15922
                        int follow_symlinks)
15923
/*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
15924
0
{
15925
0
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
15926
0
}
15927
15928
/*[clinic input]
15929
os.DirEntry.is_file -> bool
15930
    defining_class: defining_class
15931
    /
15932
    *
15933
    follow_symlinks: bool = True
15934
15935
Return True if the entry is a file; cached per entry.
15936
[clinic start generated code]*/
15937
15938
static int
15939
os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
15940
                         int follow_symlinks)
15941
/*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
15942
0
{
15943
0
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
15944
0
}
15945
15946
/*[clinic input]
15947
os.DirEntry.inode
15948
15949
Return inode of the entry; cached per entry.
15950
[clinic start generated code]*/
15951
15952
static PyObject *
15953
os_DirEntry_inode_impl(DirEntry *self)
15954
/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
15955
0
{
15956
#ifdef MS_WINDOWS
15957
    if (!self->got_file_index) {
15958
        PyObject *unicode;
15959
        STRUCT_STAT stat;
15960
        int result;
15961
15962
        if (!PyUnicode_FSDecoder(self->path, &unicode))
15963
            return NULL;
15964
        wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
15965
        Py_DECREF(unicode);
15966
        result = LSTAT(path, &stat);
15967
15968
        int saved_errno = errno;
15969
        PyMem_Free(path);
15970
15971
        if (result != 0) {
15972
            errno = saved_errno;
15973
            return path_object_error(self->path);
15974
        }
15975
15976
        self->win32_file_index = stat.st_ino;
15977
        self->win32_file_index_high = stat.st_ino_high;
15978
        self->got_file_index = 1;
15979
    }
15980
    return _pystat_l128_from_l64_l64(self->win32_file_index, self->win32_file_index_high);
15981
#else /* POSIX */
15982
0
    static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
15983
0
                  "DirEntry.d_ino is larger than unsigned long long");
15984
0
    return PyLong_FromUnsignedLongLong(self->d_ino);
15985
0
#endif
15986
0
}
15987
15988
static PyObject *
15989
DirEntry_repr(PyObject *op)
15990
0
{
15991
0
    DirEntry *self = DirEntry_CAST(op);
15992
0
    return PyUnicode_FromFormat("<DirEntry %R>", self->name);
15993
0
}
15994
15995
/*[clinic input]
15996
os.DirEntry.__fspath__
15997
15998
Returns the path for the entry.
15999
[clinic start generated code]*/
16000
16001
static PyObject *
16002
os_DirEntry___fspath___impl(DirEntry *self)
16003
/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
16004
0
{
16005
0
    return Py_NewRef(self->path);
16006
0
}
16007
16008
static PyMemberDef DirEntry_members[] = {
16009
    {"name", Py_T_OBJECT_EX, offsetof(DirEntry, name), Py_READONLY,
16010
     "the entry's base filename, relative to scandir() \"path\" argument"},
16011
    {"path", Py_T_OBJECT_EX, offsetof(DirEntry, path), Py_READONLY,
16012
     "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
16013
    {NULL}
16014
};
16015
16016
#include "clinic/posixmodule.c.h"
16017
16018
static PyMethodDef DirEntry_methods[] = {
16019
    OS_DIRENTRY_IS_DIR_METHODDEF
16020
    OS_DIRENTRY_IS_FILE_METHODDEF
16021
    OS_DIRENTRY_IS_SYMLINK_METHODDEF
16022
    OS_DIRENTRY_IS_JUNCTION_METHODDEF
16023
    OS_DIRENTRY_STAT_METHODDEF
16024
    OS_DIRENTRY_INODE_METHODDEF
16025
    OS_DIRENTRY___FSPATH___METHODDEF
16026
    {"__class_getitem__",       Py_GenericAlias,
16027
    METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
16028
    {NULL}
16029
};
16030
16031
static PyType_Slot DirEntryType_slots[] = {
16032
    {Py_tp_dealloc, DirEntry_dealloc},
16033
    {Py_tp_repr, DirEntry_repr},
16034
    {Py_tp_methods, DirEntry_methods},
16035
    {Py_tp_members, DirEntry_members},
16036
    {0, 0},
16037
};
16038
16039
static PyType_Spec DirEntryType_spec = {
16040
    MODNAME ".DirEntry",
16041
    sizeof(DirEntry),
16042
    0,
16043
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
16044
    DirEntryType_slots
16045
};
16046
16047
16048
#ifdef MS_WINDOWS
16049
16050
static wchar_t *
16051
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
16052
{
16053
    Py_ssize_t path_len;
16054
    Py_ssize_t size;
16055
    wchar_t *result;
16056
    wchar_t ch;
16057
16058
    if (!path_wide) { /* Default arg: "." */
16059
        path_wide = L".";
16060
        path_len = 1;
16061
    }
16062
    else {
16063
        path_len = wcslen(path_wide);
16064
    }
16065
16066
    /* The +1's are for the path separator and the NUL */
16067
    size = path_len + 1 + wcslen(filename) + 1;
16068
    result = PyMem_New(wchar_t, size);
16069
    if (!result) {
16070
        PyErr_NoMemory();
16071
        return NULL;
16072
    }
16073
    wcscpy(result, path_wide);
16074
    if (path_len > 0) {
16075
        ch = result[path_len - 1];
16076
        if (ch != SEP && ch != ALTSEP && ch != L':')
16077
            result[path_len++] = SEP;
16078
        wcscpy(result + path_len, filename);
16079
    }
16080
    return result;
16081
}
16082
16083
static PyObject *
16084
DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
16085
{
16086
    DirEntry *entry;
16087
    BY_HANDLE_FILE_INFORMATION file_info;
16088
    ULONG reparse_tag;
16089
    wchar_t *joined_path;
16090
16091
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16092
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16093
    if (!entry)
16094
        return NULL;
16095
    entry->name = NULL;
16096
    entry->path = NULL;
16097
    entry->stat = NULL;
16098
    entry->lstat = NULL;
16099
    entry->got_file_index = 0;
16100
16101
    entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
16102
    if (!entry->name)
16103
        goto error;
16104
    int return_bytes = path->wide && PyBytes_Check(path->object);
16105
    if (return_bytes) {
16106
        Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
16107
        if (!entry->name)
16108
            goto error;
16109
    }
16110
16111
    joined_path = join_path_filenameW(path->wide, dataW->cFileName);
16112
    if (!joined_path)
16113
        goto error;
16114
16115
    entry->path = PyUnicode_FromWideChar(joined_path, -1);
16116
    PyMem_Free(joined_path);
16117
    if (!entry->path)
16118
        goto error;
16119
    if (return_bytes) {
16120
        Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
16121
        if (!entry->path)
16122
            goto error;
16123
    }
16124
16125
    find_data_to_file_info(dataW, &file_info, &reparse_tag);
16126
    _Py_attribute_data_to_stat(&file_info, reparse_tag, NULL, NULL, &entry->win32_lstat);
16127
16128
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
16129
    entry->win32_lstat.st_ctime = entry->win32_lstat.st_birthtime;
16130
    entry->win32_lstat.st_ctime_nsec = entry->win32_lstat.st_birthtime_nsec;
16131
16132
    return (PyObject *)entry;
16133
16134
error:
16135
    Py_DECREF(entry);
16136
    return NULL;
16137
}
16138
16139
#else /* POSIX */
16140
16141
static char *
16142
join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
16143
0
{
16144
0
    Py_ssize_t path_len;
16145
0
    Py_ssize_t size;
16146
0
    char *result;
16147
16148
0
    if (!path_narrow) { /* Default arg: "." */
16149
0
        path_narrow = ".";
16150
0
        path_len = 1;
16151
0
    }
16152
0
    else {
16153
0
        path_len = strlen(path_narrow);
16154
0
    }
16155
16156
0
    if (filename_len == -1)
16157
0
        filename_len = strlen(filename);
16158
16159
    /* The +1's are for the path separator and the NUL */
16160
0
    size = path_len + 1 + filename_len + 1;
16161
0
    result = PyMem_New(char, size);
16162
0
    if (!result) {
16163
0
        PyErr_NoMemory();
16164
0
        return NULL;
16165
0
    }
16166
0
    strcpy(result, path_narrow);
16167
0
    if (path_len > 0 && result[path_len - 1] != '/')
16168
0
        result[path_len++] = '/';
16169
0
    strcpy(result + path_len, filename);
16170
0
    return result;
16171
0
}
16172
16173
static PyObject *
16174
DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
16175
                         Py_ssize_t name_len, ino_t d_ino
16176
#ifdef HAVE_DIRENT_D_TYPE
16177
                         , unsigned char d_type
16178
#endif
16179
                         )
16180
0
{
16181
0
    DirEntry *entry;
16182
0
    char *joined_path;
16183
16184
0
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16185
0
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16186
0
    if (!entry)
16187
0
        return NULL;
16188
0
    entry->name = NULL;
16189
0
    entry->path = NULL;
16190
0
    entry->stat = NULL;
16191
0
    entry->lstat = NULL;
16192
16193
0
    if (path->fd != -1) {
16194
0
        entry->dir_fd = path->fd;
16195
0
        joined_path = NULL;
16196
0
    }
16197
0
    else {
16198
0
        entry->dir_fd = DEFAULT_DIR_FD;
16199
0
        joined_path = join_path_filename(path->narrow, name, name_len);
16200
0
        if (!joined_path)
16201
0
            goto error;
16202
0
    }
16203
16204
0
    if (!path->narrow || !PyBytes_Check(path->object)) {
16205
0
        entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
16206
0
        if (joined_path)
16207
0
            entry->path = PyUnicode_DecodeFSDefault(joined_path);
16208
0
    }
16209
0
    else {
16210
0
        entry->name = PyBytes_FromStringAndSize(name, name_len);
16211
0
        if (joined_path)
16212
0
            entry->path = PyBytes_FromString(joined_path);
16213
0
    }
16214
0
    PyMem_Free(joined_path);
16215
0
    if (!entry->name)
16216
0
        goto error;
16217
16218
0
    if (path->fd != -1) {
16219
0
        entry->path = Py_NewRef(entry->name);
16220
0
    }
16221
0
    else if (!entry->path)
16222
0
        goto error;
16223
16224
0
#ifdef HAVE_DIRENT_D_TYPE
16225
0
    entry->d_type = d_type;
16226
0
#endif
16227
0
    entry->d_ino = d_ino;
16228
16229
0
    return (PyObject *)entry;
16230
16231
0
error:
16232
0
    Py_XDECREF(entry);
16233
0
    return NULL;
16234
0
}
16235
16236
#endif
16237
16238
16239
typedef struct {
16240
    PyObject_HEAD
16241
    path_t path;
16242
#ifdef MS_WINDOWS
16243
    HANDLE handle;
16244
    WIN32_FIND_DATAW file_data;
16245
    int first_time;
16246
#else /* POSIX */
16247
    DIR *dirp;
16248
#endif
16249
#ifdef HAVE_FDOPENDIR
16250
    int fd;
16251
#endif
16252
} ScandirIterator;
16253
16254
0
#define ScandirIterator_CAST(op)    ((ScandirIterator *)(op))
16255
16256
#ifdef MS_WINDOWS
16257
16258
static int
16259
ScandirIterator_is_closed(ScandirIterator *iterator)
16260
{
16261
    return iterator->handle == INVALID_HANDLE_VALUE;
16262
}
16263
16264
static void
16265
ScandirIterator_closedir(ScandirIterator *iterator)
16266
{
16267
    HANDLE handle = iterator->handle;
16268
16269
    if (handle == INVALID_HANDLE_VALUE)
16270
        return;
16271
16272
    iterator->handle = INVALID_HANDLE_VALUE;
16273
    Py_BEGIN_ALLOW_THREADS
16274
    FindClose(handle);
16275
    Py_END_ALLOW_THREADS
16276
}
16277
16278
static PyObject *
16279
ScandirIterator_iternext(PyObject *op)
16280
{
16281
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16282
    WIN32_FIND_DATAW *file_data = &iterator->file_data;
16283
    BOOL success;
16284
    PyObject *entry;
16285
16286
    /* Happens if the iterator is iterated twice, or closed explicitly */
16287
    if (iterator->handle == INVALID_HANDLE_VALUE)
16288
        return NULL;
16289
16290
    while (1) {
16291
        if (!iterator->first_time) {
16292
            Py_BEGIN_ALLOW_THREADS
16293
            success = FindNextFileW(iterator->handle, file_data);
16294
            Py_END_ALLOW_THREADS
16295
            if (!success) {
16296
                /* Error or no more files */
16297
                if (GetLastError() != ERROR_NO_MORE_FILES)
16298
                    path_error(&iterator->path);
16299
                break;
16300
            }
16301
        }
16302
        iterator->first_time = 0;
16303
16304
        /* Skip over . and .. */
16305
        if (wcscmp(file_data->cFileName, L".") != 0 &&
16306
            wcscmp(file_data->cFileName, L"..") != 0)
16307
        {
16308
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16309
            entry = DirEntry_from_find_data(module, &iterator->path, file_data);
16310
            if (!entry)
16311
                break;
16312
            return entry;
16313
        }
16314
16315
        /* Loop till we get a non-dot directory or finish iterating */
16316
    }
16317
16318
    /* Error or no more files */
16319
    ScandirIterator_closedir(iterator);
16320
    return NULL;
16321
}
16322
16323
#else /* POSIX */
16324
16325
static int
16326
ScandirIterator_is_closed(ScandirIterator *iterator)
16327
0
{
16328
0
    return !iterator->dirp;
16329
0
}
16330
16331
static void
16332
ScandirIterator_closedir(ScandirIterator *iterator)
16333
0
{
16334
0
    DIR *dirp = iterator->dirp;
16335
16336
0
    if (!dirp)
16337
0
        return;
16338
16339
0
    iterator->dirp = NULL;
16340
0
    Py_BEGIN_ALLOW_THREADS
16341
0
#ifdef HAVE_FDOPENDIR
16342
0
    if (iterator->path.fd != -1)
16343
0
        rewinddir(dirp);
16344
0
#endif
16345
0
    closedir(dirp);
16346
0
    Py_END_ALLOW_THREADS
16347
0
    return;
16348
0
}
16349
16350
static PyObject *
16351
ScandirIterator_iternext(PyObject *op)
16352
0
{
16353
0
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16354
0
    struct dirent *direntp;
16355
0
    Py_ssize_t name_len;
16356
0
    int is_dot;
16357
0
    PyObject *entry;
16358
16359
    /* Happens if the iterator is iterated twice, or closed explicitly */
16360
0
    if (!iterator->dirp)
16361
0
        return NULL;
16362
16363
0
    while (1) {
16364
0
        errno = 0;
16365
0
        Py_BEGIN_ALLOW_THREADS
16366
0
        direntp = readdir(iterator->dirp);
16367
0
        Py_END_ALLOW_THREADS
16368
16369
0
        if (!direntp) {
16370
            /* Error or no more files */
16371
0
            if (errno != 0)
16372
0
                path_error(&iterator->path);
16373
0
            break;
16374
0
        }
16375
16376
        /* Skip over . and .. */
16377
0
        name_len = NAMLEN(direntp);
16378
0
        is_dot = direntp->d_name[0] == '.' &&
16379
0
                 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
16380
0
        if (!is_dot) {
16381
0
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16382
0
            entry = DirEntry_from_posix_info(module,
16383
0
                                             &iterator->path, direntp->d_name,
16384
0
                                             name_len, direntp->d_ino
16385
0
#ifdef HAVE_DIRENT_D_TYPE
16386
0
                                             , direntp->d_type
16387
0
#endif
16388
0
                                            );
16389
0
            if (!entry)
16390
0
                break;
16391
0
            return entry;
16392
0
        }
16393
16394
        /* Loop till we get a non-dot directory or finish iterating */
16395
0
    }
16396
16397
    /* Error or no more files */
16398
0
    ScandirIterator_closedir(iterator);
16399
0
    return NULL;
16400
0
}
16401
16402
#endif
16403
16404
static PyObject *
16405
ScandirIterator_close(PyObject *op, PyObject *Py_UNUSED(dummy))
16406
0
{
16407
0
    ScandirIterator *self = ScandirIterator_CAST(op);
16408
0
    ScandirIterator_closedir(self);
16409
0
    Py_RETURN_NONE;
16410
0
}
16411
16412
static PyObject *
16413
ScandirIterator_enter(PyObject *self, PyObject *Py_UNUSED(dummy))
16414
0
{
16415
0
    return Py_NewRef(self);
16416
0
}
16417
16418
static PyObject *
16419
ScandirIterator_exit(PyObject *op, PyObject *Py_UNUSED(args))
16420
0
{
16421
0
    ScandirIterator *self = ScandirIterator_CAST(op);
16422
0
    ScandirIterator_closedir(self);
16423
0
    Py_RETURN_NONE;
16424
0
}
16425
16426
static void
16427
ScandirIterator_finalize(PyObject *op)
16428
0
{
16429
0
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16430
    /* Save the current exception, if any. */
16431
0
    PyObject *exc = PyErr_GetRaisedException();
16432
16433
0
    if (!ScandirIterator_is_closed(iterator)) {
16434
0
        ScandirIterator_closedir(iterator);
16435
16436
0
        if (PyErr_ResourceWarning(op, 1,
16437
0
                                  "unclosed scandir iterator %R", iterator))
16438
0
        {
16439
            /* Spurious errors can appear at shutdown */
16440
0
            if (PyErr_ExceptionMatches(PyExc_Warning)) {
16441
0
                PyErr_FormatUnraisable("Exception ignored while finalizing "
16442
0
                                       "scandir iterator %R", iterator);
16443
0
            }
16444
0
        }
16445
0
    }
16446
16447
0
    path_cleanup(&iterator->path);
16448
16449
    /* Restore the saved exception. */
16450
0
    PyErr_SetRaisedException(exc);
16451
0
}
16452
16453
static void
16454
ScandirIterator_dealloc(PyObject *op)
16455
0
{
16456
0
    PyTypeObject *tp = Py_TYPE(op);
16457
0
    if (PyObject_CallFinalizerFromDealloc(op) < 0)
16458
0
        return;
16459
16460
0
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16461
0
    free_func(op);
16462
0
    Py_DECREF(tp);
16463
0
}
16464
16465
static PyMethodDef ScandirIterator_methods[] = {
16466
    {"__enter__", ScandirIterator_enter, METH_NOARGS},
16467
    {"__exit__", ScandirIterator_exit, METH_VARARGS},
16468
    {"close", ScandirIterator_close, METH_NOARGS},
16469
    {NULL}
16470
};
16471
16472
static PyType_Slot ScandirIteratorType_slots[] = {
16473
    {Py_tp_dealloc, ScandirIterator_dealloc},
16474
    {Py_tp_finalize, ScandirIterator_finalize},
16475
    {Py_tp_iter, PyObject_SelfIter},
16476
    {Py_tp_iternext, ScandirIterator_iternext},
16477
    {Py_tp_methods, ScandirIterator_methods},
16478
    {0, 0},
16479
};
16480
16481
static PyType_Spec ScandirIteratorType_spec = {
16482
    MODNAME ".ScandirIterator",
16483
    sizeof(ScandirIterator),
16484
    0,
16485
    // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
16486
    // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
16487
    (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE
16488
        | Py_TPFLAGS_DISALLOW_INSTANTIATION),
16489
    ScandirIteratorType_slots
16490
};
16491
16492
/*[clinic input]
16493
os.scandir
16494
16495
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
16496
16497
Return an iterator of DirEntry objects for given path.
16498
16499
path can be specified as either str, bytes, or a path-like object.  If path
16500
is bytes, the names of yielded DirEntry objects will also be bytes; in
16501
all other circumstances they will be str.
16502
16503
If path is None, uses the path='.'.
16504
[clinic start generated code]*/
16505
16506
static PyObject *
16507
os_scandir_impl(PyObject *module, path_t *path)
16508
/*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
16509
0
{
16510
0
    ScandirIterator *iterator;
16511
#ifdef MS_WINDOWS
16512
    wchar_t *path_strW;
16513
#else
16514
0
    const char *path_str;
16515
0
#ifdef HAVE_FDOPENDIR
16516
0
    int fd = -1;
16517
0
#endif
16518
0
#endif
16519
16520
0
    if (PySys_Audit("os.scandir", "O",
16521
0
                    path->object ? path->object : Py_None) < 0) {
16522
0
        return NULL;
16523
0
    }
16524
16525
0
    PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
16526
0
    iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
16527
0
    if (!iterator)
16528
0
        return NULL;
16529
16530
#ifdef MS_WINDOWS
16531
    iterator->handle = INVALID_HANDLE_VALUE;
16532
#else
16533
0
    iterator->dirp = NULL;
16534
0
#endif
16535
16536
    /* Move the ownership to iterator->path */
16537
0
    memcpy(&iterator->path, path, sizeof(path_t));
16538
0
    memset(path, 0, sizeof(path_t));
16539
16540
#ifdef MS_WINDOWS
16541
    iterator->first_time = 1;
16542
16543
    path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
16544
    if (!path_strW)
16545
        goto error;
16546
16547
    Py_BEGIN_ALLOW_THREADS
16548
    iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
16549
    Py_END_ALLOW_THREADS
16550
16551
    if (iterator->handle == INVALID_HANDLE_VALUE) {
16552
        path_error(&iterator->path);
16553
        PyMem_Free(path_strW);
16554
        goto error;
16555
    }
16556
    PyMem_Free(path_strW);
16557
#else /* POSIX */
16558
0
    errno = 0;
16559
0
#ifdef HAVE_FDOPENDIR
16560
0
    if (iterator->path.fd != -1) {
16561
0
      if (HAVE_FDOPENDIR_RUNTIME) {
16562
        /* closedir() closes the FD, so we duplicate it */
16563
0
        fd = _Py_dup(iterator->path.fd);
16564
0
        if (fd == -1)
16565
0
            goto error;
16566
16567
0
        Py_BEGIN_ALLOW_THREADS
16568
0
        iterator->dirp = fdopendir(fd);
16569
0
        Py_END_ALLOW_THREADS
16570
0
      } else {
16571
0
        PyErr_SetString(PyExc_TypeError,
16572
0
            "scandir: path should be string, bytes, os.PathLike or None, not int");
16573
0
        return NULL;
16574
0
      }
16575
0
    }
16576
0
    else
16577
0
#endif
16578
0
    {
16579
0
        if (iterator->path.narrow)
16580
0
            path_str = iterator->path.narrow;
16581
0
        else
16582
0
            path_str = ".";
16583
16584
0
        Py_BEGIN_ALLOW_THREADS
16585
0
        iterator->dirp = opendir(path_str);
16586
0
        Py_END_ALLOW_THREADS
16587
0
    }
16588
16589
0
    if (!iterator->dirp) {
16590
0
        path_error(&iterator->path);
16591
0
#ifdef HAVE_FDOPENDIR
16592
0
        if (fd != -1) {
16593
0
            Py_BEGIN_ALLOW_THREADS
16594
0
            close(fd);
16595
0
            Py_END_ALLOW_THREADS
16596
0
        }
16597
0
#endif
16598
0
        goto error;
16599
0
    }
16600
0
#endif
16601
16602
0
    return (PyObject *)iterator;
16603
16604
0
error:
16605
0
    Py_DECREF(iterator);
16606
0
    return NULL;
16607
0
}
16608
16609
/*
16610
    Return the file system path representation of the object.
16611
16612
    If the object is str or bytes, then allow it to pass through with
16613
    an incremented refcount. If the object defines __fspath__(), then
16614
    return the result of that method. All other types raise a TypeError.
16615
*/
16616
PyObject *
16617
PyOS_FSPath(PyObject *path)
16618
9.01k
{
16619
    /* For error message reasons, this function is manually inlined in
16620
       path_converter(). */
16621
9.01k
    PyObject *func = NULL;
16622
9.01k
    PyObject *path_repr = NULL;
16623
16624
9.01k
    if (PyUnicode_Check(path) || PyBytes_Check(path)) {
16625
9.01k
        return Py_NewRef(path);
16626
9.01k
    }
16627
16628
0
    func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
16629
0
    if ((NULL == func) || (func == Py_None)) {
16630
0
        return PyErr_Format(PyExc_TypeError,
16631
0
                            "expected str, bytes or os.PathLike object, "
16632
0
                            "not %.200s",
16633
0
                            _PyType_Name(Py_TYPE(path)));
16634
0
    }
16635
16636
0
    path_repr = _PyObject_CallNoArgs(func);
16637
0
    Py_DECREF(func);
16638
0
    if (NULL == path_repr) {
16639
0
        return NULL;
16640
0
    }
16641
16642
0
    if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
16643
0
        PyErr_Format(PyExc_TypeError,
16644
0
                     "expected %.200s.__fspath__() to return str or bytes, "
16645
0
                     "not %.200s", _PyType_Name(Py_TYPE(path)),
16646
0
                     _PyType_Name(Py_TYPE(path_repr)));
16647
0
        Py_DECREF(path_repr);
16648
0
        return NULL;
16649
0
    }
16650
16651
0
    return path_repr;
16652
0
}
16653
16654
/*[clinic input]
16655
@permit_long_docstring_body
16656
os.fspath
16657
16658
    path: object
16659
16660
Return the file system path representation of the object.
16661
16662
If the object is str or bytes, then allow it to pass through as-is. If the
16663
object defines __fspath__(), then return the result of that method. All other
16664
types raise a TypeError.
16665
[clinic start generated code]*/
16666
16667
static PyObject *
16668
os_fspath_impl(PyObject *module, PyObject *path)
16669
/*[clinic end generated code: output=c3c3b78ecff2914f input=f608743e60a3211e]*/
16670
1.93k
{
16671
1.93k
    return PyOS_FSPath(path);
16672
1.93k
}
16673
16674
#ifdef HAVE_GETRANDOM_SYSCALL
16675
/*[clinic input]
16676
os.getrandom
16677
16678
    size: Py_ssize_t
16679
    flags: int=0
16680
16681
Obtain a series of random bytes.
16682
[clinic start generated code]*/
16683
16684
static PyObject *
16685
os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
16686
/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
16687
0
{
16688
0
    PyObject *bytes;
16689
0
    Py_ssize_t n;
16690
16691
0
    if (size < 0) {
16692
0
        errno = EINVAL;
16693
0
        return posix_error();
16694
0
    }
16695
16696
0
    bytes = PyBytes_FromStringAndSize(NULL, size);
16697
0
    if (bytes == NULL) {
16698
0
        PyErr_NoMemory();
16699
0
        return NULL;
16700
0
    }
16701
16702
0
    while (1) {
16703
0
        n = syscall(SYS_getrandom,
16704
0
                    PyBytes_AS_STRING(bytes),
16705
0
                    PyBytes_GET_SIZE(bytes),
16706
0
                    flags);
16707
0
        if (n < 0 && errno == EINTR) {
16708
0
            if (PyErr_CheckSignals() < 0) {
16709
0
                goto error;
16710
0
            }
16711
16712
            /* getrandom() was interrupted by a signal: retry */
16713
0
            continue;
16714
0
        }
16715
0
        break;
16716
0
    }
16717
16718
0
    if (n < 0) {
16719
0
        PyErr_SetFromErrno(PyExc_OSError);
16720
0
        goto error;
16721
0
    }
16722
16723
0
    if (n != size) {
16724
0
        _PyBytes_Resize(&bytes, n);
16725
0
    }
16726
16727
0
    return bytes;
16728
16729
0
error:
16730
0
    Py_DECREF(bytes);
16731
0
    return NULL;
16732
0
}
16733
#endif   /* HAVE_GETRANDOM_SYSCALL */
16734
16735
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
16736
16737
/* bpo-36085: Helper functions for managing DLL search directories
16738
 * on win32
16739
 */
16740
16741
/*[clinic input]
16742
os._add_dll_directory
16743
16744
    path: path_t
16745
16746
Add a path to the DLL search path.
16747
16748
This search path is used when resolving dependencies for imported
16749
extension modules (the module itself is resolved through sys.path),
16750
and also by ctypes.
16751
16752
Returns an opaque value that may be passed to os.remove_dll_directory
16753
to remove this directory from the search path.
16754
[clinic start generated code]*/
16755
16756
static PyObject *
16757
os__add_dll_directory_impl(PyObject *module, path_t *path)
16758
/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
16759
{
16760
    DLL_DIRECTORY_COOKIE cookie = 0;
16761
    DWORD err = 0;
16762
16763
    if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
16764
        return NULL;
16765
    }
16766
16767
    Py_BEGIN_ALLOW_THREADS
16768
    if (!(cookie = AddDllDirectory(path->wide))) {
16769
        err = GetLastError();
16770
    }
16771
    Py_END_ALLOW_THREADS
16772
16773
    if (err) {
16774
        return win32_error_object_err("add_dll_directory",
16775
                                      path->object, err);
16776
    }
16777
16778
    return PyCapsule_New(cookie, "DLL directory cookie", NULL);
16779
}
16780
16781
/*[clinic input]
16782
os._remove_dll_directory
16783
16784
    cookie: object
16785
16786
Removes a path from the DLL search path.
16787
16788
The parameter is an opaque value that was returned from
16789
os.add_dll_directory. You can only remove directories that you added
16790
yourself.
16791
[clinic start generated code]*/
16792
16793
static PyObject *
16794
os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
16795
/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
16796
{
16797
    DLL_DIRECTORY_COOKIE cookieValue;
16798
    DWORD err = 0;
16799
16800
    if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
16801
        PyErr_SetString(PyExc_TypeError,
16802
            "Provided cookie was not returned from os.add_dll_directory");
16803
        return NULL;
16804
    }
16805
16806
    cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
16807
        cookie, "DLL directory cookie");
16808
16809
    Py_BEGIN_ALLOW_THREADS
16810
    if (!RemoveDllDirectory(cookieValue)) {
16811
        err = GetLastError();
16812
    }
16813
    Py_END_ALLOW_THREADS
16814
16815
    if (err) {
16816
        return win32_error_object_err("remove_dll_directory",
16817
                                      NULL, err);
16818
    }
16819
16820
    if (PyCapsule_SetName(cookie, NULL)) {
16821
        return NULL;
16822
    }
16823
16824
    Py_RETURN_NONE;
16825
}
16826
16827
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
16828
16829
16830
/* Only check if WIFEXITED is available: expect that it comes
16831
   with WEXITSTATUS, WIFSIGNALED, etc.
16832
16833
   os.waitstatus_to_exitcode() is implemented in C and not in Python, so
16834
   subprocess can safely call it during late Python finalization without
16835
   risking that used os attributes were set to None by finalize_modules(). */
16836
#if defined(WIFEXITED) || defined(MS_WINDOWS)
16837
/*[clinic input]
16838
os.waitstatus_to_exitcode
16839
16840
    status as status_obj: object
16841
16842
Convert a wait status to an exit code.
16843
16844
On Unix:
16845
16846
* If WIFEXITED(status) is true, return WEXITSTATUS(status).
16847
* If WIFSIGNALED(status) is true, return -WTERMSIG(status).
16848
* Otherwise, raise a ValueError.
16849
16850
On Windows, return status shifted right by 8 bits.
16851
16852
On Unix, if the process is being traced or if waitpid() was called with
16853
WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
16854
This function must not be called if WIFSTOPPED(status) is true.
16855
[clinic start generated code]*/
16856
16857
static PyObject *
16858
os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
16859
/*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
16860
0
{
16861
0
#ifndef MS_WINDOWS
16862
0
    int status = PyLong_AsInt(status_obj);
16863
0
    if (status == -1 && PyErr_Occurred()) {
16864
0
        return NULL;
16865
0
    }
16866
16867
0
    WAIT_TYPE wait_status;
16868
0
    WAIT_STATUS_INT(wait_status) = status;
16869
0
    int exitcode;
16870
0
    if (WIFEXITED(wait_status)) {
16871
0
        exitcode = WEXITSTATUS(wait_status);
16872
        /* Sanity check to provide warranty on the function behavior.
16873
           It should not occur in practice */
16874
0
        if (exitcode < 0) {
16875
0
            PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
16876
0
            return NULL;
16877
0
        }
16878
0
    }
16879
0
    else if (WIFSIGNALED(wait_status)) {
16880
0
        int signum = WTERMSIG(wait_status);
16881
        /* Sanity check to provide warranty on the function behavior.
16882
           It should not occurs in practice */
16883
0
        if (signum <= 0) {
16884
0
            PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
16885
0
            return NULL;
16886
0
        }
16887
0
        exitcode = -signum;
16888
0
    } else if (WIFSTOPPED(wait_status)) {
16889
        /* Status only received if the process is being traced
16890
           or if waitpid() was called with WUNTRACED option. */
16891
0
        int signum = WSTOPSIG(wait_status);
16892
0
        PyErr_Format(PyExc_ValueError,
16893
0
                     "process stopped by delivery of signal %i",
16894
0
                     signum);
16895
0
        return NULL;
16896
0
    }
16897
0
    else {
16898
0
        PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
16899
0
        return NULL;
16900
0
    }
16901
0
    return PyLong_FromLong(exitcode);
16902
#else
16903
    /* Windows implementation: see os.waitpid() implementation
16904
       which uses _cwait(). */
16905
    unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
16906
    if (status == (unsigned long long)-1 && PyErr_Occurred()) {
16907
        return NULL;
16908
    }
16909
16910
    unsigned long long exitcode = (status >> 8);
16911
    /* ExitProcess() accepts an UINT type:
16912
       reject exit code which doesn't fit in an UINT */
16913
    if (exitcode > UINT_MAX) {
16914
        PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
16915
        return NULL;
16916
    }
16917
    return PyLong_FromUnsignedLong((unsigned long)exitcode);
16918
#endif
16919
0
}
16920
#endif
16921
16922
#if defined(MS_WINDOWS)
16923
/*[clinic input]
16924
os._supports_virtual_terminal
16925
16926
Checks if virtual terminal is supported in windows
16927
[clinic start generated code]*/
16928
16929
static PyObject *
16930
os__supports_virtual_terminal_impl(PyObject *module)
16931
/*[clinic end generated code: output=bd0556a6d9d99fe6 input=0752c98e5d321542]*/
16932
{
16933
#ifdef HAVE_WINDOWS_CONSOLE_IO
16934
    DWORD mode = 0;
16935
    HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
16936
    if (!GetConsoleMode(handle, &mode)) {
16937
        Py_RETURN_FALSE;
16938
    }
16939
    return PyBool_FromLong(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING);
16940
#else
16941
    Py_RETURN_FALSE;
16942
#endif /* HAVE_WINDOWS_CONSOLE_IO */
16943
}
16944
#endif
16945
16946
/*[clinic input]
16947
os._inputhook
16948
16949
Calls PyOS_CallInputHook droppong the GIL first
16950
[clinic start generated code]*/
16951
16952
static PyObject *
16953
os__inputhook_impl(PyObject *module)
16954
/*[clinic end generated code: output=525aca4ef3c6149f input=fc531701930d064f]*/
16955
0
{
16956
0
     int result = 0;
16957
0
     if (PyOS_InputHook) {
16958
0
         Py_BEGIN_ALLOW_THREADS;
16959
0
         result = PyOS_InputHook();
16960
0
         Py_END_ALLOW_THREADS;
16961
0
     }
16962
0
     return PyLong_FromLong(result);
16963
0
}
16964
16965
/*[clinic input]
16966
os._is_inputhook_installed
16967
16968
Checks if PyOS_CallInputHook is set
16969
[clinic start generated code]*/
16970
16971
static PyObject *
16972
os__is_inputhook_installed_impl(PyObject *module)
16973
/*[clinic end generated code: output=3b3eab4f672c689a input=ff177c9938dd76d8]*/
16974
0
{
16975
0
    return PyBool_FromLong(PyOS_InputHook != NULL);
16976
0
}
16977
16978
/*[clinic input]
16979
os._create_environ
16980
16981
Create the environment dictionary.
16982
[clinic start generated code]*/
16983
16984
static PyObject *
16985
os__create_environ_impl(PyObject *module)
16986
/*[clinic end generated code: output=19d9039ab14f8ad4 input=a4c05686b34635e8]*/
16987
0
{
16988
0
    return convertenviron();
16989
0
}
16990
16991
16992
#ifdef __EMSCRIPTEN__
16993
/*[clinic input]
16994
os._emscripten_debugger
16995
16996
Create a breakpoint for the JavaScript debugger. Emscripten only.
16997
[clinic start generated code]*/
16998
16999
static PyObject *
17000
os__emscripten_debugger_impl(PyObject *module)
17001
/*[clinic end generated code: output=ad47dc3bf0661343 input=d814b1877fb6083a]*/
17002
{
17003
    emscripten_debugger();
17004
    Py_RETURN_NONE;
17005
}
17006
17007
EM_JS(void, emscripten_log_impl_js, (const char* arg), {
17008
    console.warn(UTF8ToString(arg));
17009
});
17010
17011
/*[clinic input]
17012
os._emscripten_log
17013
   arg: str
17014
17015
Log something to the JS console. Emscripten only.
17016
[clinic start generated code]*/
17017
17018
static PyObject *
17019
os__emscripten_log_impl(PyObject *module, const char *arg)
17020
/*[clinic end generated code: output=9749e5e293c42784 input=350aa1f70bc1e905]*/
17021
{
17022
    emscripten_log_impl_js(arg);
17023
    Py_RETURN_NONE;
17024
}
17025
#endif /* __EMSCRIPTEN__ */
17026
17027
17028
static PyMethodDef posix_methods[] = {
17029
    OS_STAT_METHODDEF
17030
    OS_ACCESS_METHODDEF
17031
    OS_TTYNAME_METHODDEF
17032
    OS_CHDIR_METHODDEF
17033
    OS_CHFLAGS_METHODDEF
17034
    OS_CHMOD_METHODDEF
17035
    OS_FCHMOD_METHODDEF
17036
    OS_LCHMOD_METHODDEF
17037
    OS_CHOWN_METHODDEF
17038
    OS_FCHOWN_METHODDEF
17039
    OS_LCHOWN_METHODDEF
17040
    OS_LCHFLAGS_METHODDEF
17041
    OS_CHROOT_METHODDEF
17042
    OS_CTERMID_METHODDEF
17043
    OS_GETCWD_METHODDEF
17044
    OS_GETCWDB_METHODDEF
17045
    OS_LINK_METHODDEF
17046
    OS_LISTDIR_METHODDEF
17047
    OS_LISTDRIVES_METHODDEF
17048
    OS_LISTMOUNTS_METHODDEF
17049
    OS_LISTVOLUMES_METHODDEF
17050
    OS_LSTAT_METHODDEF
17051
    OS_MKDIR_METHODDEF
17052
    OS_NICE_METHODDEF
17053
    OS_GETPRIORITY_METHODDEF
17054
    OS_SETPRIORITY_METHODDEF
17055
    OS_POSIX_SPAWN_METHODDEF
17056
    OS_POSIX_SPAWNP_METHODDEF
17057
    OS_READLINK_METHODDEF
17058
    OS_COPY_FILE_RANGE_METHODDEF
17059
    OS_SPLICE_METHODDEF
17060
    OS_RENAME_METHODDEF
17061
    OS_REPLACE_METHODDEF
17062
    OS_RMDIR_METHODDEF
17063
    OS_SYMLINK_METHODDEF
17064
    OS_SYSTEM_METHODDEF
17065
    OS_UMASK_METHODDEF
17066
    OS_UNAME_METHODDEF
17067
    OS_UNLINK_METHODDEF
17068
    OS_REMOVE_METHODDEF
17069
    OS_UTIME_METHODDEF
17070
    OS_TIMES_METHODDEF
17071
    OS__EXIT_METHODDEF
17072
    OS__FCOPYFILE_METHODDEF
17073
    OS_EXECV_METHODDEF
17074
    OS_EXECVE_METHODDEF
17075
    OS_SPAWNV_METHODDEF
17076
    OS_SPAWNVE_METHODDEF
17077
    OS_FORK1_METHODDEF
17078
    OS_FORK_METHODDEF
17079
    OS_REGISTER_AT_FORK_METHODDEF
17080
    OS_SCHED_GET_PRIORITY_MAX_METHODDEF
17081
    OS_SCHED_GET_PRIORITY_MIN_METHODDEF
17082
    OS_SCHED_GETPARAM_METHODDEF
17083
    OS_SCHED_GETSCHEDULER_METHODDEF
17084
    OS_SCHED_RR_GET_INTERVAL_METHODDEF
17085
    OS_SCHED_SETPARAM_METHODDEF
17086
    OS_SCHED_SETSCHEDULER_METHODDEF
17087
    OS_SCHED_YIELD_METHODDEF
17088
    OS_SCHED_SETAFFINITY_METHODDEF
17089
    OS_SCHED_GETAFFINITY_METHODDEF
17090
    OS_POSIX_OPENPT_METHODDEF
17091
    OS_GRANTPT_METHODDEF
17092
    OS_UNLOCKPT_METHODDEF
17093
    OS_PTSNAME_METHODDEF
17094
    OS_OPENPTY_METHODDEF
17095
    OS_LOGIN_TTY_METHODDEF
17096
    OS_FORKPTY_METHODDEF
17097
    OS_GETEGID_METHODDEF
17098
    OS_GETEUID_METHODDEF
17099
    OS_GETGID_METHODDEF
17100
    OS_GETGROUPLIST_METHODDEF
17101
    OS_GETGROUPS_METHODDEF
17102
    OS_GETPID_METHODDEF
17103
    OS_GETPGRP_METHODDEF
17104
    OS_GETPPID_METHODDEF
17105
    OS_GETUID_METHODDEF
17106
    OS_GETLOGIN_METHODDEF
17107
    OS_KILL_METHODDEF
17108
    OS_KILLPG_METHODDEF
17109
    OS_PLOCK_METHODDEF
17110
    OS_STARTFILE_METHODDEF
17111
    OS_SETUID_METHODDEF
17112
    OS_SETEUID_METHODDEF
17113
    OS_SETREUID_METHODDEF
17114
    OS_SETGID_METHODDEF
17115
    OS_SETEGID_METHODDEF
17116
    OS_SETREGID_METHODDEF
17117
    OS_SETGROUPS_METHODDEF
17118
    OS_INITGROUPS_METHODDEF
17119
    OS_GETPGID_METHODDEF
17120
    OS_SETPGRP_METHODDEF
17121
    OS_WAIT_METHODDEF
17122
    OS_WAIT3_METHODDEF
17123
    OS_WAIT4_METHODDEF
17124
    OS_WAITID_METHODDEF
17125
    OS_WAITPID_METHODDEF
17126
    OS_PIDFD_OPEN_METHODDEF
17127
    OS_GETSID_METHODDEF
17128
    OS_SETSID_METHODDEF
17129
    OS_SETPGID_METHODDEF
17130
    OS_TCGETPGRP_METHODDEF
17131
    OS_TCSETPGRP_METHODDEF
17132
    OS_OPEN_METHODDEF
17133
    OS_CLOSE_METHODDEF
17134
    OS_CLOSERANGE_METHODDEF
17135
    OS_DEVICE_ENCODING_METHODDEF
17136
    OS_DUP_METHODDEF
17137
    OS_DUP2_METHODDEF
17138
    OS_LOCKF_METHODDEF
17139
    OS_LSEEK_METHODDEF
17140
    OS_READ_METHODDEF
17141
    OS_READINTO_METHODDEF
17142
    OS_READV_METHODDEF
17143
    OS_PREAD_METHODDEF
17144
    OS_PREADV_METHODDEF
17145
    OS_WRITE_METHODDEF
17146
    OS_WRITEV_METHODDEF
17147
    OS_PWRITE_METHODDEF
17148
    OS_PWRITEV_METHODDEF
17149
    OS_SENDFILE_METHODDEF
17150
    OS_FSTAT_METHODDEF
17151
    OS_ISATTY_METHODDEF
17152
    OS_PIPE_METHODDEF
17153
    OS_PIPE2_METHODDEF
17154
    OS_MKFIFO_METHODDEF
17155
    OS_MKNOD_METHODDEF
17156
    OS_MAJOR_METHODDEF
17157
    OS_MINOR_METHODDEF
17158
    OS_MAKEDEV_METHODDEF
17159
    OS_FTRUNCATE_METHODDEF
17160
    OS_TRUNCATE_METHODDEF
17161
    OS_POSIX_FALLOCATE_METHODDEF
17162
    OS_POSIX_FADVISE_METHODDEF
17163
    OS_PUTENV_METHODDEF
17164
    OS_UNSETENV_METHODDEF
17165
    OS_STRERROR_METHODDEF
17166
    OS_FCHDIR_METHODDEF
17167
    OS_FSYNC_METHODDEF
17168
    OS_SYNC_METHODDEF
17169
    OS_FDATASYNC_METHODDEF
17170
    OS_WCOREDUMP_METHODDEF
17171
    OS_WIFCONTINUED_METHODDEF
17172
    OS_WIFSTOPPED_METHODDEF
17173
    OS_WIFSIGNALED_METHODDEF
17174
    OS_WIFEXITED_METHODDEF
17175
    OS_WEXITSTATUS_METHODDEF
17176
    OS_WTERMSIG_METHODDEF
17177
    OS_WSTOPSIG_METHODDEF
17178
    OS_FSTATVFS_METHODDEF
17179
    OS_STATVFS_METHODDEF
17180
    OS_CONFSTR_METHODDEF
17181
    OS_SYSCONF_METHODDEF
17182
    OS_FPATHCONF_METHODDEF
17183
    OS_PATHCONF_METHODDEF
17184
    OS_ABORT_METHODDEF
17185
    OS__GETFULLPATHNAME_METHODDEF
17186
    OS__GETDISKUSAGE_METHODDEF
17187
    OS__GETFINALPATHNAME_METHODDEF
17188
    OS__FINDFIRSTFILE_METHODDEF
17189
    OS__GETVOLUMEPATHNAME_METHODDEF
17190
    OS__PATH_SPLITROOT_METHODDEF
17191
    OS__PATH_SPLITROOT_EX_METHODDEF
17192
    OS__PATH_NORMPATH_METHODDEF
17193
    OS_GETLOADAVG_METHODDEF
17194
    OS_URANDOM_METHODDEF
17195
    OS_SETRESUID_METHODDEF
17196
    OS_SETRESGID_METHODDEF
17197
    OS_GETRESUID_METHODDEF
17198
    OS_GETRESGID_METHODDEF
17199
17200
    OS_GETXATTR_METHODDEF
17201
    OS_SETXATTR_METHODDEF
17202
    OS_REMOVEXATTR_METHODDEF
17203
    OS_LISTXATTR_METHODDEF
17204
17205
    OS_GET_TERMINAL_SIZE_METHODDEF
17206
    OS_CPU_COUNT_METHODDEF
17207
    OS_GET_INHERITABLE_METHODDEF
17208
    OS_SET_INHERITABLE_METHODDEF
17209
    OS_GET_HANDLE_INHERITABLE_METHODDEF
17210
    OS_SET_HANDLE_INHERITABLE_METHODDEF
17211
    OS_GET_BLOCKING_METHODDEF
17212
    OS_SET_BLOCKING_METHODDEF
17213
    OS_SCANDIR_METHODDEF
17214
    OS_FSPATH_METHODDEF
17215
    OS_GETRANDOM_METHODDEF
17216
    OS_MEMFD_CREATE_METHODDEF
17217
    OS_EVENTFD_METHODDEF
17218
    OS_EVENTFD_READ_METHODDEF
17219
    OS_EVENTFD_WRITE_METHODDEF
17220
    OS__ADD_DLL_DIRECTORY_METHODDEF
17221
    OS__REMOVE_DLL_DIRECTORY_METHODDEF
17222
    OS_WAITSTATUS_TO_EXITCODE_METHODDEF
17223
    OS_SETNS_METHODDEF
17224
    OS_UNSHARE_METHODDEF
17225
    OS_TIMERFD_CREATE_METHODDEF
17226
    OS_TIMERFD_SETTIME_METHODDEF
17227
    OS_TIMERFD_SETTIME_NS_METHODDEF
17228
    OS_TIMERFD_GETTIME_METHODDEF
17229
    OS_TIMERFD_GETTIME_NS_METHODDEF
17230
17231
    OS__PATH_ISDEVDRIVE_METHODDEF
17232
    OS__PATH_ISDIR_METHODDEF
17233
    OS__PATH_ISFILE_METHODDEF
17234
    OS__PATH_ISLINK_METHODDEF
17235
    OS__PATH_ISJUNCTION_METHODDEF
17236
    OS__PATH_EXISTS_METHODDEF
17237
    OS__PATH_LEXISTS_METHODDEF
17238
17239
    OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
17240
    OS__INPUTHOOK_METHODDEF
17241
    OS__IS_INPUTHOOK_INSTALLED_METHODDEF
17242
    OS__CREATE_ENVIRON_METHODDEF
17243
    OS__EMSCRIPTEN_DEBUGGER_METHODDEF
17244
    OS__EMSCRIPTEN_LOG_METHODDEF
17245
    {NULL,              NULL}            /* Sentinel */
17246
};
17247
17248
static int
17249
all_ins(PyObject *m)
17250
22
{
17251
22
#ifdef F_OK
17252
22
    if (PyModule_AddIntMacro(m, F_OK)) return -1;
17253
22
#endif
17254
22
#ifdef R_OK
17255
22
    if (PyModule_AddIntMacro(m, R_OK)) return -1;
17256
22
#endif
17257
22
#ifdef W_OK
17258
22
    if (PyModule_AddIntMacro(m, W_OK)) return -1;
17259
22
#endif
17260
22
#ifdef X_OK
17261
22
    if (PyModule_AddIntMacro(m, X_OK)) return -1;
17262
22
#endif
17263
22
#ifdef NGROUPS_MAX
17264
22
    if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
17265
22
#endif
17266
22
#ifdef TMP_MAX
17267
22
    if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
17268
22
#endif
17269
22
#ifdef WCONTINUED
17270
22
    if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
17271
22
#endif
17272
22
#ifdef WNOHANG
17273
22
    if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
17274
22
#endif
17275
22
#ifdef WUNTRACED
17276
22
    if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
17277
22
#endif
17278
22
#ifdef O_RDONLY
17279
22
    if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
17280
22
#endif
17281
22
#ifdef O_WRONLY
17282
22
    if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
17283
22
#endif
17284
22
#ifdef O_RDWR
17285
22
    if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
17286
22
#endif
17287
22
#ifdef O_NDELAY
17288
22
    if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
17289
22
#endif
17290
22
#ifdef O_NONBLOCK
17291
22
    if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
17292
22
#endif
17293
22
#ifdef O_APPEND
17294
22
    if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
17295
22
#endif
17296
22
#ifdef O_DSYNC
17297
22
    if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
17298
22
#endif
17299
22
#ifdef O_RSYNC
17300
22
    if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
17301
22
#endif
17302
22
#ifdef O_SYNC
17303
22
    if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
17304
22
#endif
17305
22
#ifdef O_NOCTTY
17306
22
    if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
17307
22
#endif
17308
22
#ifdef O_CREAT
17309
22
    if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
17310
22
#endif
17311
22
#ifdef O_EXCL
17312
22
    if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
17313
22
#endif
17314
22
#ifdef O_TRUNC
17315
22
    if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
17316
22
#endif
17317
#ifdef O_BINARY
17318
    if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
17319
#endif
17320
#ifdef O_TEXT
17321
    if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
17322
#endif
17323
#ifdef O_XATTR
17324
    if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
17325
#endif
17326
22
#ifdef O_LARGEFILE
17327
22
    if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
17328
22
#endif
17329
22
#ifndef __GNU__
17330
#ifdef O_SHLOCK
17331
    if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
17332
#endif
17333
#ifdef O_EXLOCK
17334
    if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
17335
#endif
17336
22
#endif
17337
#ifdef O_EXEC
17338
    if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
17339
#endif
17340
#ifdef O_SEARCH
17341
    if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
17342
#endif
17343
22
#ifdef O_PATH
17344
22
    if (PyModule_AddIntMacro(m, O_PATH)) return -1;
17345
22
#endif
17346
#ifdef O_TTY_INIT
17347
    if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
17348
#endif
17349
22
#ifdef O_TMPFILE
17350
22
    if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
17351
22
#endif
17352
22
#ifdef PRIO_PROCESS
17353
22
    if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
17354
22
#endif
17355
22
#ifdef PRIO_PGRP
17356
22
    if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
17357
22
#endif
17358
22
#ifdef PRIO_USER
17359
22
    if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
17360
22
#endif
17361
#ifdef PRIO_DARWIN_THREAD
17362
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_THREAD)) return -1;
17363
#endif
17364
#ifdef PRIO_DARWIN_PROCESS
17365
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_PROCESS)) return -1;
17366
#endif
17367
#ifdef PRIO_DARWIN_BG
17368
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_BG)) return -1;
17369
#endif
17370
#ifdef PRIO_DARWIN_NONUI
17371
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_NONUI)) return -1;
17372
#endif
17373
22
#ifdef O_CLOEXEC
17374
22
    if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
17375
22
#endif
17376
22
#ifdef O_ACCMODE
17377
22
    if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
17378
22
#endif
17379
#ifdef O_EVTONLY
17380
    if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
17381
#endif
17382
22
#ifdef O_FSYNC
17383
22
    if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
17384
22
#endif
17385
#ifdef O_SYMLINK
17386
    if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
17387
#endif
17388
17389
22
#ifdef SEEK_HOLE
17390
22
    if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
17391
22
#endif
17392
22
#ifdef SEEK_DATA
17393
22
    if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
17394
22
#endif
17395
17396
/* MS Windows */
17397
#ifdef O_NOINHERIT
17398
    /* Don't inherit in child processes. */
17399
    if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
17400
#endif
17401
#ifdef _O_SHORT_LIVED
17402
    /* Optimize for short life (keep in memory). */
17403
    /* MS forgot to define this one with a non-underscore form too. */
17404
    if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
17405
#endif
17406
#ifdef O_TEMPORARY
17407
    /* Automatically delete when last handle is closed. */
17408
    if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
17409
#endif
17410
#ifdef O_RANDOM
17411
    /* Optimize for random access. */
17412
    if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
17413
#endif
17414
#ifdef O_SEQUENTIAL
17415
    /* Optimize for sequential access. */
17416
    if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
17417
#endif
17418
17419
/* GNU extensions. */
17420
22
#ifdef O_ASYNC
17421
    /* Send a SIGIO signal whenever input or output
17422
       becomes available on file descriptor */
17423
22
    if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
17424
22
#endif
17425
22
#ifdef O_DIRECT
17426
    /* Direct disk access. */
17427
22
    if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
17428
22
#endif
17429
22
#ifdef O_DIRECTORY
17430
    /* Must be a directory.      */
17431
22
    if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
17432
22
#endif
17433
22
#ifdef O_NOFOLLOW
17434
    /* Do not follow links.      */
17435
22
    if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
17436
22
#endif
17437
#ifdef O_NOFOLLOW_ANY
17438
    if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
17439
#endif
17440
#ifdef O_NOLINKS
17441
    /* Fails if link count of the named file is greater than 1 */
17442
    if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
17443
#endif
17444
22
#ifdef O_NOATIME
17445
    /* Do not update the access time. */
17446
22
    if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
17447
22
#endif
17448
17449
    /* These come from sysexits.h */
17450
22
#ifdef EX_OK
17451
22
    if (PyModule_AddIntMacro(m, EX_OK)) return -1;
17452
22
#endif /* EX_OK */
17453
22
#ifdef EX_USAGE
17454
22
    if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
17455
22
#endif /* EX_USAGE */
17456
22
#ifdef EX_DATAERR
17457
22
    if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
17458
22
#endif /* EX_DATAERR */
17459
22
#ifdef EX_NOINPUT
17460
22
    if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
17461
22
#endif /* EX_NOINPUT */
17462
22
#ifdef EX_NOUSER
17463
22
    if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
17464
22
#endif /* EX_NOUSER */
17465
22
#ifdef EX_NOHOST
17466
22
    if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
17467
22
#endif /* EX_NOHOST */
17468
22
#ifdef EX_UNAVAILABLE
17469
22
    if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
17470
22
#endif /* EX_UNAVAILABLE */
17471
22
#ifdef EX_SOFTWARE
17472
22
    if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
17473
22
#endif /* EX_SOFTWARE */
17474
22
#ifdef EX_OSERR
17475
22
    if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
17476
22
#endif /* EX_OSERR */
17477
22
#ifdef EX_OSFILE
17478
22
    if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
17479
22
#endif /* EX_OSFILE */
17480
22
#ifdef EX_CANTCREAT
17481
22
    if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
17482
22
#endif /* EX_CANTCREAT */
17483
22
#ifdef EX_IOERR
17484
22
    if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
17485
22
#endif /* EX_IOERR */
17486
22
#ifdef EX_TEMPFAIL
17487
22
    if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
17488
22
#endif /* EX_TEMPFAIL */
17489
22
#ifdef EX_PROTOCOL
17490
22
    if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
17491
22
#endif /* EX_PROTOCOL */
17492
22
#ifdef EX_NOPERM
17493
22
    if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
17494
22
#endif /* EX_NOPERM */
17495
22
#ifdef EX_CONFIG
17496
22
    if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
17497
22
#endif /* EX_CONFIG */
17498
#ifdef EX_NOTFOUND
17499
    if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
17500
#endif /* EX_NOTFOUND */
17501
17502
    /* statvfs */
17503
22
#ifdef ST_RDONLY
17504
22
    if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
17505
22
#endif /* ST_RDONLY */
17506
22
#ifdef ST_NOSUID
17507
22
    if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
17508
22
#endif /* ST_NOSUID */
17509
17510
       /* GNU extensions */
17511
22
#ifdef ST_NODEV
17512
22
    if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
17513
22
#endif /* ST_NODEV */
17514
22
#ifdef ST_NOEXEC
17515
22
    if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
17516
22
#endif /* ST_NOEXEC */
17517
22
#ifdef ST_SYNCHRONOUS
17518
22
    if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
17519
22
#endif /* ST_SYNCHRONOUS */
17520
22
#ifdef ST_MANDLOCK
17521
22
    if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
17522
22
#endif /* ST_MANDLOCK */
17523
22
#ifdef ST_WRITE
17524
22
    if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
17525
22
#endif /* ST_WRITE */
17526
22
#ifdef ST_APPEND
17527
22
    if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
17528
22
#endif /* ST_APPEND */
17529
22
#ifdef ST_NOATIME
17530
22
    if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
17531
22
#endif /* ST_NOATIME */
17532
22
#ifdef ST_NODIRATIME
17533
22
    if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
17534
22
#endif /* ST_NODIRATIME */
17535
22
#ifdef ST_RELATIME
17536
22
    if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
17537
22
#endif /* ST_RELATIME */
17538
17539
    /* FreeBSD sendfile() constants */
17540
#ifdef SF_NODISKIO
17541
    if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
17542
#endif
17543
    /* is obsolete since the 11.x release */
17544
#ifdef SF_MNOWAIT
17545
    if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
17546
#endif
17547
#ifdef SF_SYNC
17548
    if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
17549
#endif
17550
#ifdef SF_NOCACHE
17551
    if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
17552
#endif
17553
17554
22
#ifdef TFD_NONBLOCK
17555
22
    if (PyModule_AddIntMacro(m, TFD_NONBLOCK)) return -1;
17556
22
#endif
17557
22
#ifdef TFD_CLOEXEC
17558
22
    if (PyModule_AddIntMacro(m, TFD_CLOEXEC)) return -1;
17559
22
#endif
17560
22
#ifdef TFD_TIMER_ABSTIME
17561
22
    if (PyModule_AddIntMacro(m, TFD_TIMER_ABSTIME)) return -1;
17562
22
#endif
17563
22
#ifdef TFD_TIMER_CANCEL_ON_SET
17564
22
    if (PyModule_AddIntMacro(m, TFD_TIMER_CANCEL_ON_SET)) return -1;
17565
22
#endif
17566
17567
    /* constants for posix_fadvise */
17568
22
#ifdef POSIX_FADV_NORMAL
17569
22
    if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
17570
22
#endif
17571
22
#ifdef POSIX_FADV_SEQUENTIAL
17572
22
    if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
17573
22
#endif
17574
22
#ifdef POSIX_FADV_RANDOM
17575
22
    if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
17576
22
#endif
17577
22
#ifdef POSIX_FADV_NOREUSE
17578
22
    if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
17579
22
#endif
17580
22
#ifdef POSIX_FADV_WILLNEED
17581
22
    if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
17582
22
#endif
17583
22
#ifdef POSIX_FADV_DONTNEED
17584
22
    if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
17585
22
#endif
17586
17587
    /* constants for waitid */
17588
22
#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
17589
22
    if (PyModule_AddIntMacro(m, P_PID)) return -1;
17590
22
    if (PyModule_AddIntMacro(m, P_PGID)) return -1;
17591
22
    if (PyModule_AddIntMacro(m, P_ALL)) return -1;
17592
22
#ifdef P_PIDFD
17593
22
    if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
17594
22
#endif
17595
#ifdef PIDFD_NONBLOCK
17596
    if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1;
17597
#endif
17598
22
#endif
17599
22
#ifdef WEXITED
17600
22
    if (PyModule_AddIntMacro(m, WEXITED)) return -1;
17601
22
#endif
17602
22
#ifdef WNOWAIT
17603
22
    if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
17604
22
#endif
17605
22
#ifdef WSTOPPED
17606
22
    if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
17607
22
#endif
17608
22
#ifdef CLD_EXITED
17609
22
    if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
17610
22
#endif
17611
22
#ifdef CLD_KILLED
17612
22
    if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
17613
22
#endif
17614
22
#ifdef CLD_DUMPED
17615
22
    if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
17616
22
#endif
17617
22
#ifdef CLD_TRAPPED
17618
22
    if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
17619
22
#endif
17620
22
#ifdef CLD_STOPPED
17621
22
    if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
17622
22
#endif
17623
22
#ifdef CLD_CONTINUED
17624
22
    if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
17625
22
#endif
17626
17627
    /* constants for lockf */
17628
22
#ifdef F_LOCK
17629
22
    if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
17630
22
#endif
17631
22
#ifdef F_TLOCK
17632
22
    if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
17633
22
#endif
17634
22
#ifdef F_ULOCK
17635
22
    if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
17636
22
#endif
17637
22
#ifdef F_TEST
17638
22
    if (PyModule_AddIntMacro(m, F_TEST)) return -1;
17639
22
#endif
17640
17641
22
#ifdef RWF_DSYNC
17642
22
    if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
17643
22
#endif
17644
22
#ifdef RWF_HIPRI
17645
22
    if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
17646
22
#endif
17647
22
#ifdef RWF_SYNC
17648
22
    if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
17649
22
#endif
17650
22
#ifdef RWF_NOWAIT
17651
22
    if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
17652
22
#endif
17653
22
#ifdef RWF_APPEND
17654
22
    if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
17655
22
#endif
17656
17657
/* constants for splice */
17658
22
#if defined(HAVE_SPLICE) && defined(__linux__)
17659
22
    if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
17660
22
    if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
17661
22
    if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
17662
22
#endif
17663
17664
/* constants for posix_spawn */
17665
22
#ifdef HAVE_POSIX_SPAWN
17666
22
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
17667
22
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
17668
22
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
17669
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
17670
    if (PyModule_AddIntMacro(m, POSIX_SPAWN_CLOSEFROM)) return -1;
17671
#endif
17672
22
#endif
17673
17674
#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
17675
    if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
17676
    if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
17677
    if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
17678
#endif
17679
#ifdef HAVE_SPAWNV
17680
    if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
17681
    if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
17682
#endif
17683
17684
22
#ifdef HAVE_SCHED_H
17685
22
#ifdef SCHED_OTHER
17686
22
    if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
17687
22
#endif
17688
22
#ifdef SCHED_DEADLINE
17689
22
    if (PyModule_AddIntMacro(m, SCHED_DEADLINE)) return -1;
17690
22
#endif
17691
22
#ifdef SCHED_FIFO
17692
22
    if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
17693
22
#endif
17694
22
#ifdef SCHED_NORMAL
17695
22
    if (PyModule_AddIntMacro(m, SCHED_NORMAL)) return -1;
17696
22
#endif
17697
22
#ifdef SCHED_RR
17698
22
    if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
17699
22
#endif
17700
#ifdef SCHED_SPORADIC
17701
    if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
17702
#endif
17703
22
#ifdef SCHED_BATCH
17704
22
    if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
17705
22
#endif
17706
22
#ifdef SCHED_IDLE
17707
22
    if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
17708
22
#endif
17709
22
#ifdef SCHED_RESET_ON_FORK
17710
22
    if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
17711
22
#endif
17712
#ifdef SCHED_SYS
17713
    if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
17714
#endif
17715
#ifdef SCHED_IA
17716
    if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
17717
#endif
17718
#ifdef SCHED_FSS
17719
    if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
17720
#endif
17721
#ifdef SCHED_FX
17722
    if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
17723
#endif
17724
17725
/* constants for namespaces */
17726
22
#if defined(HAVE_SETNS) || defined(HAVE_UNSHARE)
17727
22
#ifdef CLONE_FS
17728
22
    if (PyModule_AddIntMacro(m, CLONE_FS)) return -1;
17729
22
#endif
17730
22
#ifdef CLONE_FILES
17731
22
    if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1;
17732
22
#endif
17733
22
#ifdef CLONE_NEWNS
17734
22
    if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1;
17735
22
#endif
17736
22
#ifdef CLONE_NEWCGROUP
17737
22
    if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1;
17738
22
#endif
17739
22
#ifdef CLONE_NEWUTS
17740
22
    if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1;
17741
22
#endif
17742
22
#ifdef CLONE_NEWIPC
17743
22
    if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1;
17744
22
#endif
17745
22
#ifdef CLONE_NEWUSER
17746
22
    if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1;
17747
22
#endif
17748
22
#ifdef CLONE_NEWPID
17749
22
    if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1;
17750
22
#endif
17751
22
#ifdef CLONE_NEWNET
17752
22
    if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1;
17753
22
#endif
17754
#ifdef CLONE_NEWTIME
17755
    if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1;
17756
#endif
17757
22
#ifdef CLONE_SYSVSEM
17758
22
    if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1;
17759
22
#endif
17760
22
#ifdef CLONE_THREAD
17761
22
    if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1;
17762
22
#endif
17763
22
#ifdef CLONE_SIGHAND
17764
22
    if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1;
17765
22
#endif
17766
22
#ifdef CLONE_VM
17767
22
    if (PyModule_AddIntMacro(m, CLONE_VM)) return -1;
17768
22
#endif
17769
22
#endif
17770
17771
22
#endif
17772
17773
22
#ifdef USE_XATTRS
17774
22
    if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
17775
22
    if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
17776
22
    if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
17777
22
#endif
17778
17779
22
#if HAVE_DECL_RTLD_LAZY
17780
22
    if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
17781
22
#endif
17782
22
#if HAVE_DECL_RTLD_NOW
17783
22
    if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
17784
22
#endif
17785
22
#if HAVE_DECL_RTLD_GLOBAL
17786
22
    if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
17787
22
#endif
17788
22
#if HAVE_DECL_RTLD_LOCAL
17789
22
    if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
17790
22
#endif
17791
22
#if HAVE_DECL_RTLD_NODELETE
17792
22
    if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
17793
22
#endif
17794
22
#if HAVE_DECL_RTLD_NOLOAD
17795
22
    if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
17796
22
#endif
17797
22
#if HAVE_DECL_RTLD_DEEPBIND
17798
22
    if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
17799
22
#endif
17800
#if HAVE_DECL_RTLD_MEMBER
17801
    if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
17802
#endif
17803
17804
22
#ifdef HAVE_GETRANDOM_SYSCALL
17805
22
    if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
17806
22
    if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
17807
22
#endif
17808
22
#ifdef HAVE_MEMFD_CREATE
17809
22
    if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
17810
22
    if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
17811
22
#ifdef MFD_HUGETLB
17812
22
    if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
17813
22
#endif
17814
22
#ifdef MFD_HUGE_SHIFT
17815
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
17816
22
#endif
17817
22
#ifdef MFD_HUGE_MASK
17818
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
17819
22
#endif
17820
22
#ifdef MFD_HUGE_64KB
17821
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
17822
22
#endif
17823
22
#ifdef MFD_HUGE_512KB
17824
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
17825
22
#endif
17826
22
#ifdef MFD_HUGE_1MB
17827
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
17828
22
#endif
17829
22
#ifdef MFD_HUGE_2MB
17830
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
17831
22
#endif
17832
22
#ifdef MFD_HUGE_8MB
17833
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
17834
22
#endif
17835
22
#ifdef MFD_HUGE_16MB
17836
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
17837
22
#endif
17838
22
#ifdef MFD_HUGE_32MB
17839
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
17840
22
#endif
17841
22
#ifdef MFD_HUGE_256MB
17842
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
17843
22
#endif
17844
22
#ifdef MFD_HUGE_512MB
17845
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
17846
22
#endif
17847
22
#ifdef MFD_HUGE_1GB
17848
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
17849
22
#endif
17850
22
#ifdef MFD_HUGE_2GB
17851
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
17852
22
#endif
17853
22
#ifdef MFD_HUGE_16GB
17854
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
17855
22
#endif
17856
22
#endif /* HAVE_MEMFD_CREATE */
17857
17858
22
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
17859
22
    if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
17860
22
#ifdef EFD_NONBLOCK
17861
22
    if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
17862
22
#endif
17863
22
#ifdef EFD_SEMAPHORE
17864
22
    if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
17865
22
#endif
17866
22
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
17867
17868
#if defined(__APPLE__)
17869
    if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
17870
    if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
17871
    if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
17872
    if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
17873
#endif
17874
17875
#ifdef MS_WINDOWS
17876
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
17877
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
17878
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
17879
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
17880
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
17881
#endif
17882
17883
22
    return 0;
17884
22
}
17885
17886
17887
17888
#define PROBE(name, test) \
17889
   static int name(void)  \
17890
374
   {                      \
17891
374
      if (test) {        \
17892
374
          return 1;       \
17893
374
      } else {            \
17894
0
          return 0;       \
17895
0
      }                   \
17896
374
   }
posixmodule.c:probe_faccessat
Line
Count
Source
17890
22
   {                      \
17891
22
      if (test) {        \
17892
22
          return 1;       \
17893
22
      } else {            \
17894
0
          return 0;       \
17895
0
      }                   \
17896
22
   }
posixmodule.c:probe_fchmodat
Line
Count
Source
17890
22
   {                      \
17891
22
      if (test) {        \
17892
22
          return 1;       \
17893
22
      } else {            \
17894
0
          return 0;       \
17895
0
      }                   \
17896
22
   }
posixmodule.c:probe_fchownat
Line
Count
Source
17890
22
   {                      \
17891
22
      if (test) {        \
17892
22
          return 1;       \
17893
22
      } else {            \
17894
0
          return 0;       \
17895
0
      }                   \
17896
22
   }
posixmodule.c:probe_fdopendir
Line
Count
Source
17890
22
   {                      \
17891
22
      if (test) {        \
17892
22
          return 1;       \
17893
22
      } else {            \
17894
0
          return 0;       \
17895
0
      }                   \
17896
22
   }
posixmodule.c:probe_fstatat
Line
Count
Source
17890
22
   {                      \
17891
22
      if (test) {        \
17892
22
          return 1;       \
17893
22
      } else {            \
17894
0
          return 0;       \
17895
0
      }                   \
17896
22
   }
posixmodule.c:probe_futimens
Line
Count
Source
17890
22
   {                      \
17891
22
      if (test) {        \
17892
22
          return 1;       \
17893
22
      } else {            \
17894
0
          return 0;       \
17895
0
      }                   \
17896
22
   }
posixmodule.c:probe_linkat
Line
Count
Source
17890
22
   {                      \
17891
22
      if (test) {        \
17892
22
          return 1;       \
17893
22
      } else {            \
17894
0
          return 0;       \
17895
0
      }                   \
17896
22
   }
posixmodule.c:probe_mkdirat
Line
Count
Source
17890
22
   {                      \
17891
22
      if (test) {        \
17892
22
          return 1;       \
17893
22
      } else {            \
17894
0
          return 0;       \
17895
0
      }                   \
17896
22
   }
posixmodule.c:probe_mkfifoat
Line
Count
Source
17890
22
   {                      \
17891
22
      if (test) {        \
17892
22
          return 1;       \
17893
22
      } else {            \
17894
0
          return 0;       \
17895
0
      }                   \
17896
22
   }
posixmodule.c:probe_mknodat
Line
Count
Source
17890
22
   {                      \
17891
22
      if (test) {        \
17892
22
          return 1;       \
17893
22
      } else {            \
17894
0
          return 0;       \
17895
0
      }                   \
17896
22
   }
posixmodule.c:probe_openat
Line
Count
Source
17890
22
   {                      \
17891
22
      if (test) {        \
17892
22
          return 1;       \
17893
22
      } else {            \
17894
0
          return 0;       \
17895
0
      }                   \
17896
22
   }
posixmodule.c:probe_readlinkat
Line
Count
Source
17890
22
   {                      \
17891
22
      if (test) {        \
17892
22
          return 1;       \
17893
22
      } else {            \
17894
0
          return 0;       \
17895
0
      }                   \
17896
22
   }
posixmodule.c:probe_renameat
Line
Count
Source
17890
22
   {                      \
17891
22
      if (test) {        \
17892
22
          return 1;       \
17893
22
      } else {            \
17894
0
          return 0;       \
17895
0
      }                   \
17896
22
   }
posixmodule.c:probe_symlinkat
Line
Count
Source
17890
22
   {                      \
17891
22
      if (test) {        \
17892
22
          return 1;       \
17893
22
      } else {            \
17894
0
          return 0;       \
17895
0
      }                   \
17896
22
   }
posixmodule.c:probe_unlinkat
Line
Count
Source
17890
22
   {                      \
17891
22
      if (test) {        \
17892
22
          return 1;       \
17893
22
      } else {            \
17894
0
          return 0;       \
17895
0
      }                   \
17896
22
   }
posixmodule.c:probe_utimensat
Line
Count
Source
17890
22
   {                      \
17891
22
      if (test) {        \
17892
22
          return 1;       \
17893
22
      } else {            \
17894
0
          return 0;       \
17895
0
      }                   \
17896
22
   }
posixmodule.c:probe_ptsname_r
Line
Count
Source
17890
22
   {                      \
17891
22
      if (test) {        \
17892
22
          return 1;       \
17893
22
      } else {            \
17894
0
          return 0;       \
17895
0
      }                   \
17896
22
   }
17897
17898
#ifdef HAVE_FSTATAT
17899
PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
17900
#endif
17901
17902
#ifdef HAVE_FACCESSAT
17903
PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
17904
#endif
17905
17906
#ifdef HAVE_FCHMODAT
17907
PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
17908
#endif
17909
17910
#ifdef HAVE_FCHOWNAT
17911
PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
17912
#endif
17913
17914
#ifdef HAVE_LINKAT
17915
PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
17916
#endif
17917
17918
#ifdef HAVE_FDOPENDIR
17919
PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
17920
#endif
17921
17922
#ifdef HAVE_MKDIRAT
17923
PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
17924
#endif
17925
17926
#ifdef HAVE_MKFIFOAT
17927
PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
17928
#endif
17929
17930
#ifdef HAVE_MKNODAT
17931
PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
17932
#endif
17933
17934
#ifdef HAVE_RENAMEAT
17935
PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
17936
#endif
17937
17938
#ifdef HAVE_UNLINKAT
17939
PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
17940
#endif
17941
17942
#ifdef HAVE_OPENAT
17943
PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
17944
#endif
17945
17946
#ifdef HAVE_READLINKAT
17947
PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
17948
#endif
17949
17950
#ifdef HAVE_SYMLINKAT
17951
PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
17952
#endif
17953
17954
#ifdef HAVE_FUTIMENS
17955
PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
17956
#endif
17957
17958
#ifdef HAVE_UTIMENSAT
17959
PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
17960
#endif
17961
17962
#ifdef HAVE_PTSNAME_R
17963
PROBE(probe_ptsname_r, HAVE_PTSNAME_R_RUNTIME)
17964
#endif
17965
17966
17967
17968
static const struct have_function {
17969
    const char * const label;
17970
    int (*probe)(void);
17971
} have_functions[] = {
17972
17973
#ifdef HAVE_EVENTFD
17974
    {"HAVE_EVENTFD", NULL},
17975
#endif
17976
17977
#ifdef HAVE_TIMERFD_CREATE
17978
    {"HAVE_TIMERFD_CREATE", NULL},
17979
#endif
17980
17981
#ifdef HAVE_FACCESSAT
17982
    { "HAVE_FACCESSAT", probe_faccessat },
17983
#endif
17984
17985
#ifdef HAVE_FCHDIR
17986
    { "HAVE_FCHDIR", NULL },
17987
#endif
17988
17989
#ifdef HAVE_FCHMOD
17990
    { "HAVE_FCHMOD", NULL },
17991
#endif
17992
17993
#ifdef HAVE_FCHMODAT
17994
    { "HAVE_FCHMODAT", probe_fchmodat },
17995
#endif
17996
17997
#ifdef HAVE_FCHOWN
17998
    { "HAVE_FCHOWN", NULL },
17999
#endif
18000
18001
#ifdef HAVE_FCHOWNAT
18002
    { "HAVE_FCHOWNAT", probe_fchownat },
18003
#endif
18004
18005
#ifdef HAVE_FEXECVE
18006
    { "HAVE_FEXECVE", NULL },
18007
#endif
18008
18009
#ifdef HAVE_FDOPENDIR
18010
    { "HAVE_FDOPENDIR", probe_fdopendir },
18011
#endif
18012
18013
#ifdef HAVE_FPATHCONF
18014
    { "HAVE_FPATHCONF", NULL },
18015
#endif
18016
18017
#ifdef HAVE_FSTATAT
18018
    { "HAVE_FSTATAT", probe_fstatat },
18019
#endif
18020
18021
#ifdef HAVE_FSTATVFS
18022
    { "HAVE_FSTATVFS", NULL },
18023
#endif
18024
18025
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
18026
    { "HAVE_FTRUNCATE", NULL },
18027
#endif
18028
18029
#ifdef HAVE_FUTIMENS
18030
    { "HAVE_FUTIMENS", probe_futimens },
18031
#endif
18032
18033
#ifdef HAVE_FUTIMES
18034
    { "HAVE_FUTIMES", NULL },
18035
#endif
18036
18037
#ifdef HAVE_FUTIMESAT
18038
    { "HAVE_FUTIMESAT", NULL },
18039
#endif
18040
18041
#ifdef HAVE_LINKAT
18042
    { "HAVE_LINKAT", probe_linkat },
18043
#endif
18044
18045
#ifdef HAVE_LCHFLAGS
18046
    { "HAVE_LCHFLAGS", NULL },
18047
#endif
18048
18049
#ifdef HAVE_LCHMOD
18050
    { "HAVE_LCHMOD", NULL },
18051
#endif
18052
18053
#ifdef HAVE_LCHOWN
18054
    { "HAVE_LCHOWN", NULL },
18055
#endif
18056
18057
#ifdef HAVE_LSTAT
18058
    { "HAVE_LSTAT", NULL },
18059
#endif
18060
18061
#ifdef HAVE_LUTIMES
18062
    { "HAVE_LUTIMES", NULL },
18063
#endif
18064
18065
#ifdef HAVE_MEMFD_CREATE
18066
    { "HAVE_MEMFD_CREATE", NULL },
18067
#endif
18068
18069
#ifdef HAVE_MKDIRAT
18070
    { "HAVE_MKDIRAT", probe_mkdirat },
18071
#endif
18072
18073
#ifdef HAVE_MKFIFOAT
18074
    { "HAVE_MKFIFOAT", probe_mkfifoat },
18075
#endif
18076
18077
#ifdef HAVE_MKNODAT
18078
    { "HAVE_MKNODAT", probe_mknodat },
18079
#endif
18080
18081
#ifdef HAVE_OPENAT
18082
    { "HAVE_OPENAT", probe_openat },
18083
#endif
18084
18085
#ifdef HAVE_READLINKAT
18086
    { "HAVE_READLINKAT", probe_readlinkat },
18087
#endif
18088
18089
#ifdef HAVE_RENAMEAT
18090
    { "HAVE_RENAMEAT", probe_renameat },
18091
#endif
18092
18093
#ifdef HAVE_SYMLINKAT
18094
    { "HAVE_SYMLINKAT", probe_symlinkat },
18095
#endif
18096
18097
#ifdef HAVE_UNLINKAT
18098
    { "HAVE_UNLINKAT", probe_unlinkat },
18099
#endif
18100
18101
#ifdef HAVE_UTIMENSAT
18102
    { "HAVE_UTIMENSAT", probe_utimensat },
18103
#endif
18104
18105
#ifdef HAVE_PTSNAME_R
18106
    { "HAVE_PTSNAME_R", probe_ptsname_r },
18107
#endif
18108
18109
#ifdef MS_WINDOWS
18110
    { "MS_WINDOWS", NULL },
18111
#endif
18112
18113
    { NULL, NULL }
18114
};
18115
18116
18117
static int
18118
posixmodule_exec(PyObject *m)
18119
22
{
18120
22
    _posixstate *state = get_posix_state(m);
18121
18122
22
#if defined(HAVE_PWRITEV)
18123
22
    if (HAVE_PWRITEV_RUNTIME) {} else {
18124
0
        PyObject* dct = PyModule_GetDict(m);
18125
18126
0
        if (dct == NULL) {
18127
0
            return -1;
18128
0
        }
18129
18130
0
        if (PyDict_PopString(dct, "pwritev", NULL) < 0) {
18131
0
            return -1;
18132
0
        }
18133
0
        if (PyDict_PopString(dct, "preadv", NULL) < 0) {
18134
0
            return -1;
18135
0
        }
18136
0
    }
18137
22
#endif
18138
18139
    /* Initialize environ dictionary */
18140
22
    if (PyModule_Add(m, "environ", convertenviron()) != 0) {
18141
0
        return -1;
18142
0
    }
18143
18144
22
    if (all_ins(m))
18145
0
        return -1;
18146
18147
22
    if (setup_confname_tables(m))
18148
0
        return -1;
18149
18150
22
    if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) {
18151
0
        return -1;
18152
0
    }
18153
18154
22
#if defined(HAVE_WAITID)
18155
22
    waitid_result_desc.name = MODNAME ".waitid_result";
18156
22
    state->WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
18157
22
    if (PyModule_AddObjectRef(m, "waitid_result", state->WaitidResultType) < 0) {
18158
0
        return -1;
18159
0
    }
18160
22
#endif
18161
18162
22
    stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
18163
22
    stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
18164
22
    stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
18165
22
    stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
18166
22
    state->StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
18167
22
    if (PyModule_AddObjectRef(m, "stat_result", state->StatResultType) < 0) {
18168
0
        return -1;
18169
0
    }
18170
22
    state->statresult_new_orig = ((PyTypeObject *)state->StatResultType)->tp_new;
18171
22
    ((PyTypeObject *)state->StatResultType)->tp_new = statresult_new;
18172
18173
22
    statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
18174
22
    state->StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
18175
22
    if (PyModule_AddObjectRef(m, "statvfs_result", state->StatVFSResultType) < 0) {
18176
0
        return -1;
18177
0
    }
18178
18179
22
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
18180
22
    sched_param_desc.name = MODNAME ".sched_param";
18181
22
    state->SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
18182
22
    if (PyModule_AddObjectRef(m, "sched_param", state->SchedParamType) < 0) {
18183
0
        return -1;
18184
0
    }
18185
22
    ((PyTypeObject *)state->SchedParamType)->tp_new = os_sched_param;
18186
22
    if (_PyType_AddMethod((PyTypeObject *)state->SchedParamType,
18187
22
                          &os_sched_param_reduce_method) < 0)
18188
0
    {
18189
0
        return -1;
18190
0
    }
18191
22
    PyType_Modified((PyTypeObject *)state->SchedParamType);
18192
22
#endif
18193
18194
    /* initialize TerminalSize_info */
18195
22
    state->TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
18196
22
    if (PyModule_AddObjectRef(m, "terminal_size", state->TerminalSizeType) < 0) {
18197
0
        return -1;
18198
0
    }
18199
18200
    /* initialize scandir types */
18201
22
    PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
18202
22
    if (ScandirIteratorType == NULL) {
18203
0
        return -1;
18204
0
    }
18205
22
    state->ScandirIteratorType = ScandirIteratorType;
18206
18207
22
    state->DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
18208
22
    if (PyModule_AddObjectRef(m, "DirEntry", state->DirEntryType) < 0) {
18209
0
        return -1;
18210
0
    }
18211
18212
22
    times_result_desc.name = MODNAME ".times_result";
18213
22
    state->TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
18214
22
    if (PyModule_AddObjectRef(m, "times_result", state->TimesResultType) < 0) {
18215
0
        return -1;
18216
0
    }
18217
18218
22
    state->UnameResultType = (PyObject *)PyStructSequence_NewType(&uname_result_desc);
18219
22
    if (PyModule_AddObjectRef(m, "uname_result", state->UnameResultType) < 0) {
18220
0
        return -1;
18221
0
    }
18222
18223
22
    if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
18224
0
        return -1;
18225
22
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
18226
22
    state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
18227
22
    if (state->struct_rusage == NULL)
18228
0
        return -1;
18229
22
#endif
18230
22
    state->st_mode = PyUnicode_InternFromString("st_mode");
18231
22
    if (state->st_mode == NULL)
18232
0
        return -1;
18233
18234
    /* suppress "function not used" warnings */
18235
22
    {
18236
22
    int ignored;
18237
22
    fd_specified("", -1);
18238
22
    follow_symlinks_specified("", 1);
18239
22
    dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
18240
22
    dir_fd_converter(Py_None, &ignored);
18241
22
    dir_fd_unavailable(Py_None, &ignored);
18242
22
    }
18243
18244
    /*
18245
     * provide list of locally available functions
18246
     * so os.py can populate support_* lists
18247
     */
18248
22
    PyObject *list = PyList_New(0);
18249
22
    if (!list) {
18250
0
        return -1;
18251
0
    }
18252
726
    for (const struct have_function *trace = have_functions; trace->label; trace++) {
18253
704
        PyObject *unicode;
18254
704
        if (trace->probe && !trace->probe()) continue;
18255
704
        unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
18256
704
        if (!unicode)
18257
0
            return -1;
18258
704
        if (PyList_Append(list, unicode))
18259
0
            return -1;
18260
704
        Py_DECREF(unicode);
18261
704
    }
18262
18263
22
#ifndef MS_WINDOWS
18264
22
    if (_Py_GetTicksPerSecond(&state->ticks_per_second) < 0) {
18265
0
        PyErr_SetString(PyExc_RuntimeError,
18266
0
                        "cannot read ticks_per_second");
18267
0
        return -1;
18268
0
    }
18269
22
    assert(state->ticks_per_second >= 1);
18270
22
#endif
18271
18272
22
    return PyModule_Add(m, "_have_functions", list);
18273
22
}
18274
18275
18276
static PyModuleDef_Slot posixmodile_slots[] = {
18277
    {Py_mod_exec, posixmodule_exec},
18278
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
18279
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
18280
    {0, NULL}
18281
};
18282
18283
static struct PyModuleDef posixmodule = {
18284
    PyModuleDef_HEAD_INIT,
18285
    .m_name = MODNAME,
18286
    .m_doc = posix__doc__,
18287
    .m_size = sizeof(_posixstate),
18288
    .m_methods = posix_methods,
18289
    .m_slots = posixmodile_slots,
18290
    .m_traverse = _posix_traverse,
18291
    .m_clear = _posix_clear,
18292
    .m_free = _posix_free,
18293
};
18294
18295
PyMODINIT_FUNC
18296
INITFUNC(void)
18297
22
{
18298
22
    return PyModuleDef_Init(&posixmodule);
18299
22
}