Coverage Report

Created: 2025-07-04 06:49

/src/cpython/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
7.07k
#  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
4.98k
#  define STAT stat
406
0
#  define LSTAT lstat
407
0
#  define FSTAT fstat
408
4.98k
#  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
16
#  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
48
#  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
6
{
762
6
    if (func == NULL)  /* nothing to register? do nothing. */
763
4
        return 0;
764
2
    if (*lst == NULL) {
765
2
        *lst = PyList_New(0);
766
2
        if (*lst == NULL)
767
0
            return -1;
768
2
    }
769
2
    return PyList_Append(*lst, func);
770
2
}
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
4.70k
{
799
4.70k
    if (uid == (uid_t)-1)
800
0
        return PyLong_FromLong(-1);
801
4.70k
    return PyLong_FromUnsignedLong(uid);
802
4.70k
}
803
804
PyObject *
805
_PyLong_FromGid(gid_t gid)
806
4.70k
{
807
4.70k
    if (gid == (gid_t)-1)
808
0
        return PyLong_FromLong(-1);
809
4.70k
    return PyLong_FromUnsignedLong(gid);
810
4.70k
}
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
4.67k
{
1030
4.67k
#ifdef NODEV
1031
4.67k
    if (dev == NODEV) {
1032
0
        return PyLong_FromLongLong((long long)dev);
1033
0
    }
1034
4.67k
#endif
1035
4.67k
    return PyLong_FromUnsignedLongLong((unsigned long long)dev);
1036
4.67k
}
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
21.7k
#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
32
{
1138
32
    if (o == Py_None) {
1139
32
        *(int *)p = DEFAULT_DIR_FD;
1140
32
        return 1;
1141
32
    }
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
32
}
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
24.2k
{
1183
24.2k
    void *state = _PyModule_GetState(module);
1184
24.2k
    assert(state != NULL);
1185
24.2k
    return (_posixstate *)state;
1186
24.2k
}
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
5.82k
    {function_name, argument_name, nullable, nonstrict, make_wide, \
1305
5.82k
     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
5.74k
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 0, \
1315
5.74k
                      suppress_value_error, allow_fd)
1316
#endif
1317
1318
static void
1319
path_cleanup(path_t *path)
1320
5.82k
{
1321
5.82k
    wchar_t *wide = (wchar_t *)path->wide;
1322
5.82k
    path->wide = NULL;
1323
5.82k
    PyMem_Free(wide);
1324
5.82k
    Py_CLEAR(path->object);
1325
5.82k
    Py_CLEAR(path->cleanup);
1326
5.82k
}
1327
1328
static int
1329
path_converter(PyObject *o, void *p)
1330
5.82k
{
1331
5.82k
    path_t *path = (path_t *)p;
1332
5.82k
    PyObject *bytes = NULL;
1333
5.82k
    Py_ssize_t length = 0;
1334
5.82k
    int is_index, is_bytes, is_unicode;
1335
5.82k
    const char *narrow;
1336
5.82k
    PyObject *wo = NULL;
1337
5.82k
    wchar_t *wide = NULL;
1338
1339
5.82k
#define FORMAT_EXCEPTION(exc, fmt) \
1340
5.82k
    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
5.82k
    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
5.82k
    path->object = path->cleanup = NULL;
1353
    /* path->object owns a reference to the original object */
1354
5.82k
    Py_INCREF(o);
1355
1356
5.82k
    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
5.82k
    is_index = path->allow_fd && PyIndex_Check(o);
1366
5.82k
    is_bytes = PyBytes_Check(o);
1367
5.82k
    is_unicode = PyUnicode_Check(o);
1368
1369
5.82k
    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
5.82k
    if (is_unicode) {
1402
5.82k
        if (path->make_wide) {
1403
80
            wide = PyUnicode_AsWideCharString(o, &length);
1404
80
            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
80
            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
80
            path->wide = wide;
1420
80
            path->narrow = NULL;
1421
80
            path->fd = -1;
1422
80
            wide = NULL;
1423
80
            goto success_exit;
1424
80
        }
1425
5.74k
        bytes = PyUnicode_EncodeFSDefault(o);
1426
5.74k
        if (!bytes) {
1427
0
            goto error_exit;
1428
0
        }
1429
5.74k
    }
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
5.74k
    length = PyBytes_GET_SIZE(bytes);
1457
5.74k
    narrow = PyBytes_AS_STRING(bytes);
1458
5.74k
    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
5.74k
    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
5.74k
    else {
1491
5.74k
        path->wide = NULL;
1492
5.74k
        path->narrow = narrow;
1493
5.74k
        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
5.74k
        else {
1499
5.74k
            path->cleanup = bytes;
1500
5.74k
        }
1501
5.74k
    }
1502
5.74k
    path->fd = -1;
1503
1504
5.82k
 success_exit:
1505
5.82k
    path->value_error = 0;
1506
5.82k
    path->length = length;
1507
5.82k
    path->object = o;
1508
5.82k
    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
16
{
1542
16
    int dir_fd;
1543
16
    if (!dir_fd_converter(o, &dir_fd))
1544
0
        return 0;
1545
16
    if (dir_fd != DEFAULT_DIR_FD) {
1546
0
        argument_unavailable_error(NULL, "dir_fd");
1547
0
        return 0;
1548
0
    }
1549
16
    *(int *)p = dir_fd;
1550
16
    return 1;
1551
16
}
1552
1553
static int
1554
fd_specified(const char *function_name, int fd)
1555
16
{
1556
16
    if (fd == -1)
1557
16
        return 0;
1558
1559
0
    argument_unavailable_error(function_name, "fd");
1560
0
    return 1;
1561
16
}
1562
1563
static int
1564
follow_symlinks_specified(const char *function_name, int follow_symlinks)
1565
16
{
1566
16
    if (follow_symlinks)
1567
16
        return 0;
1568
1569
0
    argument_unavailable_error(function_name, "follow_symlinks");
1570
0
    return 1;
1571
16
}
1572
1573
static int
1574
path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1575
4.98k
{
1576
4.98k
    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
4.98k
    return 0;
1583
4.98k
}
1584
1585
static int
1586
dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1587
4.98k
{
1588
4.98k
    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
4.98k
    return 0;
1595
4.98k
}
1596
1597
static int
1598
fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1599
                               int follow_symlinks)
1600
4.98k
{
1601
4.98k
    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
4.98k
    return 0;
1608
4.98k
}
1609
1610
static int
1611
dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1612
                                   int follow_symlinks)
1613
16
{
1614
16
    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
16
    return 0;
1621
16
}
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
16
{
1741
16
    PyObject *d;
1742
#ifdef MS_WINDOWS
1743
    wchar_t **e;
1744
#else
1745
16
    char **e;
1746
16
#endif
1747
1748
16
    d = PyDict_New();
1749
16
    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
16
    e = environ;
1763
16
#endif
1764
16
    if (e == NULL)
1765
0
        return d;
1766
592
    for (; *e != NULL; e++) {
1767
576
        PyObject *k;
1768
576
        PyObject *v;
1769
#ifdef MS_WINDOWS
1770
        const wchar_t *p = wcschr(*e, L'=');
1771
#else
1772
576
        const char *p = strchr(*e, '=');
1773
576
#endif
1774
576
        if (p == NULL)
1775
0
            continue;
1776
#ifdef MS_WINDOWS
1777
        k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1778
#else
1779
576
        k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1780
576
#endif
1781
576
        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
576
        v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1789
576
#endif
1790
576
        if (v == NULL) {
1791
0
            Py_DECREF(k);
1792
0
            Py_DECREF(d);
1793
0
            return NULL;
1794
0
        }
1795
576
        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
576
        Py_DECREF(k);
1802
576
        Py_DECREF(v);
1803
576
    }
1804
16
    return d;
1805
16
}
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
305
{
1856
305
    return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1857
305
}
1858
1859
static PyObject *
1860
path_object_error(PyObject *path)
1861
305
{
1862
#ifdef MS_WINDOWS
1863
    return PyErr_SetExcFromWindowsErrWithFilenameObject(
1864
                PyExc_OSError, 0, path);
1865
#else
1866
305
    return posix_path_object_error(path);
1867
305
#endif
1868
305
}
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
305
{
1884
305
    return path_object_error(path->object);
1885
305
}
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
5.58k
{
2559
5.58k
    _posixstate *state = get_posix_state(module);
2560
5.58k
    Py_VISIT(state->billion);
2561
5.58k
    Py_VISIT(state->DirEntryType);
2562
5.58k
    Py_VISIT(state->ScandirIteratorType);
2563
5.58k
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2564
5.58k
    Py_VISIT(state->SchedParamType);
2565
5.58k
#endif
2566
5.58k
    Py_VISIT(state->StatResultType);
2567
5.58k
    Py_VISIT(state->StatVFSResultType);
2568
5.58k
    Py_VISIT(state->TerminalSizeType);
2569
5.58k
    Py_VISIT(state->TimesResultType);
2570
5.58k
    Py_VISIT(state->UnameResultType);
2571
5.58k
#if defined(HAVE_WAITID)
2572
5.58k
    Py_VISIT(state->WaitidResultType);
2573
5.58k
#endif
2574
5.58k
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2575
5.58k
    Py_VISIT(state->struct_rusage);
2576
5.58k
#endif
2577
5.58k
    Py_VISIT(state->st_mode);
2578
5.58k
    return 0;
2579
5.58k
}
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
14.0k
{
2590
14.0k
    assert(!PyErr_Occurred());
2591
2592
14.0k
    int res = -1;
2593
14.0k
    PyObject *s_in_ns = NULL;
2594
14.0k
    PyObject *ns_total = NULL;
2595
14.0k
    PyObject *float_s = NULL;
2596
2597
14.0k
    PyObject *s = _PyLong_FromTime_t(sec);
2598
14.0k
    PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2599
14.0k
    if (!(s && ns_fractional)) {
2600
0
        goto exit;
2601
0
    }
2602
2603
14.0k
    s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
2604
14.0k
    if (!s_in_ns) {
2605
0
        goto exit;
2606
0
    }
2607
2608
14.0k
    ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2609
14.0k
    if (!ns_total)
2610
0
        goto exit;
2611
2612
14.0k
    float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2613
14.0k
    if (!float_s) {
2614
0
        goto exit;
2615
0
    }
2616
2617
14.0k
    if (s_index >= 0) {
2618
14.0k
        PyStructSequence_SET_ITEM(v, s_index, s);
2619
14.0k
        s = NULL;
2620
14.0k
    }
2621
14.0k
    if (f_index >= 0) {
2622
14.0k
        PyStructSequence_SET_ITEM(v, f_index, float_s);
2623
14.0k
        float_s = NULL;
2624
14.0k
    }
2625
14.0k
    if (ns_index >= 0) {
2626
14.0k
        PyStructSequence_SET_ITEM(v, ns_index, ns_total);
2627
14.0k
        ns_total = NULL;
2628
14.0k
    }
2629
2630
14.0k
    assert(!PyErr_Occurred());
2631
14.0k
    res = 0;
2632
2633
14.0k
exit:
2634
14.0k
    Py_XDECREF(s);
2635
14.0k
    Py_XDECREF(ns_fractional);
2636
14.0k
    Py_XDECREF(s_in_ns);
2637
14.0k
    Py_XDECREF(ns_total);
2638
14.0k
    Py_XDECREF(float_s);
2639
14.0k
    return res;
2640
14.0k
}
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
4.67k
{
2674
4.67k
    assert(!PyErr_Occurred());
2675
2676
4.67k
    PyObject *StatResultType = get_posix_state(module)->StatResultType;
2677
4.67k
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2678
4.67k
    if (v == NULL) {
2679
0
        return NULL;
2680
0
    }
2681
2682
4.67k
#define SET_ITEM(pos, expr) \
2683
46.7k
    do { \
2684
46.7k
        PyObject *obj = (expr); \
2685
46.7k
        if (obj == NULL) { \
2686
0
            goto error; \
2687
0
        } \
2688
46.7k
        PyStructSequence_SET_ITEM(v, (pos), obj); \
2689
46.7k
    } while (0)
2690
2691
4.67k
    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
4.67k
    static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2697
4.67k
                  "stat.st_ino is larger than unsigned long long");
2698
4.67k
    SET_ITEM(1, PyLong_FromUnsignedLongLong(st->st_ino));
2699
4.67k
    SET_ITEM(2, _PyLong_FromDev(st->st_dev));
2700
4.67k
#endif
2701
4.67k
    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
4.67k
    SET_ITEM(4, _PyLong_FromUid(st->st_uid));
2707
4.67k
    SET_ITEM(5, _PyLong_FromGid(st->st_gid));
2708
4.67k
#endif
2709
4.67k
    static_assert(sizeof(long long) >= sizeof(st->st_size),
2710
4.67k
                  "stat.st_size is larger than long long");
2711
4.67k
    SET_ITEM(6, PyLong_FromLongLong(st->st_size));
2712
2713
    // Set st_atime, st_mtime and st_ctime
2714
4.67k
    unsigned long ansec, mnsec, cnsec;
2715
4.67k
#if defined(HAVE_STAT_TV_NSEC)
2716
4.67k
    ansec = st->st_atim.tv_nsec;
2717
4.67k
    mnsec = st->st_mtim.tv_nsec;
2718
4.67k
    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
4.67k
    if (fill_time(module, v, 7, 10, 13, st->st_atime, ansec) < 0) {
2731
0
        goto error;
2732
0
    }
2733
4.67k
    if (fill_time(module, v, 8, 11, 14, st->st_mtime, mnsec) < 0) {
2734
0
        goto error;
2735
0
    }
2736
4.67k
    if (fill_time(module, v, 9, 12, 15, st->st_ctime, cnsec) < 0) {
2737
0
        goto error;
2738
0
    }
2739
2740
4.67k
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2741
4.67k
    SET_ITEM(ST_BLKSIZE_IDX, PyLong_FromLong((long)st->st_blksize));
2742
4.67k
#endif
2743
4.67k
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2744
4.67k
    SET_ITEM(ST_BLOCKS_IDX, PyLong_FromLong((long)st->st_blocks));
2745
4.67k
#endif
2746
4.67k
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2747
4.67k
    SET_ITEM(ST_RDEV_IDX, PyLong_FromLong((long)st->st_rdev));
2748
4.67k
#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
4.67k
    assert(!PyErr_Occurred());
2784
4.67k
    return v;
2785
2786
0
error:
2787
0
    Py_DECREF(v);
2788
0
    return NULL;
2789
2790
4.67k
#undef SET_ITEM
2791
4.67k
}
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
4.98k
{
2800
4.98k
    STRUCT_STAT st;
2801
4.98k
    int result;
2802
2803
4.98k
#ifdef HAVE_FSTATAT
2804
4.98k
    int fstatat_unavailable = 0;
2805
4.98k
#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
4.98k
    if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2813
4.98k
        dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2814
4.98k
        fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2815
0
        return NULL;
2816
2817
4.98k
    Py_BEGIN_ALLOW_THREADS
2818
4.98k
    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
4.98k
    else
2827
4.98k
#if defined(HAVE_LSTAT)
2828
4.98k
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2829
0
        result = LSTAT(path->narrow, &st);
2830
4.98k
    else
2831
4.98k
#endif /* HAVE_LSTAT */
2832
4.98k
#ifdef HAVE_FSTATAT
2833
4.98k
    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
4.98k
#endif /* HAVE_FSTATAT */
2843
4.98k
        result = STAT(path->narrow, &st);
2844
4.98k
#endif /* MS_WINDOWS */
2845
4.98k
    Py_END_ALLOW_THREADS
2846
2847
4.98k
#ifdef HAVE_FSTATAT
2848
4.98k
    if (fstatat_unavailable) {
2849
0
        argument_unavailable_error("stat", "dir_fd");
2850
0
        return NULL;
2851
0
    }
2852
4.98k
#endif
2853
2854
4.98k
    if (result != 0) {
2855
305
        return path_error(path);
2856
305
    }
2857
2858
4.67k
    return _pystat_fromstructstat(module, &st);
2859
4.98k
}
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
4.98k
{
3236
4.98k
    return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
3237
4.98k
}
3238
3239
3240
/*[clinic input]
3241
os.lstat
3242
3243
    path : path_t
3244
3245
    *
3246
3247
    dir_fd : dir_fd(requires='fstatat') = None
3248
3249
Perform a stat system call on the given path, without following symbolic links.
3250
3251
Like stat(), but do not follow symbolic links.
3252
Equivalent to stat(path, follow_symlinks=False).
3253
[clinic start generated code]*/
3254
3255
static PyObject *
3256
os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
3257
/*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
3258
0
{
3259
0
    int follow_symlinks = 0;
3260
0
    return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
3261
0
}
3262
3263
3264
/*[clinic input]
3265
os.access -> bool
3266
3267
    path: path_t
3268
        Path to be tested; can be string, bytes, or a path-like object.
3269
3270
    mode: int
3271
        Operating-system mode bitfield.  Can be F_OK to test existence,
3272
        or the inclusive-OR of R_OK, W_OK, and X_OK.
3273
3274
    *
3275
3276
    dir_fd : dir_fd(requires='faccessat') = None
3277
        If not None, it should be a file descriptor open to a directory,
3278
        and path should be relative; path will then be relative to that
3279
        directory.
3280
3281
    effective_ids: bool = False
3282
        If True, access will use the effective uid/gid instead of
3283
        the real uid/gid.
3284
3285
    follow_symlinks: bool = True
3286
        If False, and the last element of the path is a symbolic link,
3287
        access will examine the symbolic link itself instead of the file
3288
        the link points to.
3289
3290
Use the real uid/gid to test for access to a path.
3291
3292
{parameters}
3293
dir_fd, effective_ids, and follow_symlinks may not be implemented
3294
  on your platform.  If they are unavailable, using them will raise a
3295
  NotImplementedError.
3296
3297
Note that most operations will use the effective uid/gid, therefore this
3298
  routine can be used in a suid/sgid environment to test if the invoking user
3299
  has the specified access to the path.
3300
3301
[clinic start generated code]*/
3302
3303
static int
3304
os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3305
               int effective_ids, int follow_symlinks)
3306
/*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/
3307
0
{
3308
0
    int return_value;
3309
3310
#ifdef MS_WINDOWS
3311
    DWORD attr;
3312
#else
3313
0
    int result;
3314
0
#endif
3315
3316
0
#ifdef HAVE_FACCESSAT
3317
0
    int faccessat_unavailable = 0;
3318
0
#endif
3319
3320
#ifndef HAVE_FACCESSAT
3321
    if (follow_symlinks_specified("access", follow_symlinks))
3322
        return -1;
3323
3324
    if (effective_ids) {
3325
        argument_unavailable_error("access", "effective_ids");
3326
        return -1;
3327
    }
3328
#endif
3329
3330
#ifdef MS_WINDOWS
3331
    Py_BEGIN_ALLOW_THREADS
3332
    attr = GetFileAttributesW(path->wide);
3333
    Py_END_ALLOW_THREADS
3334
3335
    /*
3336
     * Access is possible if
3337
     *   * we didn't get a -1, and
3338
     *     * write access wasn't requested,
3339
     *     * or the file isn't read-only,
3340
     *     * or it's a directory.
3341
     * (Directories cannot be read-only on Windows.)
3342
    */
3343
    return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
3344
            (!(mode & 2) ||
3345
            !(attr & FILE_ATTRIBUTE_READONLY) ||
3346
            (attr & FILE_ATTRIBUTE_DIRECTORY));
3347
#else
3348
3349
0
    Py_BEGIN_ALLOW_THREADS
3350
0
#ifdef HAVE_FACCESSAT
3351
0
    if ((dir_fd != DEFAULT_DIR_FD) ||
3352
0
        effective_ids ||
3353
0
        !follow_symlinks) {
3354
3355
0
        if (HAVE_FACCESSAT_RUNTIME) {
3356
0
            int flags = 0;
3357
0
            if (!follow_symlinks)
3358
0
                flags |= AT_SYMLINK_NOFOLLOW;
3359
0
            if (effective_ids)
3360
0
                flags |= AT_EACCESS;
3361
0
            result = faccessat(dir_fd, path->narrow, mode, flags);
3362
0
        } else {
3363
0
            faccessat_unavailable = 1;
3364
0
        }
3365
0
    }
3366
0
    else
3367
0
#endif
3368
0
        result = access(path->narrow, mode);
3369
0
    Py_END_ALLOW_THREADS
3370
3371
0
#ifdef HAVE_FACCESSAT
3372
0
    if (faccessat_unavailable) {
3373
0
        if (dir_fd != DEFAULT_DIR_FD) {
3374
0
            argument_unavailable_error("access", "dir_fd");
3375
0
            return -1;
3376
0
        }
3377
0
        if (follow_symlinks_specified("access", follow_symlinks))
3378
0
            return -1;
3379
3380
0
        if (effective_ids) {
3381
0
            argument_unavailable_error("access", "effective_ids");
3382
0
            return -1;
3383
0
        }
3384
        /* should be unreachable */
3385
0
        return -1;
3386
0
    }
3387
0
#endif
3388
0
    return_value = !result;
3389
0
#endif
3390
3391
0
    return return_value;
3392
0
}
3393
3394
#ifndef F_OK
3395
#define F_OK 0
3396
#endif
3397
#ifndef R_OK
3398
#define R_OK 4
3399
#endif
3400
#ifndef W_OK
3401
#define W_OK 2
3402
#endif
3403
#ifndef X_OK
3404
#define X_OK 1
3405
#endif
3406
3407
3408
#ifdef HAVE_TTYNAME_R
3409
/*[clinic input]
3410
os.ttyname
3411
3412
    fd: int
3413
        Integer file descriptor handle.
3414
3415
    /
3416
3417
Return the name of the terminal device connected to 'fd'.
3418
[clinic start generated code]*/
3419
3420
static PyObject *
3421
os_ttyname_impl(PyObject *module, int fd)
3422
/*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3423
0
{
3424
3425
0
    long size = sysconf(_SC_TTY_NAME_MAX);
3426
0
    if (size == -1) {
3427
0
        return posix_error();
3428
0
    }
3429
0
    char *buffer = (char *)PyMem_RawMalloc(size);
3430
0
    if (buffer == NULL) {
3431
0
        return PyErr_NoMemory();
3432
0
    }
3433
0
    int ret = ttyname_r(fd, buffer, size);
3434
0
    if (ret != 0) {
3435
0
        PyMem_RawFree(buffer);
3436
0
        errno = ret;
3437
0
        return posix_error();
3438
0
    }
3439
0
    PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3440
0
    PyMem_RawFree(buffer);
3441
0
    return res;
3442
0
}
3443
#endif
3444
3445
#ifdef HAVE_CTERMID
3446
/*[clinic input]
3447
os.ctermid
3448
3449
Return the name of the controlling terminal for this process.
3450
[clinic start generated code]*/
3451
3452
static PyObject *
3453
os_ctermid_impl(PyObject *module)
3454
/*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3455
0
{
3456
0
    char *ret;
3457
0
    char buffer[L_ctermid];
3458
3459
#ifdef USE_CTERMID_R
3460
    ret = ctermid_r(buffer);
3461
#else
3462
0
    ret = ctermid(buffer);
3463
0
#endif
3464
0
    if (ret == NULL)
3465
0
        return posix_error();
3466
0
    return PyUnicode_DecodeFSDefault(buffer);
3467
0
}
3468
#endif /* HAVE_CTERMID */
3469
3470
3471
/*[clinic input]
3472
os.chdir
3473
3474
    path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3475
3476
Change the current working directory to the specified path.
3477
3478
path may always be specified as a string.
3479
On some platforms, path may also be specified as an open file descriptor.
3480
  If this functionality is unavailable, using it raises an exception.
3481
[clinic start generated code]*/
3482
3483
static PyObject *
3484
os_chdir_impl(PyObject *module, path_t *path)
3485
/*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
3486
0
{
3487
0
    int result;
3488
3489
0
    if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3490
0
        return NULL;
3491
0
    }
3492
3493
0
    Py_BEGIN_ALLOW_THREADS
3494
#ifdef MS_WINDOWS
3495
    /* on unix, success = 0, on windows, success = !0 */
3496
    result = !win32_wchdir(path->wide);
3497
#else
3498
0
#ifdef HAVE_FCHDIR
3499
0
    if (path->fd != -1)
3500
0
        result = fchdir(path->fd);
3501
0
    else
3502
0
#endif
3503
0
        result = chdir(path->narrow);
3504
0
#endif
3505
0
    Py_END_ALLOW_THREADS
3506
3507
0
    if (result) {
3508
0
        return path_error(path);
3509
0
    }
3510
3511
0
    Py_RETURN_NONE;
3512
0
}
3513
3514
3515
#ifdef HAVE_FCHDIR
3516
/*[clinic input]
3517
os.fchdir
3518
3519
    fd: fildes
3520
3521
Change to the directory of the given file descriptor.
3522
3523
fd must be opened on a directory, not a file.
3524
Equivalent to os.chdir(fd).
3525
3526
[clinic start generated code]*/
3527
3528
static PyObject *
3529
os_fchdir_impl(PyObject *module, int fd)
3530
/*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3531
0
{
3532
0
    if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3533
0
        return NULL;
3534
0
    }
3535
0
    return posix_fildes_fd(fd, fchdir);
3536
0
}
3537
#endif /* HAVE_FCHDIR */
3538
3539
#ifdef MS_WINDOWS
3540
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 0
3541
#else
3542
0
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 1
3543
#endif
3544
3545
#ifdef MS_WINDOWS
3546
static int
3547
win32_lchmod(LPCWSTR path, int mode)
3548
{
3549
    DWORD attr = GetFileAttributesW(path);
3550
    if (attr == INVALID_FILE_ATTRIBUTES) {
3551
        return 0;
3552
    }
3553
    if (mode & _S_IWRITE) {
3554
        attr &= ~FILE_ATTRIBUTE_READONLY;
3555
    }
3556
    else {
3557
        attr |= FILE_ATTRIBUTE_READONLY;
3558
    }
3559
    return SetFileAttributesW(path, attr);
3560
}
3561
3562
static int
3563
win32_hchmod(HANDLE hfile, int mode)
3564
{
3565
    FILE_BASIC_INFO info;
3566
    if (!GetFileInformationByHandleEx(hfile, FileBasicInfo,
3567
                                      &info, sizeof(info)))
3568
    {
3569
        return 0;
3570
    }
3571
    if (mode & _S_IWRITE) {
3572
        info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
3573
    }
3574
    else {
3575
        info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
3576
    }
3577
    return SetFileInformationByHandle(hfile, FileBasicInfo,
3578
                                      &info, sizeof(info));
3579
}
3580
3581
static int
3582
win32_fchmod(int fd, int mode)
3583
{
3584
    HANDLE hfile = _Py_get_osfhandle_noraise(fd);
3585
    if (hfile == INVALID_HANDLE_VALUE) {
3586
        SetLastError(ERROR_INVALID_HANDLE);
3587
        return 0;
3588
    }
3589
    return win32_hchmod(hfile, mode);
3590
}
3591
3592
#endif /* MS_WINDOWS */
3593
3594
/*[clinic input]
3595
os.chmod
3596
3597
    path: path_t(allow_fd='PATH_HAVE_FCHMOD')
3598
        Path to be modified.  May always be specified as a str, bytes, or a path-like object.
3599
        On some platforms, path may also be specified as an open file descriptor.
3600
        If this functionality is unavailable, using it raises an exception.
3601
3602
    mode: int
3603
        Operating-system mode bitfield.
3604
        Be careful when using number literals for *mode*. The conventional UNIX notation for
3605
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
3606
        Python.
3607
3608
    *
3609
3610
    dir_fd : dir_fd(requires='fchmodat') = None
3611
        If not None, it should be a file descriptor open to a directory,
3612
        and path should be relative; path will then be relative to that
3613
        directory.
3614
3615
    follow_symlinks: bool(c_default="CHMOD_DEFAULT_FOLLOW_SYMLINKS", \
3616
                          py_default="(os.name != 'nt')") = CHMOD_DEFAULT_FOLLOW_SYMLINKS
3617
        If False, and the last element of the path is a symbolic link,
3618
        chmod will modify the symbolic link itself instead of the file
3619
        the link points to.
3620
3621
Change the access permissions of a file.
3622
3623
It is an error to use dir_fd or follow_symlinks when specifying path as
3624
  an open file descriptor.
3625
dir_fd and follow_symlinks may not be implemented on your platform.
3626
  If they are unavailable, using them will raise a NotImplementedError.
3627
3628
[clinic start generated code]*/
3629
3630
static PyObject *
3631
os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3632
              int follow_symlinks)
3633
/*[clinic end generated code: output=5cf6a94915cc7bff input=fcf115d174b9f3d8]*/
3634
0
{
3635
0
    int result;
3636
3637
0
#ifdef HAVE_FCHMODAT
3638
0
    int fchmodat_nofollow_unsupported = 0;
3639
0
    int fchmodat_unsupported = 0;
3640
0
#endif
3641
3642
#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD) || defined(MS_WINDOWS))
3643
    if (follow_symlinks_specified("chmod", follow_symlinks))
3644
        return NULL;
3645
#endif
3646
3647
0
    if (PySys_Audit("os.chmod", "Oii", path->object, mode,
3648
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3649
0
        return NULL;
3650
0
    }
3651
3652
#ifdef MS_WINDOWS
3653
    result = 0;
3654
    Py_BEGIN_ALLOW_THREADS
3655
    if (path->fd != -1) {
3656
        result = win32_fchmod(path->fd, mode);
3657
    }
3658
    else if (follow_symlinks) {
3659
        HANDLE hfile = CreateFileW(path->wide,
3660
                                   FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
3661
                                   0, NULL,
3662
                                   OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
3663
        if (hfile != INVALID_HANDLE_VALUE) {
3664
            result = win32_hchmod(hfile, mode);
3665
            (void)CloseHandle(hfile);
3666
        }
3667
    }
3668
    else {
3669
        result = win32_lchmod(path->wide, mode);
3670
    }
3671
    Py_END_ALLOW_THREADS
3672
    if (!result) {
3673
        return path_error(path);
3674
    }
3675
#else /* MS_WINDOWS */
3676
0
    Py_BEGIN_ALLOW_THREADS
3677
0
#ifdef HAVE_FCHMOD
3678
0
    if (path->fd != -1)
3679
0
        result = fchmod(path->fd, mode);
3680
0
    else
3681
0
#endif /* HAVE_CHMOD */
3682
#ifdef HAVE_LCHMOD
3683
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3684
        result = lchmod(path->narrow, mode);
3685
    else
3686
#endif /* HAVE_LCHMOD */
3687
0
#ifdef HAVE_FCHMODAT
3688
0
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
3689
0
        if (HAVE_FCHMODAT_RUNTIME) {
3690
            /*
3691
             * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
3692
             * The documentation specifically shows how to use it,
3693
             * and then says it isn't implemented yet.
3694
             * (true on linux with glibc 2.15, and openindiana 3.x)
3695
             *
3696
             * Once it is supported, os.chmod will automatically
3697
             * support dir_fd and follow_symlinks=False.  (Hopefully.)
3698
             * Until then, we need to be careful what exception we raise.
3699
             */
3700
0
            result = fchmodat(dir_fd, path->narrow, mode,
3701
0
                              follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3702
            /*
3703
             * But wait!  We can't throw the exception without allowing threads,
3704
             * and we can't do that in this nested scope.  (Macro trickery, sigh.)
3705
             */
3706
0
            fchmodat_nofollow_unsupported =
3707
0
                             result &&
3708
0
                             ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
3709
0
                             !follow_symlinks;
3710
0
        } else {
3711
0
            fchmodat_unsupported = 1;
3712
0
            fchmodat_nofollow_unsupported = 1;
3713
3714
0
            result = -1;
3715
0
        }
3716
0
    }
3717
0
    else
3718
0
#endif /* HAVE_FHCMODAT */
3719
0
    {
3720
0
#ifdef HAVE_CHMOD
3721
0
        result = chmod(path->narrow, mode);
3722
#elif defined(__wasi__)
3723
        // WASI SDK 15.0 does not support chmod.
3724
        // Ignore missing syscall for now.
3725
        result = 0;
3726
#else
3727
        result = -1;
3728
        errno = ENOSYS;
3729
#endif
3730
0
    }
3731
0
    Py_END_ALLOW_THREADS
3732
3733
0
    if (result) {
3734
0
#ifdef HAVE_FCHMODAT
3735
0
        if (fchmodat_unsupported) {
3736
0
            if (dir_fd != DEFAULT_DIR_FD) {
3737
0
                argument_unavailable_error("chmod", "dir_fd");
3738
0
                return NULL;
3739
0
            }
3740
0
        }
3741
3742
0
        if (fchmodat_nofollow_unsupported) {
3743
0
            if (dir_fd != DEFAULT_DIR_FD)
3744
0
                dir_fd_and_follow_symlinks_invalid("chmod",
3745
0
                                                   dir_fd, follow_symlinks);
3746
0
            else
3747
0
                follow_symlinks_specified("chmod", follow_symlinks);
3748
0
            return NULL;
3749
0
        }
3750
0
        else
3751
0
#endif /* HAVE_FCHMODAT */
3752
0
        return path_error(path);
3753
0
    }
3754
0
#endif /* MS_WINDOWS */
3755
3756
0
    Py_RETURN_NONE;
3757
0
}
3758
3759
3760
#if defined(HAVE_FCHMOD) || defined(MS_WINDOWS)
3761
/*[clinic input]
3762
os.fchmod
3763
3764
    fd: int
3765
        The file descriptor of the file to be modified.
3766
    mode: int
3767
        Operating-system mode bitfield.
3768
        Be careful when using number literals for *mode*. The conventional UNIX notation for
3769
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
3770
        Python.
3771
3772
Change the access permissions of the file given by file descriptor fd.
3773
3774
Equivalent to os.chmod(fd, mode).
3775
[clinic start generated code]*/
3776
3777
static PyObject *
3778
os_fchmod_impl(PyObject *module, int fd, int mode)
3779
/*[clinic end generated code: output=afd9bc05b4e426b3 input=b5594618bbbc22df]*/
3780
0
{
3781
0
    int res;
3782
3783
0
    if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
3784
0
        return NULL;
3785
0
    }
3786
3787
#ifdef MS_WINDOWS
3788
    res = 0;
3789
    Py_BEGIN_ALLOW_THREADS
3790
    res = win32_fchmod(fd, mode);
3791
    Py_END_ALLOW_THREADS
3792
    if (!res) {
3793
        return PyErr_SetFromWindowsErr(0);
3794
    }
3795
#else /* MS_WINDOWS */
3796
0
    int async_err = 0;
3797
0
    do {
3798
0
        Py_BEGIN_ALLOW_THREADS
3799
0
        res = fchmod(fd, mode);
3800
0
        Py_END_ALLOW_THREADS
3801
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3802
0
    if (res != 0)
3803
0
        return (!async_err) ? posix_error() : NULL;
3804
0
#endif /* MS_WINDOWS */
3805
3806
0
    Py_RETURN_NONE;
3807
0
}
3808
#endif /* HAVE_FCHMOD || MS_WINDOWS */
3809
3810
3811
#if defined(HAVE_LCHMOD) || defined(MS_WINDOWS)
3812
/*[clinic input]
3813
os.lchmod
3814
3815
    path: path_t
3816
    mode: int
3817
3818
Change the access permissions of a file, without following symbolic links.
3819
3820
If path is a symlink, this affects the link itself rather than the target.
3821
Equivalent to chmod(path, mode, follow_symlinks=False)."
3822
[clinic start generated code]*/
3823
3824
static PyObject *
3825
os_lchmod_impl(PyObject *module, path_t *path, int mode)
3826
/*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
3827
{
3828
    int res;
3829
    if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
3830
        return NULL;
3831
    }
3832
#ifdef MS_WINDOWS
3833
    Py_BEGIN_ALLOW_THREADS
3834
    res = win32_lchmod(path->wide, mode);
3835
    Py_END_ALLOW_THREADS
3836
    if (!res) {
3837
        path_error(path);
3838
        return NULL;
3839
    }
3840
#else /* MS_WINDOWS */
3841
    Py_BEGIN_ALLOW_THREADS
3842
    res = lchmod(path->narrow, mode);
3843
    Py_END_ALLOW_THREADS
3844
    if (res < 0) {
3845
        path_error(path);
3846
        return NULL;
3847
    }
3848
#endif /* MS_WINDOWS */
3849
    Py_RETURN_NONE;
3850
}
3851
#endif /* HAVE_LCHMOD || MS_WINDOWS */
3852
3853
3854
#ifdef HAVE_CHFLAGS
3855
/*[clinic input]
3856
os.chflags
3857
3858
    path: path_t
3859
    flags: unsigned_long(bitwise=True)
3860
    follow_symlinks: bool=True
3861
3862
Set file flags.
3863
3864
If follow_symlinks is False, and the last element of the path is a symbolic
3865
  link, chflags will change flags on the symbolic link itself instead of the
3866
  file the link points to.
3867
follow_symlinks may not be implemented on your platform.  If it is
3868
unavailable, using it will raise a NotImplementedError.
3869
3870
[clinic start generated code]*/
3871
3872
static PyObject *
3873
os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
3874
                int follow_symlinks)
3875
/*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
3876
{
3877
    int result;
3878
3879
#ifndef HAVE_LCHFLAGS
3880
    if (follow_symlinks_specified("chflags", follow_symlinks))
3881
        return NULL;
3882
#endif
3883
3884
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3885
        return NULL;
3886
    }
3887
3888
    Py_BEGIN_ALLOW_THREADS
3889
#ifdef HAVE_LCHFLAGS
3890
    if (!follow_symlinks)
3891
        result = lchflags(path->narrow, flags);
3892
    else
3893
#endif
3894
        result = chflags(path->narrow, flags);
3895
    Py_END_ALLOW_THREADS
3896
3897
    if (result)
3898
        return path_error(path);
3899
3900
    Py_RETURN_NONE;
3901
}
3902
#endif /* HAVE_CHFLAGS */
3903
3904
3905
#ifdef HAVE_LCHFLAGS
3906
/*[clinic input]
3907
os.lchflags
3908
3909
    path: path_t
3910
    flags: unsigned_long(bitwise=True)
3911
3912
Set file flags.
3913
3914
This function will not follow symbolic links.
3915
Equivalent to chflags(path, flags, follow_symlinks=False).
3916
[clinic start generated code]*/
3917
3918
static PyObject *
3919
os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
3920
/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
3921
{
3922
    int res;
3923
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3924
        return NULL;
3925
    }
3926
    Py_BEGIN_ALLOW_THREADS
3927
    res = lchflags(path->narrow, flags);
3928
    Py_END_ALLOW_THREADS
3929
    if (res < 0) {
3930
        return path_error(path);
3931
    }
3932
    Py_RETURN_NONE;
3933
}
3934
#endif /* HAVE_LCHFLAGS */
3935
3936
3937
#ifdef HAVE_CHROOT
3938
/*[clinic input]
3939
os.chroot
3940
    path: path_t
3941
3942
Change root directory to path.
3943
3944
[clinic start generated code]*/
3945
3946
static PyObject *
3947
os_chroot_impl(PyObject *module, path_t *path)
3948
/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
3949
0
{
3950
0
    int res;
3951
0
    Py_BEGIN_ALLOW_THREADS
3952
0
    res = chroot(path->narrow);
3953
0
    Py_END_ALLOW_THREADS
3954
0
    if (res < 0)
3955
0
        return path_error(path);
3956
0
    Py_RETURN_NONE;
3957
0
}
3958
#endif /* HAVE_CHROOT */
3959
3960
3961
#ifdef HAVE_FSYNC
3962
/*[clinic input]
3963
os.fsync
3964
3965
    fd: fildes
3966
3967
Force write of fd to disk.
3968
[clinic start generated code]*/
3969
3970
static PyObject *
3971
os_fsync_impl(PyObject *module, int fd)
3972
/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
3973
0
{
3974
0
    return posix_fildes_fd(fd, fsync);
3975
0
}
3976
#endif /* HAVE_FSYNC */
3977
3978
3979
#ifdef HAVE_SYNC
3980
/*[clinic input]
3981
os.sync
3982
3983
Force write of everything to disk.
3984
[clinic start generated code]*/
3985
3986
static PyObject *
3987
os_sync_impl(PyObject *module)
3988
/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
3989
0
{
3990
0
    Py_BEGIN_ALLOW_THREADS
3991
0
    sync();
3992
0
    Py_END_ALLOW_THREADS
3993
0
    Py_RETURN_NONE;
3994
0
}
3995
#endif /* HAVE_SYNC */
3996
3997
3998
#ifdef HAVE_FDATASYNC
3999
#ifdef __hpux
4000
extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
4001
#endif
4002
4003
/*[clinic input]
4004
os.fdatasync
4005
4006
    fd: fildes
4007
4008
Force write of fd to disk without forcing update of metadata.
4009
[clinic start generated code]*/
4010
4011
static PyObject *
4012
os_fdatasync_impl(PyObject *module, int fd)
4013
/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
4014
0
{
4015
0
    return posix_fildes_fd(fd, fdatasync);
4016
0
}
4017
#endif /* HAVE_FDATASYNC */
4018
4019
4020
#ifdef HAVE_CHOWN
4021
/*[clinic input]
4022
os.chown
4023
4024
    path : path_t(allow_fd='PATH_HAVE_FCHOWN')
4025
        Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
4026
4027
    uid: uid_t
4028
4029
    gid: gid_t
4030
4031
    *
4032
4033
    dir_fd : dir_fd(requires='fchownat') = None
4034
        If not None, it should be a file descriptor open to a directory,
4035
        and path should be relative; path will then be relative to that
4036
        directory.
4037
4038
    follow_symlinks: bool = True
4039
        If False, and the last element of the path is a symbolic link,
4040
        stat will examine the symbolic link itself instead of the file
4041
        the link points to.
4042
4043
Change the owner and group id of path to the numeric uid and gid.\
4044
4045
path may always be specified as a string.
4046
On some platforms, path may also be specified as an open file descriptor.
4047
  If this functionality is unavailable, using it raises an exception.
4048
If dir_fd is not None, it should be a file descriptor open to a directory,
4049
  and path should be relative; path will then be relative to that directory.
4050
If follow_symlinks is False, and the last element of the path is a symbolic
4051
  link, chown will modify the symbolic link itself instead of the file the
4052
  link points to.
4053
It is an error to use dir_fd or follow_symlinks when specifying path as
4054
  an open file descriptor.
4055
dir_fd and follow_symlinks may not be implemented on your platform.
4056
  If they are unavailable, using them will raise a NotImplementedError.
4057
4058
[clinic start generated code]*/
4059
4060
static PyObject *
4061
os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
4062
              int dir_fd, int follow_symlinks)
4063
/*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
4064
0
{
4065
0
    int result;
4066
4067
0
#if defined(HAVE_FCHOWNAT)
4068
0
    int fchownat_unsupported = 0;
4069
0
#endif
4070
4071
#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
4072
    if (follow_symlinks_specified("chown", follow_symlinks))
4073
        return NULL;
4074
#endif
4075
0
    if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
4076
0
        fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
4077
0
        return NULL;
4078
4079
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
4080
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4081
0
        return NULL;
4082
0
    }
4083
4084
0
    Py_BEGIN_ALLOW_THREADS
4085
0
#ifdef HAVE_FCHOWN
4086
0
    if (path->fd != -1)
4087
0
        result = fchown(path->fd, uid, gid);
4088
0
    else
4089
0
#endif
4090
0
#ifdef HAVE_LCHOWN
4091
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4092
0
        result = lchown(path->narrow, uid, gid);
4093
0
    else
4094
0
#endif
4095
0
#ifdef HAVE_FCHOWNAT
4096
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
4097
0
      if (HAVE_FCHOWNAT_RUNTIME) {
4098
0
        result = fchownat(dir_fd, path->narrow, uid, gid,
4099
0
                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4100
0
      } else {
4101
0
         fchownat_unsupported = 1;
4102
0
      }
4103
0
    } else
4104
0
#endif
4105
0
        result = chown(path->narrow, uid, gid);
4106
0
    Py_END_ALLOW_THREADS
4107
4108
0
#ifdef HAVE_FCHOWNAT
4109
0
    if (fchownat_unsupported) {
4110
        /* This would be incorrect if the current platform
4111
         * doesn't support lchown.
4112
         */
4113
0
        argument_unavailable_error(NULL, "dir_fd");
4114
0
        return NULL;
4115
0
    }
4116
0
#endif
4117
4118
0
    if (result)
4119
0
        return path_error(path);
4120
4121
0
    Py_RETURN_NONE;
4122
0
}
4123
#endif /* HAVE_CHOWN */
4124
4125
4126
#ifdef HAVE_FCHOWN
4127
/*[clinic input]
4128
os.fchown
4129
4130
    fd: int
4131
    uid: uid_t
4132
    gid: gid_t
4133
4134
Change the owner and group id of the file specified by file descriptor.
4135
4136
Equivalent to os.chown(fd, uid, gid).
4137
4138
[clinic start generated code]*/
4139
4140
static PyObject *
4141
os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
4142
/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
4143
0
{
4144
0
    int res;
4145
0
    int async_err = 0;
4146
4147
0
    if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
4148
0
        return NULL;
4149
0
    }
4150
4151
0
    do {
4152
0
        Py_BEGIN_ALLOW_THREADS
4153
0
        res = fchown(fd, uid, gid);
4154
0
        Py_END_ALLOW_THREADS
4155
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4156
0
    if (res != 0)
4157
0
        return (!async_err) ? posix_error() : NULL;
4158
4159
0
    Py_RETURN_NONE;
4160
0
}
4161
#endif /* HAVE_FCHOWN */
4162
4163
4164
#ifdef HAVE_LCHOWN
4165
/*[clinic input]
4166
os.lchown
4167
4168
    path : path_t
4169
    uid: uid_t
4170
    gid: gid_t
4171
4172
Change the owner and group id of path to the numeric uid and gid.
4173
4174
This function will not follow symbolic links.
4175
Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
4176
[clinic start generated code]*/
4177
4178
static PyObject *
4179
os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
4180
/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
4181
0
{
4182
0
    int res;
4183
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
4184
0
        return NULL;
4185
0
    }
4186
0
    Py_BEGIN_ALLOW_THREADS
4187
0
    res = lchown(path->narrow, uid, gid);
4188
0
    Py_END_ALLOW_THREADS
4189
0
    if (res < 0) {
4190
0
        return path_error(path);
4191
0
    }
4192
0
    Py_RETURN_NONE;
4193
0
}
4194
#endif /* HAVE_LCHOWN */
4195
4196
4197
static PyObject *
4198
posix_getcwd(int use_bytes)
4199
0
{
4200
#ifdef MS_WINDOWS
4201
    wchar_t wbuf[MAXPATHLEN];
4202
    wchar_t *wbuf2 = wbuf;
4203
    DWORD len;
4204
4205
    Py_BEGIN_ALLOW_THREADS
4206
    len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
4207
    /* If the buffer is large enough, len does not include the
4208
       terminating \0. If the buffer is too small, len includes
4209
       the space needed for the terminator. */
4210
    if (len >= Py_ARRAY_LENGTH(wbuf)) {
4211
        if ((Py_ssize_t)len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4212
            wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
4213
        }
4214
        else {
4215
            wbuf2 = NULL;
4216
        }
4217
        if (wbuf2) {
4218
            len = GetCurrentDirectoryW(len, wbuf2);
4219
        }
4220
    }
4221
    Py_END_ALLOW_THREADS
4222
4223
    if (!wbuf2) {
4224
        PyErr_NoMemory();
4225
        return NULL;
4226
    }
4227
    if (!len) {
4228
        PyErr_SetFromWindowsErr(0);
4229
        if (wbuf2 != wbuf)
4230
            PyMem_RawFree(wbuf2);
4231
        return NULL;
4232
    }
4233
4234
    PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
4235
    if (wbuf2 != wbuf) {
4236
        PyMem_RawFree(wbuf2);
4237
    }
4238
4239
    if (use_bytes) {
4240
        if (resobj == NULL) {
4241
            return NULL;
4242
        }
4243
        Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
4244
    }
4245
4246
    return resobj;
4247
#else
4248
0
    const size_t chunk = 1024;
4249
4250
0
    char *buf = NULL;
4251
0
    char *cwd = NULL;
4252
0
    size_t buflen = 0;
4253
4254
0
    Py_BEGIN_ALLOW_THREADS
4255
0
    do {
4256
0
        char *newbuf;
4257
0
        if (buflen <= PY_SSIZE_T_MAX - chunk) {
4258
0
            buflen += chunk;
4259
0
            newbuf = PyMem_RawRealloc(buf, buflen);
4260
0
        }
4261
0
        else {
4262
0
            newbuf = NULL;
4263
0
        }
4264
0
        if (newbuf == NULL) {
4265
0
            PyMem_RawFree(buf);
4266
0
            buf = NULL;
4267
0
            break;
4268
0
        }
4269
0
        buf = newbuf;
4270
4271
0
        cwd = getcwd(buf, buflen);
4272
0
    } while (cwd == NULL && errno == ERANGE);
4273
0
    Py_END_ALLOW_THREADS
4274
4275
0
    if (buf == NULL) {
4276
0
        return PyErr_NoMemory();
4277
0
    }
4278
0
    if (cwd == NULL) {
4279
0
        posix_error();
4280
0
        PyMem_RawFree(buf);
4281
0
        return NULL;
4282
0
    }
4283
4284
0
    PyObject *obj;
4285
0
    if (use_bytes) {
4286
0
        obj = PyBytes_FromStringAndSize(buf, strlen(buf));
4287
0
    }
4288
0
    else {
4289
0
        obj = PyUnicode_DecodeFSDefault(buf);
4290
0
    }
4291
0
#ifdef __linux__
4292
0
    if (buf[0] != '/') {
4293
        /*
4294
         * On Linux >= 2.6.36 with glibc < 2.27, getcwd() can return a
4295
         * relative pathname starting with '(unreachable)'. We detect this
4296
         * and fail with ENOENT, matching newer glibc behaviour.
4297
         */
4298
0
        errno = ENOENT;
4299
0
        path_object_error(obj);
4300
0
        PyMem_RawFree(buf);
4301
0
        return NULL;
4302
0
    }
4303
0
#endif
4304
0
    assert(buf[0] == '/');
4305
0
    PyMem_RawFree(buf);
4306
4307
0
    return obj;
4308
0
#endif   /* !MS_WINDOWS */
4309
0
}
4310
4311
4312
/*[clinic input]
4313
os.getcwd
4314
4315
Return a unicode string representing the current working directory.
4316
[clinic start generated code]*/
4317
4318
static PyObject *
4319
os_getcwd_impl(PyObject *module)
4320
/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
4321
0
{
4322
0
    return posix_getcwd(0);
4323
0
}
4324
4325
4326
/*[clinic input]
4327
os.getcwdb
4328
4329
Return a bytes string representing the current working directory.
4330
[clinic start generated code]*/
4331
4332
static PyObject *
4333
os_getcwdb_impl(PyObject *module)
4334
/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
4335
0
{
4336
0
    return posix_getcwd(1);
4337
0
}
4338
4339
4340
#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
4341
#define HAVE_LINK 1
4342
#endif
4343
4344
#ifdef HAVE_LINK
4345
/*[clinic input]
4346
4347
os.link
4348
4349
    src : path_t
4350
    dst : path_t
4351
    *
4352
    src_dir_fd : dir_fd = None
4353
    dst_dir_fd : dir_fd = None
4354
    follow_symlinks: bool(c_default="-1", py_default="(os.name != 'nt')") = PLACEHOLDER
4355
4356
Create a hard link to a file.
4357
4358
If either src_dir_fd or dst_dir_fd is not None, it should be a file
4359
  descriptor open to a directory, and the respective path string (src or dst)
4360
  should be relative; the path will then be relative to that directory.
4361
If follow_symlinks is False, and the last element of src is a symbolic
4362
  link, link will create a link to the symbolic link itself instead of the
4363
  file the link points to.
4364
src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
4365
  platform.  If they are unavailable, using them will raise a
4366
  NotImplementedError.
4367
[clinic start generated code]*/
4368
4369
static PyObject *
4370
os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4371
             int dst_dir_fd, int follow_symlinks)
4372
/*[clinic end generated code: output=7f00f6007fd5269a input=1d5e602d115fed7b]*/
4373
0
{
4374
#ifdef MS_WINDOWS
4375
    BOOL result = FALSE;
4376
#else
4377
0
    int result;
4378
0
#endif
4379
4380
0
#ifdef HAVE_LINKAT
4381
0
    if (HAVE_LINKAT_RUNTIME) {
4382
0
        if (follow_symlinks < 0) {
4383
0
            follow_symlinks = 1;
4384
0
        }
4385
0
    }
4386
0
    else
4387
0
#endif
4388
0
    {
4389
0
        if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
4390
0
            argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
4391
0
            return NULL;
4392
0
        }
4393
/* See issue 85527: link() on Linux works like linkat without AT_SYMLINK_FOLLOW,
4394
   but on Mac it works like linkat *with* AT_SYMLINK_FOLLOW. */
4395
0
#if defined(MS_WINDOWS) || defined(__linux__)
4396
0
        if (follow_symlinks == 1) {
4397
0
            argument_unavailable_error("link", "follow_symlinks=True");
4398
0
            return NULL;
4399
0
        }
4400
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || (defined(__sun) && defined(__SVR4))
4401
        if (follow_symlinks == 0) {
4402
            argument_unavailable_error("link", "follow_symlinks=False");
4403
            return NULL;
4404
        }
4405
#else
4406
        if (follow_symlinks >= 0) {
4407
            argument_unavailable_error("link", "follow_symlinks");
4408
            return NULL;
4409
        }
4410
#endif
4411
0
    }
4412
4413
0
    if (PySys_Audit("os.link", "OOii", src->object, dst->object,
4414
0
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4415
0
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4416
0
        return NULL;
4417
0
    }
4418
4419
#ifdef MS_WINDOWS
4420
    Py_BEGIN_ALLOW_THREADS
4421
    result = CreateHardLinkW(dst->wide, src->wide, NULL);
4422
    Py_END_ALLOW_THREADS
4423
4424
    if (!result)
4425
        return path_error2(src, dst);
4426
#else
4427
0
    Py_BEGIN_ALLOW_THREADS
4428
0
#ifdef HAVE_LINKAT
4429
0
    if (HAVE_LINKAT_RUNTIME) {
4430
0
        result = linkat(src_dir_fd, src->narrow,
4431
0
            dst_dir_fd, dst->narrow,
4432
0
            follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
4433
0
    }
4434
0
    else
4435
0
#endif
4436
0
    {
4437
        /* linkat not available */
4438
0
        result = link(src->narrow, dst->narrow);
4439
0
    }
4440
0
    Py_END_ALLOW_THREADS
4441
4442
0
    if (result)
4443
0
        return path_error2(src, dst);
4444
0
#endif /* MS_WINDOWS */
4445
4446
0
    Py_RETURN_NONE;
4447
0
}
4448
#endif
4449
4450
4451
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4452
static PyObject *
4453
_listdir_windows_no_opendir(path_t *path, PyObject *list)
4454
{
4455
    PyObject *v;
4456
    HANDLE hFindFile = INVALID_HANDLE_VALUE;
4457
    BOOL result, return_bytes;
4458
    wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
4459
    /* only claim to have space for MAX_PATH */
4460
    Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
4461
    wchar_t *wnamebuf = NULL;
4462
4463
    WIN32_FIND_DATAW wFileData;
4464
    const wchar_t *po_wchars;
4465
4466
    if (!path->wide) { /* Default arg: "." */
4467
        po_wchars = L".";
4468
        len = 1;
4469
        return_bytes = 0;
4470
    } else {
4471
        po_wchars = path->wide;
4472
        len = wcslen(path->wide);
4473
        return_bytes = PyBytes_Check(path->object);
4474
    }
4475
    /* The +5 is so we can append "\\*.*\0" */
4476
    wnamebuf = PyMem_New(wchar_t, len + 5);
4477
    if (!wnamebuf) {
4478
        PyErr_NoMemory();
4479
        goto exit;
4480
    }
4481
    wcscpy(wnamebuf, po_wchars);
4482
    if (len > 0) {
4483
        wchar_t wch = wnamebuf[len-1];
4484
        if (wch != SEP && wch != ALTSEP && wch != L':')
4485
            wnamebuf[len++] = SEP;
4486
        wcscpy(wnamebuf + len, L"*.*");
4487
    }
4488
    if ((list = PyList_New(0)) == NULL) {
4489
        goto exit;
4490
    }
4491
    Py_BEGIN_ALLOW_THREADS
4492
    hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4493
    Py_END_ALLOW_THREADS
4494
    if (hFindFile == INVALID_HANDLE_VALUE) {
4495
        int error = GetLastError();
4496
        if (error == ERROR_FILE_NOT_FOUND)
4497
            goto exit;
4498
        path_error(path);
4499
        Py_CLEAR(list);
4500
        goto exit;
4501
    }
4502
    do {
4503
        /* Skip over . and .. */
4504
        if (wcscmp(wFileData.cFileName, L".") != 0 &&
4505
            wcscmp(wFileData.cFileName, L"..") != 0) {
4506
            v = PyUnicode_FromWideChar(wFileData.cFileName,
4507
                                       wcslen(wFileData.cFileName));
4508
            if (return_bytes && v) {
4509
                Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4510
            }
4511
            if (v == NULL) {
4512
                Py_CLEAR(list);
4513
                break;
4514
            }
4515
            if (PyList_Append(list, v) != 0) {
4516
                Py_DECREF(v);
4517
                Py_CLEAR(list);
4518
                break;
4519
            }
4520
            Py_DECREF(v);
4521
        }
4522
        Py_BEGIN_ALLOW_THREADS
4523
        result = FindNextFileW(hFindFile, &wFileData);
4524
        Py_END_ALLOW_THREADS
4525
        /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4526
           it got to the end of the directory. */
4527
        if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4528
            path_error(path);
4529
            Py_CLEAR(list);
4530
            goto exit;
4531
        }
4532
    } while (result == TRUE);
4533
4534
exit:
4535
    if (hFindFile != INVALID_HANDLE_VALUE) {
4536
        if (FindClose(hFindFile) == FALSE) {
4537
            if (list != NULL) {
4538
                path_error(path);
4539
                Py_CLEAR(list);
4540
            }
4541
        }
4542
    }
4543
    PyMem_Free(wnamebuf);
4544
4545
    return list;
4546
}  /* end of _listdir_windows_no_opendir */
4547
4548
#else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4549
4550
static PyObject *
4551
_posix_listdir(path_t *path, PyObject *list)
4552
119
{
4553
119
    PyObject *v;
4554
119
    DIR *dirp = NULL;
4555
119
    struct dirent *ep;
4556
119
    int return_str; /* if false, return bytes */
4557
119
#ifdef HAVE_FDOPENDIR
4558
119
    int fd = -1;
4559
119
#endif
4560
4561
119
    errno = 0;
4562
119
#ifdef HAVE_FDOPENDIR
4563
119
    if (path->fd != -1) {
4564
0
      if (HAVE_FDOPENDIR_RUNTIME) {
4565
        /* closedir() closes the FD, so we duplicate it */
4566
0
        fd = _Py_dup(path->fd);
4567
0
        if (fd == -1)
4568
0
            return NULL;
4569
4570
0
        return_str = 1;
4571
4572
0
        Py_BEGIN_ALLOW_THREADS
4573
0
        dirp = fdopendir(fd);
4574
0
        Py_END_ALLOW_THREADS
4575
0
      } else {
4576
0
        PyErr_SetString(PyExc_TypeError,
4577
0
            "listdir: path should be string, bytes, os.PathLike or None, not int");
4578
0
        return NULL;
4579
0
      }
4580
0
    }
4581
119
    else
4582
119
#endif
4583
119
    {
4584
119
        const char *name;
4585
119
        if (path->narrow) {
4586
119
            name = path->narrow;
4587
            /* only return bytes if they specified a bytes object */
4588
119
            return_str = !PyBytes_Check(path->object);
4589
119
        }
4590
0
        else {
4591
0
            name = ".";
4592
0
            return_str = 1;
4593
0
        }
4594
4595
119
        Py_BEGIN_ALLOW_THREADS
4596
119
        dirp = opendir(name);
4597
119
        Py_END_ALLOW_THREADS
4598
119
    }
4599
4600
119
    if (dirp == NULL) {
4601
0
        path_error(path);
4602
0
        list = NULL;
4603
0
#ifdef HAVE_FDOPENDIR
4604
0
        if (fd != -1) {
4605
0
            Py_BEGIN_ALLOW_THREADS
4606
0
            close(fd);
4607
0
            Py_END_ALLOW_THREADS
4608
0
        }
4609
0
#endif
4610
0
        goto exit;
4611
0
    }
4612
119
    if ((list = PyList_New(0)) == NULL) {
4613
0
        goto exit;
4614
0
    }
4615
7.07k
    for (;;) {
4616
7.07k
        errno = 0;
4617
7.07k
        Py_BEGIN_ALLOW_THREADS
4618
7.07k
        ep = readdir(dirp);
4619
7.07k
        Py_END_ALLOW_THREADS
4620
7.07k
        if (ep == NULL) {
4621
119
            if (errno == 0) {
4622
119
                break;
4623
119
            } else {
4624
0
                path_error(path);
4625
0
                Py_CLEAR(list);
4626
0
                goto exit;
4627
0
            }
4628
119
        }
4629
6.95k
        if (ep->d_name[0] == '.' &&
4630
6.95k
            (NAMLEN(ep) == 1 ||
4631
238
             (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
4632
238
            continue;
4633
6.72k
        if (return_str)
4634
6.72k
            v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
4635
0
        else
4636
0
            v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
4637
6.72k
        if (v == NULL) {
4638
0
            Py_CLEAR(list);
4639
0
            break;
4640
0
        }
4641
6.72k
        if (PyList_Append(list, v) != 0) {
4642
0
            Py_DECREF(v);
4643
0
            Py_CLEAR(list);
4644
0
            break;
4645
0
        }
4646
6.72k
        Py_DECREF(v);
4647
6.72k
    }
4648
4649
119
exit:
4650
119
    if (dirp != NULL) {
4651
119
        Py_BEGIN_ALLOW_THREADS
4652
119
#ifdef HAVE_FDOPENDIR
4653
119
        if (fd > -1)
4654
0
            rewinddir(dirp);
4655
119
#endif
4656
119
        closedir(dirp);
4657
119
        Py_END_ALLOW_THREADS
4658
119
    }
4659
4660
119
    return list;
4661
119
}  /* end of _posix_listdir */
4662
#endif  /* which OS */
4663
4664
4665
/*[clinic input]
4666
os.listdir
4667
4668
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
4669
4670
Return a list containing the names of the files in the directory.
4671
4672
path can be specified as either str, bytes, or a path-like object.  If path is bytes,
4673
  the filenames returned will also be bytes; in all other circumstances
4674
  the filenames returned will be str.
4675
If path is None, uses the path='.'.
4676
On some platforms, path may also be specified as an open file descriptor;\
4677
  the file descriptor must refer to a directory.
4678
  If this functionality is unavailable, using it raises NotImplementedError.
4679
4680
The list is in arbitrary order.  It does not include the special
4681
entries '.' and '..' even if they are present in the directory.
4682
4683
4684
[clinic start generated code]*/
4685
4686
static PyObject *
4687
os_listdir_impl(PyObject *module, path_t *path)
4688
/*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
4689
119
{
4690
119
    if (PySys_Audit("os.listdir", "O",
4691
119
                    path->object ? path->object : Py_None) < 0) {
4692
0
        return NULL;
4693
0
    }
4694
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4695
    return _listdir_windows_no_opendir(path, NULL);
4696
#else
4697
119
    return _posix_listdir(path, NULL);
4698
119
#endif
4699
119
}
4700
4701
4702
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
4703
4704
/*[clinic input]
4705
os.listdrives
4706
4707
Return a list containing the names of drives in the system.
4708
4709
A drive name typically looks like 'C:\\'.
4710
4711
[clinic start generated code]*/
4712
4713
static PyObject *
4714
os_listdrives_impl(PyObject *module)
4715
/*[clinic end generated code: output=aaece9dacdf682b5 input=1af9ccc9e583798e]*/
4716
{
4717
    /* Number of possible drives is limited, so 256 should always be enough.
4718
       On the day when it is not, listmounts() will have to be used. */
4719
    wchar_t buffer[256];
4720
    DWORD buflen = Py_ARRAY_LENGTH(buffer);
4721
    PyObject *result = NULL;
4722
    if (PySys_Audit("os.listdrives", NULL) < 0) {
4723
        return NULL;
4724
    }
4725
4726
    Py_BEGIN_ALLOW_THREADS;
4727
    buflen = GetLogicalDriveStringsW(buflen, buffer);
4728
    Py_END_ALLOW_THREADS;
4729
4730
    if (!buflen) {
4731
        PyErr_SetFromWindowsErr(0);
4732
        return NULL;
4733
    } else if (buflen >= Py_ARRAY_LENGTH(buffer)) {
4734
        PyErr_SetFromWindowsErr(ERROR_MORE_DATA);
4735
        return NULL;
4736
    }
4737
4738
    /* buflen includes a null terminator, so remove it */
4739
    PyObject *str = PyUnicode_FromWideChar(buffer, buflen - 1);
4740
    if (str) {
4741
        PyObject *nullchar = PyUnicode_FromStringAndSize("\0", 1);
4742
        if (nullchar) {
4743
            result = PyUnicode_Split(str, nullchar, -1);
4744
            Py_DECREF(nullchar);
4745
        }
4746
        Py_DECREF(str);
4747
    }
4748
    return result;
4749
}
4750
4751
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
4752
4753
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
4754
4755
/*[clinic input]
4756
os.listvolumes
4757
4758
Return a list containing the volumes in the system.
4759
4760
Volumes are typically represented as a GUID path.
4761
4762
[clinic start generated code]*/
4763
4764
static PyObject *
4765
os_listvolumes_impl(PyObject *module)
4766
/*[clinic end generated code: output=534e10ea2bf9d386 input=f6e4e70371f11e99]*/
4767
{
4768
    PyObject *result = PyList_New(0);
4769
    HANDLE find = INVALID_HANDLE_VALUE;
4770
    wchar_t buffer[MAX_PATH + 1];
4771
    if (!result) {
4772
        return NULL;
4773
    }
4774
    if (PySys_Audit("os.listvolumes", NULL) < 0) {
4775
        Py_DECREF(result);
4776
        return NULL;
4777
    }
4778
4779
    int err = 0;
4780
    Py_BEGIN_ALLOW_THREADS;
4781
    find = FindFirstVolumeW(buffer, Py_ARRAY_LENGTH(buffer));
4782
    if (find == INVALID_HANDLE_VALUE) {
4783
        err = GetLastError();
4784
    }
4785
    Py_END_ALLOW_THREADS;
4786
4787
    while (!err) {
4788
        PyObject *s = PyUnicode_FromWideChar(buffer, -1);
4789
        if (!s || PyList_Append(result, s) < 0) {
4790
            Py_XDECREF(s);
4791
            Py_CLEAR(result);
4792
            break;
4793
        }
4794
        Py_DECREF(s);
4795
4796
        Py_BEGIN_ALLOW_THREADS;
4797
        if (!FindNextVolumeW(find, buffer, Py_ARRAY_LENGTH(buffer))) {
4798
            err = GetLastError();
4799
        }
4800
        Py_END_ALLOW_THREADS;
4801
    }
4802
4803
    if (find != INVALID_HANDLE_VALUE) {
4804
        Py_BEGIN_ALLOW_THREADS;
4805
        FindVolumeClose(find);
4806
        Py_END_ALLOW_THREADS;
4807
    }
4808
    if (err && err != ERROR_NO_MORE_FILES) {
4809
        PyErr_SetFromWindowsErr(err);
4810
        Py_XDECREF(result);
4811
        result = NULL;
4812
    }
4813
    return result;
4814
}
4815
4816
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
4817
4818
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
4819
4820
/*[clinic input]
4821
os.listmounts
4822
4823
    volume: path_t
4824
4825
Return a list containing mount points for a particular volume.
4826
4827
'volume' should be a GUID path as returned from os.listvolumes.
4828
4829
[clinic start generated code]*/
4830
4831
static PyObject *
4832
os_listmounts_impl(PyObject *module, path_t *volume)
4833
/*[clinic end generated code: output=06da49679de4512e input=a8a27178e3f67845]*/
4834
{
4835
    wchar_t default_buffer[MAX_PATH + 1];
4836
    DWORD buflen = Py_ARRAY_LENGTH(default_buffer);
4837
    LPWSTR buffer = default_buffer;
4838
    DWORD attributes;
4839
    PyObject *str = NULL;
4840
    PyObject *nullchar = NULL;
4841
    PyObject *result = NULL;
4842
4843
    /* Ensure we have a valid volume path before continuing */
4844
    Py_BEGIN_ALLOW_THREADS
4845
    attributes = GetFileAttributesW(volume->wide);
4846
    Py_END_ALLOW_THREADS
4847
    if (attributes == INVALID_FILE_ATTRIBUTES &&
4848
        GetLastError() == ERROR_UNRECOGNIZED_VOLUME)
4849
    {
4850
        return PyErr_SetFromWindowsErr(ERROR_UNRECOGNIZED_VOLUME);
4851
    }
4852
4853
    if (PySys_Audit("os.listmounts", "O", volume->object) < 0) {
4854
        return NULL;
4855
    }
4856
4857
    while (1) {
4858
        BOOL success;
4859
        Py_BEGIN_ALLOW_THREADS
4860
        success = GetVolumePathNamesForVolumeNameW(volume->wide, buffer,
4861
                                                   buflen, &buflen);
4862
        Py_END_ALLOW_THREADS
4863
        if (success) {
4864
            break;
4865
        }
4866
        if (GetLastError() != ERROR_MORE_DATA) {
4867
            PyErr_SetFromWindowsErr(0);
4868
            goto exit;
4869
        }
4870
        if (buffer != default_buffer) {
4871
            PyMem_Free((void *)buffer);
4872
        }
4873
        buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * buflen);
4874
        if (!buffer) {
4875
            PyErr_NoMemory();
4876
            goto exit;
4877
        }
4878
    }
4879
    if (buflen < 2) {
4880
        result = PyList_New(0);
4881
        goto exit;
4882
    }
4883
    // buflen includes two null terminators, one for the last string
4884
    // and one for the array of strings.
4885
    str = PyUnicode_FromWideChar(buffer, buflen - 2);
4886
    nullchar = PyUnicode_FromStringAndSize("\0", 1);
4887
    if (str && nullchar) {
4888
        result = PyUnicode_Split(str, nullchar, -1);
4889
    }
4890
exit:
4891
    if (buffer != default_buffer) {
4892
        PyMem_Free(buffer);
4893
    }
4894
    Py_XDECREF(nullchar);
4895
    Py_XDECREF(str);
4896
    return result;
4897
}
4898
4899
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
4900
4901
#ifdef MS_WINDOWS
4902
4903
/*[clinic input]
4904
os._path_isdevdrive
4905
4906
    path: path_t
4907
4908
Determines whether the specified path is on a Windows Dev Drive.
4909
4910
[clinic start generated code]*/
4911
4912
static PyObject *
4913
os__path_isdevdrive_impl(PyObject *module, path_t *path)
4914
/*[clinic end generated code: output=1f437ea6677433a2 input=ee83e4996a48e23d]*/
4915
{
4916
#ifndef PERSISTENT_VOLUME_STATE_DEV_VOLUME
4917
    /* This flag will be documented at
4918
       https://learn.microsoft.com/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_fs_persistent_volume_information
4919
       after release, and will be available in the latest WinSDK.
4920
       We include the flag to avoid a specific version dependency
4921
       on the latest WinSDK. */
4922
    const int PERSISTENT_VOLUME_STATE_DEV_VOLUME = 0x00002000;
4923
#endif
4924
    int err = 0;
4925
    PyObject *r = NULL;
4926
    wchar_t volume[MAX_PATH];
4927
4928
    Py_BEGIN_ALLOW_THREADS
4929
    if (!GetVolumePathNameW(path->wide, volume, MAX_PATH)) {
4930
        /* invalid path of some kind */
4931
        /* Note that this also includes the case where a volume is mounted
4932
           in a path longer than 260 characters. This is likely to be rare
4933
           and problematic for other reasons, so a (soft) failure in this
4934
           check seems okay. */
4935
        err = GetLastError();
4936
    } else if (GetDriveTypeW(volume) != DRIVE_FIXED) {
4937
        /* only care about local dev drives */
4938
        r = Py_False;
4939
    } else {
4940
        HANDLE hVolume = CreateFileW(
4941
            volume,
4942
            FILE_READ_ATTRIBUTES,
4943
            FILE_SHARE_READ | FILE_SHARE_WRITE,
4944
            NULL,
4945
            OPEN_EXISTING,
4946
            FILE_FLAG_BACKUP_SEMANTICS,
4947
            NULL
4948
        );
4949
        if (hVolume == INVALID_HANDLE_VALUE) {
4950
            err = GetLastError();
4951
        } else {
4952
            FILE_FS_PERSISTENT_VOLUME_INFORMATION volumeState = {0};
4953
            volumeState.Version = 1;
4954
            volumeState.FlagMask = PERSISTENT_VOLUME_STATE_DEV_VOLUME;
4955
            if (!DeviceIoControl(
4956
                hVolume,
4957
                FSCTL_QUERY_PERSISTENT_VOLUME_STATE,
4958
                &volumeState,
4959
                sizeof(volumeState),
4960
                &volumeState,
4961
                sizeof(volumeState),
4962
                NULL,
4963
                NULL
4964
            )) {
4965
                err = GetLastError();
4966
            }
4967
            CloseHandle(hVolume);
4968
            if (err == ERROR_INVALID_PARAMETER) {
4969
                /* not supported on this platform */
4970
                r = Py_False;
4971
            } else if (!err) {
4972
                r = (volumeState.VolumeFlags & PERSISTENT_VOLUME_STATE_DEV_VOLUME)
4973
                    ? Py_True : Py_False;
4974
            }
4975
        }
4976
    }
4977
    Py_END_ALLOW_THREADS
4978
4979
    if (err) {
4980
        PyErr_SetFromWindowsErr(err);
4981
        return NULL;
4982
    }
4983
4984
    if (r) {
4985
        return Py_NewRef(r);
4986
    }
4987
4988
    return NULL;
4989
}
4990
4991
4992
int
4993
_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
4994
{
4995
    wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
4996
    DWORD result;
4997
4998
    result = GetFullPathNameW(path,
4999
                              Py_ARRAY_LENGTH(woutbuf), woutbuf,
5000
                              NULL);
5001
    if (!result) {
5002
        return -1;
5003
    }
5004
5005
    if (result >= Py_ARRAY_LENGTH(woutbuf)) {
5006
        if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
5007
            woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
5008
        }
5009
        else {
5010
            woutbufp = NULL;
5011
        }
5012
        if (!woutbufp) {
5013
            *abspath_p = NULL;
5014
            return 0;
5015
        }
5016
5017
        result = GetFullPathNameW(path, result, woutbufp, NULL);
5018
        if (!result) {
5019
            PyMem_RawFree(woutbufp);
5020
            return -1;
5021
        }
5022
    }
5023
5024
    if (woutbufp != woutbuf) {
5025
        *abspath_p = woutbufp;
5026
        return 0;
5027
    }
5028
5029
    *abspath_p = _PyMem_RawWcsdup(woutbufp);
5030
    return 0;
5031
}
5032
5033
5034
/* A helper function for abspath on win32 */
5035
/*[clinic input]
5036
os._getfullpathname
5037
5038
    path: path_t
5039
    /
5040
5041
[clinic start generated code]*/
5042
5043
static PyObject *
5044
os__getfullpathname_impl(PyObject *module, path_t *path)
5045
/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
5046
{
5047
    wchar_t *abspath;
5048
5049
    if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
5050
        return win32_error_object("GetFullPathNameW", path->object);
5051
    }
5052
    if (abspath == NULL) {
5053
        return PyErr_NoMemory();
5054
    }
5055
5056
    PyObject *str = PyUnicode_FromWideChar(abspath, -1);
5057
    PyMem_RawFree(abspath);
5058
    if (str == NULL) {
5059
        return NULL;
5060
    }
5061
    if (PyBytes_Check(path->object)) {
5062
        Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
5063
    }
5064
    return str;
5065
}
5066
5067
5068
/*[clinic input]
5069
os._getfinalpathname
5070
5071
    path: path_t
5072
    /
5073
5074
A helper function for samepath on windows.
5075
[clinic start generated code]*/
5076
5077
static PyObject *
5078
os__getfinalpathname_impl(PyObject *module, path_t *path)
5079
/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
5080
{
5081
    HANDLE hFile;
5082
    wchar_t buf[MAXPATHLEN], *target_path = buf;
5083
    int buf_size = Py_ARRAY_LENGTH(buf);
5084
    int result_length;
5085
    PyObject *result;
5086
5087
    Py_BEGIN_ALLOW_THREADS
5088
    hFile = CreateFileW(
5089
        path->wide,
5090
        0, /* desired access */
5091
        0, /* share mode */
5092
        NULL, /* security attributes */
5093
        OPEN_EXISTING,
5094
        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
5095
        FILE_FLAG_BACKUP_SEMANTICS,
5096
        NULL);
5097
    Py_END_ALLOW_THREADS
5098
5099
    if (hFile == INVALID_HANDLE_VALUE) {
5100
        return win32_error_object("CreateFileW", path->object);
5101
    }
5102
5103
    /* We have a good handle to the target, use it to determine the
5104
       target path name. */
5105
    while (1) {
5106
        Py_BEGIN_ALLOW_THREADS
5107
        result_length = GetFinalPathNameByHandleW(hFile, target_path,
5108
                                                  buf_size, VOLUME_NAME_DOS);
5109
        Py_END_ALLOW_THREADS
5110
5111
        if (!result_length) {
5112
            result = win32_error_object("GetFinalPathNameByHandleW",
5113
                                         path->object);
5114
            goto cleanup;
5115
        }
5116
5117
        if (result_length < buf_size) {
5118
            break;
5119
        }
5120
5121
        wchar_t *tmp;
5122
        tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
5123
                            result_length * sizeof(*tmp));
5124
        if (!tmp) {
5125
            result = PyErr_NoMemory();
5126
            goto cleanup;
5127
        }
5128
5129
        buf_size = result_length;
5130
        target_path = tmp;
5131
    }
5132
5133
    result = PyUnicode_FromWideChar(target_path, result_length);
5134
    if (result && PyBytes_Check(path->object)) {
5135
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5136
    }
5137
5138
cleanup:
5139
    if (target_path != buf) {
5140
        PyMem_Free(target_path);
5141
    }
5142
    CloseHandle(hFile);
5143
    return result;
5144
}
5145
5146
/*[clinic input]
5147
os._findfirstfile
5148
    path: path_t
5149
    /
5150
A function to get the real file name without accessing the file in Windows.
5151
[clinic start generated code]*/
5152
5153
static PyObject *
5154
os__findfirstfile_impl(PyObject *module, path_t *path)
5155
/*[clinic end generated code: output=106dd3f0779c83dd input=0734dff70f60e1a8]*/
5156
{
5157
    PyObject *result;
5158
    HANDLE hFindFile;
5159
    WIN32_FIND_DATAW wFileData;
5160
    WCHAR *wRealFileName;
5161
5162
    Py_BEGIN_ALLOW_THREADS
5163
    hFindFile = FindFirstFileW(path->wide, &wFileData);
5164
    Py_END_ALLOW_THREADS
5165
5166
    if (hFindFile == INVALID_HANDLE_VALUE) {
5167
        path_error(path);
5168
        return NULL;
5169
    }
5170
5171
    wRealFileName = wFileData.cFileName;
5172
    result = PyUnicode_FromWideChar(wRealFileName, -1);
5173
    FindClose(hFindFile);
5174
    return result;
5175
}
5176
5177
5178
/*[clinic input]
5179
os._getvolumepathname
5180
5181
    path: path_t
5182
5183
A helper function for ismount on Win32.
5184
[clinic start generated code]*/
5185
5186
static PyObject *
5187
os__getvolumepathname_impl(PyObject *module, path_t *path)
5188
/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
5189
{
5190
    PyObject *result;
5191
    wchar_t *mountpath=NULL;
5192
    size_t buflen;
5193
    BOOL ret;
5194
5195
    /* Volume path should be shorter than entire path */
5196
    buflen = Py_MAX(path->length, MAX_PATH);
5197
5198
    if (buflen > PY_DWORD_MAX) {
5199
        PyErr_SetString(PyExc_OverflowError, "path too long");
5200
        return NULL;
5201
    }
5202
5203
    mountpath = PyMem_New(wchar_t, buflen);
5204
    if (mountpath == NULL)
5205
        return PyErr_NoMemory();
5206
5207
    Py_BEGIN_ALLOW_THREADS
5208
    ret = GetVolumePathNameW(path->wide, mountpath,
5209
                             Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
5210
    Py_END_ALLOW_THREADS
5211
5212
    if (!ret) {
5213
        result = win32_error_object("_getvolumepathname", path->object);
5214
        goto exit;
5215
    }
5216
    result = PyUnicode_FromWideChar(mountpath, -1);
5217
    if (PyBytes_Check(path->object))
5218
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5219
5220
exit:
5221
    PyMem_Free(mountpath);
5222
    return result;
5223
}
5224
5225
5226
/*[clinic input]
5227
os._path_splitroot
5228
5229
    path: path_t
5230
5231
Removes everything after the root on Win32.
5232
[clinic start generated code]*/
5233
5234
static PyObject *
5235
os__path_splitroot_impl(PyObject *module, path_t *path)
5236
/*[clinic end generated code: output=ab7f1a88b654581c input=dc93b1d3984cffb6]*/
5237
{
5238
    wchar_t *buffer;
5239
    wchar_t *end;
5240
    PyObject *result = NULL;
5241
    HRESULT ret;
5242
5243
    buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
5244
    if (!buffer) {
5245
        return NULL;
5246
    }
5247
    wcscpy(buffer, path->wide);
5248
    for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
5249
        *p = L'\\';
5250
    }
5251
5252
    Py_BEGIN_ALLOW_THREADS
5253
    ret = PathCchSkipRoot(buffer, &end);
5254
    Py_END_ALLOW_THREADS
5255
    if (FAILED(ret)) {
5256
        result = Py_BuildValue("sO", "", path->object);
5257
    } else if (end != buffer) {
5258
        size_t rootLen = (size_t)(end - buffer);
5259
        result = Py_BuildValue("NN",
5260
            PyUnicode_FromWideChar(path->wide, rootLen),
5261
            PyUnicode_FromWideChar(path->wide + rootLen, -1)
5262
        );
5263
    } else {
5264
        result = Py_BuildValue("Os", path->object, "");
5265
    }
5266
    PyMem_Free(buffer);
5267
5268
    return result;
5269
}
5270
5271
5272
#define PY_IFREG  1 // Regular file
5273
#define PY_IFDIR  2 // Directory
5274
#define PY_IFLNK  4 // Symlink
5275
#define PY_IFMNT  8 // Mount Point (junction)
5276
#define PY_IFLRP 16 // Link Reparse Point (name-surrogate, symlink, junction)
5277
#define PY_IFRRP 32 // Regular Reparse Point
5278
5279
static inline BOOL
5280
_testInfo(DWORD attributes, DWORD reparseTag, BOOL diskDevice, int testedType)
5281
{
5282
    switch (testedType) {
5283
    case PY_IFREG:
5284
        return diskDevice && attributes &&
5285
               !(attributes & FILE_ATTRIBUTE_DIRECTORY);
5286
    case PY_IFDIR:
5287
        return attributes & FILE_ATTRIBUTE_DIRECTORY;
5288
    case PY_IFLNK:
5289
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5290
               reparseTag == IO_REPARSE_TAG_SYMLINK;
5291
    case PY_IFMNT:
5292
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5293
               reparseTag == IO_REPARSE_TAG_MOUNT_POINT;
5294
    case PY_IFLRP:
5295
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5296
               IsReparseTagNameSurrogate(reparseTag);
5297
    case PY_IFRRP:
5298
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5299
               reparseTag && !IsReparseTagNameSurrogate(reparseTag);
5300
    }
5301
5302
    return FALSE;
5303
}
5304
5305
static BOOL
5306
_testFileTypeByHandle(HANDLE hfile, int testedType, BOOL diskOnly)
5307
{
5308
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5309
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5310
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5311
5312
    BOOL diskDevice = GetFileType(hfile) == FILE_TYPE_DISK;
5313
    if (diskOnly && !diskDevice) {
5314
        return FALSE;
5315
    }
5316
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5317
        FILE_ATTRIBUTE_TAG_INFO info;
5318
        return GetFileInformationByHandleEx(hfile, FileAttributeTagInfo, &info,
5319
                                            sizeof(info)) &&
5320
               _testInfo(info.FileAttributes, info.ReparseTag, diskDevice,
5321
                         testedType);
5322
    }
5323
    FILE_BASIC_INFO info;
5324
    return GetFileInformationByHandleEx(hfile, FileBasicInfo, &info,
5325
                                        sizeof(info)) &&
5326
           _testInfo(info.FileAttributes, 0, diskDevice, testedType);
5327
}
5328
5329
static BOOL
5330
_testFileTypeByName(LPCWSTR path, int testedType)
5331
{
5332
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5333
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5334
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5335
5336
    FILE_STAT_BASIC_INFORMATION info;
5337
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5338
                                     sizeof(info)))
5339
    {
5340
        BOOL diskDevice = info.DeviceType == FILE_DEVICE_DISK ||
5341
                          info.DeviceType == FILE_DEVICE_VIRTUAL_DISK ||
5342
                          info.DeviceType == FILE_DEVICE_CD_ROM;
5343
        BOOL result = _testInfo(info.FileAttributes, info.ReparseTag,
5344
                                diskDevice, testedType);
5345
        if (!result || (testedType != PY_IFREG && testedType != PY_IFDIR) ||
5346
            !(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
5347
        {
5348
            return result;
5349
        }
5350
    }
5351
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5352
                GetLastError()))
5353
    {
5354
        return FALSE;
5355
    }
5356
5357
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5358
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5359
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5360
    }
5361
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5362
                               OPEN_EXISTING, flags, NULL);
5363
    if (hfile != INVALID_HANDLE_VALUE) {
5364
        BOOL result = _testFileTypeByHandle(hfile, testedType, FALSE);
5365
        CloseHandle(hfile);
5366
        return result;
5367
    }
5368
5369
    switch (GetLastError()) {
5370
    case ERROR_ACCESS_DENIED:
5371
    case ERROR_SHARING_VIOLATION:
5372
    case ERROR_CANT_ACCESS_FILE:
5373
    case ERROR_INVALID_PARAMETER:
5374
        int rc;
5375
        STRUCT_STAT st;
5376
        if (testedType == PY_IFREG || testedType == PY_IFDIR) {
5377
            rc = STAT(path, &st);
5378
        }
5379
        else {
5380
            // PY_IFRRP is not generally supported in this case, except for
5381
            // unhandled reparse points such as IO_REPARSE_TAG_APPEXECLINK.
5382
            rc = LSTAT(path, &st);
5383
        }
5384
        if (!rc) {
5385
            return _testInfo(st.st_file_attributes, st.st_reparse_tag,
5386
                             st.st_mode & S_IFREG, testedType);
5387
        }
5388
    }
5389
5390
    return FALSE;
5391
}
5392
5393
5394
static BOOL
5395
_testFileExistsByName(LPCWSTR path, BOOL followLinks)
5396
{
5397
    FILE_STAT_BASIC_INFORMATION info;
5398
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5399
                                     sizeof(info)))
5400
    {
5401
        if (!(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ||
5402
            (!followLinks && IsReparseTagNameSurrogate(info.ReparseTag)))
5403
        {
5404
            return TRUE;
5405
        }
5406
    }
5407
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5408
                    GetLastError()))
5409
    {
5410
        return FALSE;
5411
    }
5412
5413
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5414
    if (!followLinks) {
5415
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5416
    }
5417
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5418
                               OPEN_EXISTING, flags, NULL);
5419
    if (hfile != INVALID_HANDLE_VALUE) {
5420
        if (followLinks) {
5421
            CloseHandle(hfile);
5422
            return TRUE;
5423
        }
5424
        // Regular Reparse Points (PY_IFRRP) have to be traversed.
5425
        BOOL result = _testFileTypeByHandle(hfile, PY_IFRRP, FALSE);
5426
        CloseHandle(hfile);
5427
        if (!result) {
5428
            return TRUE;
5429
        }
5430
        hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
5431
                            FILE_FLAG_BACKUP_SEMANTICS, NULL);
5432
        if (hfile != INVALID_HANDLE_VALUE) {
5433
            CloseHandle(hfile);
5434
            return TRUE;
5435
        }
5436
    }
5437
5438
    switch (GetLastError()) {
5439
    case ERROR_ACCESS_DENIED:
5440
    case ERROR_SHARING_VIOLATION:
5441
    case ERROR_CANT_ACCESS_FILE:
5442
    case ERROR_INVALID_PARAMETER:
5443
        STRUCT_STAT _st;
5444
        return followLinks ? !STAT(path, &_st): !LSTAT(path, &_st);
5445
    }
5446
5447
    return FALSE;
5448
}
5449
5450
5451
static BOOL
5452
_testFileExists(path_t *path, BOOL followLinks)
5453
{
5454
    BOOL result = FALSE;
5455
    if (path->value_error) {
5456
        return FALSE;
5457
    }
5458
5459
    Py_BEGIN_ALLOW_THREADS
5460
    if (path->fd != -1) {
5461
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5462
        if (hfile != INVALID_HANDLE_VALUE) {
5463
            if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) {
5464
                result = TRUE;
5465
            }
5466
        }
5467
    }
5468
    else if (path->wide) {
5469
        result = _testFileExistsByName(path->wide, followLinks);
5470
    }
5471
    Py_END_ALLOW_THREADS
5472
5473
    return result;
5474
}
5475
5476
5477
static BOOL
5478
_testFileType(path_t *path, int testedType)
5479
{
5480
    BOOL result = FALSE;
5481
    if (path->value_error) {
5482
        return FALSE;
5483
    }
5484
5485
    Py_BEGIN_ALLOW_THREADS
5486
    if (path->fd != -1) {
5487
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5488
        if (hfile != INVALID_HANDLE_VALUE) {
5489
            result = _testFileTypeByHandle(hfile, testedType, TRUE);
5490
        }
5491
    }
5492
    else if (path->wide) {
5493
        result = _testFileTypeByName(path->wide, testedType);
5494
    }
5495
    Py_END_ALLOW_THREADS
5496
5497
    return result;
5498
}
5499
5500
5501
/*[clinic input]
5502
os._path_exists -> bool
5503
5504
    path: path_t(allow_fd=True, suppress_value_error=True)
5505
5506
Test whether a path exists.  Returns False for broken symbolic links.
5507
5508
[clinic start generated code]*/
5509
5510
static int
5511
os__path_exists_impl(PyObject *module, path_t *path)
5512
/*[clinic end generated code: output=8da13acf666e16ba input=142beabfc66783eb]*/
5513
{
5514
    return _testFileExists(path, TRUE);
5515
}
5516
5517
5518
/*[clinic input]
5519
os._path_lexists -> bool
5520
5521
    path: path_t(allow_fd=True, suppress_value_error=True)
5522
5523
Test whether a path exists.  Returns True for broken symbolic links.
5524
5525
[clinic start generated code]*/
5526
5527
static int
5528
os__path_lexists_impl(PyObject *module, path_t *path)
5529
/*[clinic end generated code: output=e7240ed5fc45bff3 input=208205112a3cc1ed]*/
5530
{
5531
    return _testFileExists(path, FALSE);
5532
}
5533
5534
5535
/*[clinic input]
5536
os._path_isdir -> bool
5537
5538
    s as path: path_t(allow_fd=True, suppress_value_error=True)
5539
5540
Return true if the pathname refers to an existing directory.
5541
5542
[clinic start generated code]*/
5543
5544
static int
5545
os__path_isdir_impl(PyObject *module, path_t *path)
5546
/*[clinic end generated code: output=d5786196f9e2fa7a input=132a3b5301aecf79]*/
5547
{
5548
    return _testFileType(path, PY_IFDIR);
5549
}
5550
5551
5552
/*[clinic input]
5553
os._path_isfile -> bool
5554
5555
    path: path_t(allow_fd=True, suppress_value_error=True)
5556
5557
Test whether a path is a regular file
5558
5559
[clinic start generated code]*/
5560
5561
static int
5562
os__path_isfile_impl(PyObject *module, path_t *path)
5563
/*[clinic end generated code: output=5c3073bc212b9863 input=4ac1fd350b30a39e]*/
5564
{
5565
    return _testFileType(path, PY_IFREG);
5566
}
5567
5568
5569
/*[clinic input]
5570
os._path_islink -> bool
5571
5572
    path: path_t(allow_fd=True, suppress_value_error=True)
5573
5574
Test whether a path is a symbolic link
5575
5576
[clinic start generated code]*/
5577
5578
static int
5579
os__path_islink_impl(PyObject *module, path_t *path)
5580
/*[clinic end generated code: output=30da7bda8296adcc input=7510ce05b547debb]*/
5581
{
5582
    return _testFileType(path, PY_IFLNK);
5583
}
5584
5585
5586
/*[clinic input]
5587
os._path_isjunction -> bool
5588
5589
    path: path_t(allow_fd=True, suppress_value_error=True)
5590
5591
Test whether a path is a junction
5592
5593
[clinic start generated code]*/
5594
5595
static int
5596
os__path_isjunction_impl(PyObject *module, path_t *path)
5597
/*[clinic end generated code: output=e1d17a9dd18a9945 input=7dcb8bc4e972fcaf]*/
5598
{
5599
    return _testFileType(path, PY_IFMNT);
5600
}
5601
5602
#undef PY_IFREG
5603
#undef PY_IFDIR
5604
#undef PY_IFLNK
5605
#undef PY_IFMNT
5606
#undef PY_IFLRP
5607
#undef PY_IFRRP
5608
5609
#endif /* MS_WINDOWS */
5610
5611
5612
/*[clinic input]
5613
os._path_splitroot_ex
5614
5615
    p as path: path_t(make_wide=True, nonstrict=True)
5616
5617
Split a pathname into drive, root and tail.
5618
5619
The tail contains anything after the root.
5620
[clinic start generated code]*/
5621
5622
static PyObject *
5623
os__path_splitroot_ex_impl(PyObject *module, path_t *path)
5624
/*[clinic end generated code: output=4b0072b6cdf4b611 input=4556b615c7cc13f2]*/
5625
0
{
5626
0
    Py_ssize_t drvsize, rootsize;
5627
0
    PyObject *drv = NULL, *root = NULL, *tail = NULL, *result = NULL;
5628
5629
0
    const wchar_t *buffer = path->wide;
5630
0
    _Py_skiproot(buffer, path->length, &drvsize, &rootsize);
5631
0
    drv = PyUnicode_FromWideChar(buffer, drvsize);
5632
0
    if (drv == NULL) {
5633
0
        goto exit;
5634
0
    }
5635
0
    root = PyUnicode_FromWideChar(&buffer[drvsize], rootsize);
5636
0
    if (root == NULL) {
5637
0
        goto exit;
5638
0
    }
5639
0
    tail = PyUnicode_FromWideChar(&buffer[drvsize + rootsize],
5640
0
                                  path->length - drvsize - rootsize);
5641
0
    if (tail == NULL) {
5642
0
        goto exit;
5643
0
    }
5644
0
    if (PyBytes_Check(path->object)) {
5645
0
        Py_SETREF(drv, PyUnicode_EncodeFSDefault(drv));
5646
0
        if (drv == NULL) {
5647
0
            goto exit;
5648
0
        }
5649
0
        Py_SETREF(root, PyUnicode_EncodeFSDefault(root));
5650
0
        if (root == NULL) {
5651
0
            goto exit;
5652
0
        }
5653
0
        Py_SETREF(tail, PyUnicode_EncodeFSDefault(tail));
5654
0
        if (tail == NULL) {
5655
0
            goto exit;
5656
0
        }
5657
0
    }
5658
0
    result = PyTuple_Pack(3, drv, root, tail);
5659
0
exit:
5660
0
    Py_XDECREF(drv);
5661
0
    Py_XDECREF(root);
5662
0
    Py_XDECREF(tail);
5663
0
    return result;
5664
0
}
5665
5666
5667
/*[clinic input]
5668
os._path_normpath
5669
5670
    path: path_t(make_wide=True, nonstrict=True)
5671
5672
Normalize path, eliminating double slashes, etc.
5673
[clinic start generated code]*/
5674
5675
static PyObject *
5676
os__path_normpath_impl(PyObject *module, path_t *path)
5677
/*[clinic end generated code: output=d353e7ed9410c044 input=3d4ac23b06332dcb]*/
5678
80
{
5679
80
    PyObject *result;
5680
80
    Py_ssize_t norm_len;
5681
80
    wchar_t *norm_path = _Py_normpath_and_size((wchar_t *)path->wide,
5682
80
                                               path->length, &norm_len);
5683
80
    if (!norm_len) {
5684
0
        result = PyUnicode_FromOrdinal('.');
5685
0
    }
5686
80
    else {
5687
80
        result = PyUnicode_FromWideChar(norm_path, norm_len);
5688
80
    }
5689
80
    if (PyBytes_Check(path->object)) {
5690
0
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5691
0
    }
5692
80
    return result;
5693
80
}
5694
5695
/*[clinic input]
5696
os.mkdir
5697
5698
    path : path_t
5699
5700
    mode: int = 0o777
5701
5702
    *
5703
5704
    dir_fd : dir_fd(requires='mkdirat') = None
5705
5706
# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
5707
5708
Create a directory.
5709
5710
If dir_fd is not None, it should be a file descriptor open to a directory,
5711
  and path should be relative; path will then be relative to that directory.
5712
dir_fd may not be implemented on your platform.
5713
  If it is unavailable, using it will raise a NotImplementedError.
5714
5715
The mode argument is ignored on Windows. Where it is used, the current umask
5716
value is first masked out.
5717
[clinic start generated code]*/
5718
5719
static PyObject *
5720
os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
5721
/*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
5722
0
{
5723
0
    int result;
5724
#ifdef MS_WINDOWS
5725
    int error = 0;
5726
    SECURITY_ATTRIBUTES secAttr = { sizeof(secAttr) };
5727
    SECURITY_ATTRIBUTES *pSecAttr = NULL;
5728
#endif
5729
0
#ifdef HAVE_MKDIRAT
5730
0
    int mkdirat_unavailable = 0;
5731
0
#endif
5732
5733
0
    if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
5734
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5735
0
        return NULL;
5736
0
    }
5737
5738
#ifdef MS_WINDOWS
5739
    Py_BEGIN_ALLOW_THREADS
5740
    // For API sets that don't support these APIs, we have no choice
5741
    // but to silently create a directory with default ACL.
5742
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
5743
    if (mode == 0700 /* 0o700 */) {
5744
        ULONG sdSize;
5745
        pSecAttr = &secAttr;
5746
        // Set a discretionary ACL (D) that is protected (P) and includes
5747
        // inheritable (OICI) entries that allow (A) full control (FA) to
5748
        // SYSTEM (SY), Administrators (BA), and the owner (OW).
5749
        if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
5750
            L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)",
5751
            SDDL_REVISION_1,
5752
            &secAttr.lpSecurityDescriptor,
5753
            &sdSize
5754
        )) {
5755
            error = GetLastError();
5756
        }
5757
    }
5758
#endif
5759
    if (!error) {
5760
        result = CreateDirectoryW(path->wide, pSecAttr);
5761
        if (secAttr.lpSecurityDescriptor &&
5762
            // uncommonly, LocalFree returns non-zero on error, but still uses
5763
            // GetLastError() to see what the error code is
5764
            LocalFree(secAttr.lpSecurityDescriptor)) {
5765
            error = GetLastError();
5766
        }
5767
    }
5768
    Py_END_ALLOW_THREADS
5769
5770
    if (error) {
5771
        return PyErr_SetFromWindowsErr(error);
5772
    }
5773
    if (!result) {
5774
        return path_error(path);
5775
    }
5776
#else
5777
0
    Py_BEGIN_ALLOW_THREADS
5778
0
#if HAVE_MKDIRAT
5779
0
    if (dir_fd != DEFAULT_DIR_FD) {
5780
0
      if (HAVE_MKDIRAT_RUNTIME) {
5781
0
        result = mkdirat(dir_fd, path->narrow, mode);
5782
5783
0
      } else {
5784
0
        mkdirat_unavailable = 1;
5785
0
      }
5786
0
    } else
5787
0
#endif
5788
#if defined(__WATCOMC__) && !defined(__QNX__)
5789
        result = mkdir(path->narrow);
5790
#else
5791
0
        result = mkdir(path->narrow, mode);
5792
0
#endif
5793
0
    Py_END_ALLOW_THREADS
5794
5795
0
#if HAVE_MKDIRAT
5796
0
    if (mkdirat_unavailable) {
5797
0
        argument_unavailable_error(NULL, "dir_fd");
5798
0
        return NULL;
5799
0
    }
5800
0
#endif
5801
5802
0
    if (result < 0)
5803
0
        return path_error(path);
5804
0
#endif /* MS_WINDOWS */
5805
0
    Py_RETURN_NONE;
5806
0
}
5807
5808
5809
/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
5810
#if defined(HAVE_SYS_RESOURCE_H)
5811
#include <sys/resource.h>
5812
#endif
5813
5814
5815
#ifdef HAVE_NICE
5816
/*[clinic input]
5817
os.nice
5818
5819
    increment: int
5820
    /
5821
5822
Add increment to the priority of process and return the new priority.
5823
[clinic start generated code]*/
5824
5825
static PyObject *
5826
os_nice_impl(PyObject *module, int increment)
5827
/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
5828
0
{
5829
0
    int value;
5830
5831
    /* There are two flavours of 'nice': one that returns the new
5832
       priority (as required by almost all standards out there) and the
5833
       Linux/FreeBSD one, which returns '0' on success and advices
5834
       the use of getpriority() to get the new priority.
5835
5836
       If we are of the nice family that returns the new priority, we
5837
       need to clear errno before the call, and check if errno is filled
5838
       before calling posix_error() on a returnvalue of -1, because the
5839
       -1 may be the actual new priority! */
5840
5841
0
    errno = 0;
5842
0
    value = nice(increment);
5843
#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
5844
    if (value == 0)
5845
        value = getpriority(PRIO_PROCESS, 0);
5846
#endif
5847
0
    if (value == -1 && errno != 0)
5848
        /* either nice() or getpriority() returned an error */
5849
0
        return posix_error();
5850
0
    return PyLong_FromLong((long) value);
5851
0
}
5852
#endif /* HAVE_NICE */
5853
5854
5855
#ifdef HAVE_GETPRIORITY
5856
/*[clinic input]
5857
os.getpriority
5858
5859
    which: int
5860
    who: int
5861
5862
Return program scheduling priority.
5863
[clinic start generated code]*/
5864
5865
static PyObject *
5866
os_getpriority_impl(PyObject *module, int which, int who)
5867
/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
5868
0
{
5869
0
    int retval;
5870
5871
0
    errno = 0;
5872
0
    retval = getpriority(which, who);
5873
0
    if (errno != 0)
5874
0
        return posix_error();
5875
0
    return PyLong_FromLong((long)retval);
5876
0
}
5877
#endif /* HAVE_GETPRIORITY */
5878
5879
5880
#ifdef HAVE_SETPRIORITY
5881
/*[clinic input]
5882
os.setpriority
5883
5884
    which: int
5885
    who: int
5886
    priority: int
5887
5888
Set program scheduling priority.
5889
[clinic start generated code]*/
5890
5891
static PyObject *
5892
os_setpriority_impl(PyObject *module, int which, int who, int priority)
5893
/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
5894
0
{
5895
0
    int retval;
5896
5897
0
    retval = setpriority(which, who, priority);
5898
0
    if (retval == -1)
5899
0
        return posix_error();
5900
0
    Py_RETURN_NONE;
5901
0
}
5902
#endif /* HAVE_SETPRIORITY */
5903
5904
5905
static PyObject *
5906
internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
5907
216
{
5908
216
    const char *function_name = is_replace ? "replace" : "rename";
5909
216
    int dir_fd_specified;
5910
5911
216
#ifdef HAVE_RENAMEAT
5912
216
    int renameat_unavailable = 0;
5913
216
#endif
5914
5915
#ifdef MS_WINDOWS
5916
    BOOL result;
5917
    int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
5918
#else
5919
216
    int result;
5920
216
#endif
5921
5922
216
    dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
5923
216
                       (dst_dir_fd != DEFAULT_DIR_FD);
5924
#ifndef HAVE_RENAMEAT
5925
    if (dir_fd_specified) {
5926
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
5927
        return NULL;
5928
    }
5929
#endif
5930
5931
216
    if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
5932
216
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
5933
216
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
5934
0
        return NULL;
5935
0
    }
5936
5937
#ifdef MS_WINDOWS
5938
    Py_BEGIN_ALLOW_THREADS
5939
    result = MoveFileExW(src->wide, dst->wide, flags);
5940
    Py_END_ALLOW_THREADS
5941
5942
    if (!result)
5943
        return path_error2(src, dst);
5944
5945
#else
5946
216
    Py_BEGIN_ALLOW_THREADS
5947
216
#ifdef HAVE_RENAMEAT
5948
216
    if (dir_fd_specified) {
5949
0
        if (HAVE_RENAMEAT_RUNTIME) {
5950
0
            result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
5951
0
        } else {
5952
0
            renameat_unavailable = 1;
5953
0
        }
5954
0
    } else
5955
216
#endif
5956
216
    result = rename(src->narrow, dst->narrow);
5957
216
    Py_END_ALLOW_THREADS
5958
5959
5960
216
#ifdef HAVE_RENAMEAT
5961
216
    if (renameat_unavailable) {
5962
0
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
5963
0
        return NULL;
5964
0
    }
5965
216
#endif
5966
5967
216
    if (result)
5968
0
        return path_error2(src, dst);
5969
216
#endif
5970
216
    Py_RETURN_NONE;
5971
216
}
5972
5973
5974
/*[clinic input]
5975
os.rename
5976
5977
    src : path_t
5978
    dst : path_t
5979
    *
5980
    src_dir_fd : dir_fd = None
5981
    dst_dir_fd : dir_fd = None
5982
5983
Rename a file or directory.
5984
5985
If either src_dir_fd or dst_dir_fd is not None, it should be a file
5986
  descriptor open to a directory, and the respective path string (src or dst)
5987
  should be relative; the path will then be relative to that directory.
5988
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
5989
  If they are unavailable, using them will raise a NotImplementedError.
5990
[clinic start generated code]*/
5991
5992
static PyObject *
5993
os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
5994
               int dst_dir_fd)
5995
/*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
5996
0
{
5997
0
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
5998
0
}
5999
6000
6001
/*[clinic input]
6002
os.replace = os.rename
6003
6004
Rename a file or directory, overwriting the destination.
6005
6006
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6007
  descriptor open to a directory, and the respective path string (src or dst)
6008
  should be relative; the path will then be relative to that directory.
6009
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6010
  If they are unavailable, using them will raise a NotImplementedError.
6011
[clinic start generated code]*/
6012
6013
static PyObject *
6014
os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6015
                int dst_dir_fd)
6016
/*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
6017
216
{
6018
216
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
6019
216
}
6020
6021
6022
/*[clinic input]
6023
os.rmdir
6024
6025
    path: path_t
6026
    *
6027
    dir_fd: dir_fd(requires='unlinkat') = None
6028
6029
Remove a directory.
6030
6031
If dir_fd is not None, it should be a file descriptor open to a directory,
6032
  and path should be relative; path will then be relative to that directory.
6033
dir_fd may not be implemented on your platform.
6034
  If it is unavailable, using it will raise a NotImplementedError.
6035
[clinic start generated code]*/
6036
6037
static PyObject *
6038
os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
6039
/*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
6040
0
{
6041
0
    int result;
6042
0
#ifdef HAVE_UNLINKAT
6043
0
    int unlinkat_unavailable = 0;
6044
0
#endif
6045
6046
0
    if (PySys_Audit("os.rmdir", "Oi", path->object,
6047
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6048
0
        return NULL;
6049
0
    }
6050
6051
0
    Py_BEGIN_ALLOW_THREADS
6052
#ifdef MS_WINDOWS
6053
    /* Windows, success=1, UNIX, success=0 */
6054
    result = !RemoveDirectoryW(path->wide);
6055
#else
6056
0
#ifdef HAVE_UNLINKAT
6057
0
    if (dir_fd != DEFAULT_DIR_FD) {
6058
0
      if (HAVE_UNLINKAT_RUNTIME) {
6059
0
        result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
6060
0
      } else {
6061
0
        unlinkat_unavailable = 1;
6062
0
        result = -1;
6063
0
      }
6064
0
    } else
6065
0
#endif
6066
0
        result = rmdir(path->narrow);
6067
0
#endif
6068
0
    Py_END_ALLOW_THREADS
6069
6070
0
#ifdef HAVE_UNLINKAT
6071
0
    if (unlinkat_unavailable) {
6072
0
        argument_unavailable_error("rmdir", "dir_fd");
6073
0
        return NULL;
6074
0
    }
6075
0
#endif
6076
6077
0
    if (result)
6078
0
        return path_error(path);
6079
6080
0
    Py_RETURN_NONE;
6081
0
}
6082
6083
6084
#ifdef HAVE_SYSTEM
6085
#ifdef MS_WINDOWS
6086
/*[clinic input]
6087
os.system -> long
6088
6089
    command: Py_UNICODE
6090
6091
Execute the command in a subshell.
6092
[clinic start generated code]*/
6093
6094
static long
6095
os_system_impl(PyObject *module, const wchar_t *command)
6096
/*[clinic end generated code: output=dd528cbd5943a679 input=303f5ce97df606b0]*/
6097
{
6098
    long result;
6099
6100
    if (PySys_Audit("os.system", "(u)", command) < 0) {
6101
        return -1;
6102
    }
6103
6104
    Py_BEGIN_ALLOW_THREADS
6105
    _Py_BEGIN_SUPPRESS_IPH
6106
    result = _wsystem(command);
6107
    _Py_END_SUPPRESS_IPH
6108
    Py_END_ALLOW_THREADS
6109
    return result;
6110
}
6111
#else /* MS_WINDOWS */
6112
/*[clinic input]
6113
os.system -> long
6114
6115
    command: FSConverter
6116
6117
Execute the command in a subshell.
6118
[clinic start generated code]*/
6119
6120
static long
6121
os_system_impl(PyObject *module, PyObject *command)
6122
/*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
6123
0
{
6124
0
    long result;
6125
0
    const char *bytes = PyBytes_AsString(command);
6126
6127
0
    if (PySys_Audit("os.system", "(O)", command) < 0) {
6128
0
        return -1;
6129
0
    }
6130
6131
0
    Py_BEGIN_ALLOW_THREADS
6132
0
    result = system(bytes);
6133
0
    Py_END_ALLOW_THREADS
6134
0
    return result;
6135
0
}
6136
#endif
6137
#endif /* HAVE_SYSTEM */
6138
6139
6140
#ifdef HAVE_UMASK
6141
/*[clinic input]
6142
os.umask
6143
6144
    mask: int
6145
    /
6146
6147
Set the current numeric umask and return the previous umask.
6148
[clinic start generated code]*/
6149
6150
static PyObject *
6151
os_umask_impl(PyObject *module, int mask)
6152
/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
6153
0
{
6154
0
    int i = (int)umask(mask);
6155
0
    if (i < 0)
6156
0
        return posix_error();
6157
0
    return PyLong_FromLong((long)i);
6158
0
}
6159
#endif
6160
6161
#ifdef MS_WINDOWS
6162
6163
/* override the default DeleteFileW behavior so that directory
6164
symlinks can be removed with this function, the same as with
6165
Unix symlinks */
6166
BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
6167
{
6168
    WIN32_FILE_ATTRIBUTE_DATA info;
6169
    WIN32_FIND_DATAW find_data;
6170
    HANDLE find_data_handle;
6171
    int is_directory = 0;
6172
    int is_link = 0;
6173
6174
    if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
6175
        is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
6176
6177
        /* Get WIN32_FIND_DATA structure for the path to determine if
6178
           it is a symlink */
6179
        if(is_directory &&
6180
           info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
6181
            find_data_handle = FindFirstFileW(lpFileName, &find_data);
6182
6183
            if(find_data_handle != INVALID_HANDLE_VALUE) {
6184
                /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
6185
                   IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
6186
                is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
6187
                          find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
6188
                FindClose(find_data_handle);
6189
            }
6190
        }
6191
    }
6192
6193
    if (is_directory && is_link)
6194
        return RemoveDirectoryW(lpFileName);
6195
6196
    return DeleteFileW(lpFileName);
6197
}
6198
#endif /* MS_WINDOWS */
6199
6200
6201
/*[clinic input]
6202
os.unlink
6203
6204
    path: path_t
6205
    *
6206
    dir_fd: dir_fd(requires='unlinkat')=None
6207
6208
Remove a file (same as remove()).
6209
6210
If dir_fd is not None, it should be a file descriptor open to a directory,
6211
  and path should be relative; path will then be relative to that directory.
6212
dir_fd may not be implemented on your platform.
6213
  If it is unavailable, using it will raise a NotImplementedError.
6214
6215
[clinic start generated code]*/
6216
6217
static PyObject *
6218
os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
6219
/*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
6220
0
{
6221
0
    int result;
6222
0
#ifdef HAVE_UNLINKAT
6223
0
    int unlinkat_unavailable = 0;
6224
0
#endif
6225
6226
0
    if (PySys_Audit("os.remove", "Oi", path->object,
6227
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6228
0
        return NULL;
6229
0
    }
6230
6231
0
    Py_BEGIN_ALLOW_THREADS
6232
0
    _Py_BEGIN_SUPPRESS_IPH
6233
#ifdef MS_WINDOWS
6234
    /* Windows, success=1, UNIX, success=0 */
6235
    result = !Py_DeleteFileW(path->wide);
6236
#else
6237
0
#ifdef HAVE_UNLINKAT
6238
0
    if (dir_fd != DEFAULT_DIR_FD) {
6239
0
      if (HAVE_UNLINKAT_RUNTIME) {
6240
6241
0
        result = unlinkat(dir_fd, path->narrow, 0);
6242
0
      } else {
6243
0
        unlinkat_unavailable = 1;
6244
0
      }
6245
0
    } else
6246
0
#endif /* HAVE_UNLINKAT */
6247
0
        result = unlink(path->narrow);
6248
0
#endif
6249
0
    _Py_END_SUPPRESS_IPH
6250
0
    Py_END_ALLOW_THREADS
6251
6252
0
#ifdef HAVE_UNLINKAT
6253
0
    if (unlinkat_unavailable) {
6254
0
        argument_unavailable_error(NULL, "dir_fd");
6255
0
        return NULL;
6256
0
    }
6257
0
#endif
6258
6259
0
    if (result)
6260
0
        return path_error(path);
6261
6262
0
    Py_RETURN_NONE;
6263
0
}
6264
6265
6266
/*[clinic input]
6267
os.remove = os.unlink
6268
6269
Remove a file (same as unlink()).
6270
6271
If dir_fd is not None, it should be a file descriptor open to a directory,
6272
  and path should be relative; path will then be relative to that directory.
6273
dir_fd may not be implemented on your platform.
6274
  If it is unavailable, using it will raise a NotImplementedError.
6275
[clinic start generated code]*/
6276
6277
static PyObject *
6278
os_remove_impl(PyObject *module, path_t *path, int dir_fd)
6279
/*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
6280
0
{
6281
0
    return os_unlink_impl(module, path, dir_fd);
6282
0
}
6283
6284
6285
static PyStructSequence_Field uname_result_fields[] = {
6286
    {"sysname",    "operating system name"},
6287
    {"nodename",   "name of machine on network (implementation-defined)"},
6288
    {"release",    "operating system release"},
6289
    {"version",    "operating system version"},
6290
    {"machine",    "hardware identifier"},
6291
    {NULL}
6292
};
6293
6294
PyDoc_STRVAR(uname_result__doc__,
6295
"uname_result: Result from os.uname().\n\n\
6296
This object may be accessed either as a tuple of\n\
6297
  (sysname, nodename, release, version, machine),\n\
6298
or via the attributes sysname, nodename, release, version, and machine.\n\
6299
\n\
6300
See os.uname for more information.");
6301
6302
static PyStructSequence_Desc uname_result_desc = {
6303
    MODNAME ".uname_result", /* name */
6304
    uname_result__doc__, /* doc */
6305
    uname_result_fields,
6306
    5
6307
};
6308
6309
#ifdef HAVE_UNAME
6310
/*[clinic input]
6311
os.uname
6312
6313
Return an object identifying the current operating system.
6314
6315
The object behaves like a named tuple with the following fields:
6316
  (sysname, nodename, release, version, machine)
6317
6318
[clinic start generated code]*/
6319
6320
static PyObject *
6321
os_uname_impl(PyObject *module)
6322
/*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
6323
0
{
6324
0
    struct utsname u;
6325
0
    int res;
6326
0
    PyObject *value;
6327
6328
0
    Py_BEGIN_ALLOW_THREADS
6329
0
    res = uname(&u);
6330
0
    Py_END_ALLOW_THREADS
6331
0
    if (res < 0)
6332
0
        return posix_error();
6333
6334
0
    PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
6335
0
    value = PyStructSequence_New((PyTypeObject *)UnameResultType);
6336
0
    if (value == NULL)
6337
0
        return NULL;
6338
6339
0
#define SET(i, field) \
6340
0
    { \
6341
0
    PyObject *o = PyUnicode_DecodeFSDefault(field); \
6342
0
    if (!o) { \
6343
0
        Py_DECREF(value); \
6344
0
        return NULL; \
6345
0
    } \
6346
0
    PyStructSequence_SET_ITEM(value, i, o); \
6347
0
    } \
6348
0
6349
0
    SET(0, u.sysname);
6350
0
    SET(1, u.nodename);
6351
0
    SET(2, u.release);
6352
0
    SET(3, u.version);
6353
0
    SET(4, u.machine);
6354
6355
0
#undef SET
6356
6357
0
    return value;
6358
0
}
6359
#endif /* HAVE_UNAME */
6360
6361
6362
6363
typedef struct {
6364
    int    now;
6365
    time_t atime_s;
6366
    long   atime_ns;
6367
    time_t mtime_s;
6368
    long   mtime_ns;
6369
} utime_t;
6370
6371
/*
6372
 * these macros assume that "ut" is a pointer to a utime_t
6373
 * they also intentionally leak the declaration of a pointer named "time"
6374
 */
6375
#define UTIME_TO_TIMESPEC \
6376
0
    struct timespec ts[2]; \
6377
0
    struct timespec *time; \
6378
0
    if (ut->now) \
6379
0
        time = NULL; \
6380
0
    else { \
6381
0
        ts[0].tv_sec = ut->atime_s; \
6382
0
        ts[0].tv_nsec = ut->atime_ns; \
6383
0
        ts[1].tv_sec = ut->mtime_s; \
6384
0
        ts[1].tv_nsec = ut->mtime_ns; \
6385
0
        time = ts; \
6386
0
    } \
6387
6388
#define UTIME_TO_TIMEVAL \
6389
0
    struct timeval tv[2]; \
6390
0
    struct timeval *time; \
6391
0
    if (ut->now) \
6392
0
        time = NULL; \
6393
0
    else { \
6394
0
        tv[0].tv_sec = ut->atime_s; \
6395
0
        tv[0].tv_usec = ut->atime_ns / 1000; \
6396
0
        tv[1].tv_sec = ut->mtime_s; \
6397
0
        tv[1].tv_usec = ut->mtime_ns / 1000; \
6398
0
        time = tv; \
6399
0
    } \
6400
6401
#define UTIME_TO_UTIMBUF \
6402
    struct utimbuf u; \
6403
    struct utimbuf *time; \
6404
    if (ut->now) \
6405
        time = NULL; \
6406
    else { \
6407
        u.actime = ut->atime_s; \
6408
        u.modtime = ut->mtime_s; \
6409
        time = &u; \
6410
    }
6411
6412
#define UTIME_TO_TIME_T \
6413
    time_t timet[2]; \
6414
    time_t *time; \
6415
    if (ut->now) \
6416
        time = NULL; \
6417
    else { \
6418
        timet[0] = ut->atime_s; \
6419
        timet[1] = ut->mtime_s; \
6420
        time = timet; \
6421
    } \
6422
6423
6424
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
6425
6426
static int
6427
utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
6428
0
{
6429
#if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
6430
    if (HAVE_UTIMENSAT_RUNTIME) {
6431
        int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6432
        UTIME_TO_TIMESPEC;
6433
        return utimensat(dir_fd, path, time, flags);
6434
    }  else {
6435
        errno = ENOSYS;
6436
        return -1;
6437
    }
6438
#elif defined(HAVE_UTIMENSAT)
6439
0
    int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6440
0
    UTIME_TO_TIMESPEC;
6441
0
    return utimensat(dir_fd, path, time, flags);
6442
#elif defined(HAVE_FUTIMESAT)
6443
    UTIME_TO_TIMEVAL;
6444
    /*
6445
     * follow_symlinks will never be false here;
6446
     * we only allow !follow_symlinks and dir_fd together
6447
     * if we have utimensat()
6448
     */
6449
    assert(follow_symlinks);
6450
    return futimesat(dir_fd, path, time);
6451
#endif
6452
0
}
6453
6454
0
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
6455
#else
6456
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
6457
#endif
6458
6459
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
6460
6461
static int
6462
utime_fd(utime_t *ut, int fd)
6463
0
{
6464
0
#ifdef HAVE_FUTIMENS
6465
6466
0
    if (HAVE_FUTIMENS_RUNTIME) {
6467
6468
0
    UTIME_TO_TIMESPEC;
6469
0
    return futimens(fd, time);
6470
6471
0
    } else
6472
#ifndef HAVE_FUTIMES
6473
    {
6474
        /* Not sure if this can happen */
6475
        PyErr_SetString(
6476
            PyExc_RuntimeError,
6477
            "neither futimens nor futimes are supported"
6478
            " on this system");
6479
        return -1;
6480
    }
6481
#endif
6482
6483
0
#endif
6484
0
#ifdef HAVE_FUTIMES
6485
0
    {
6486
0
    UTIME_TO_TIMEVAL;
6487
0
    return futimes(fd, time);
6488
0
    }
6489
0
#endif
6490
0
}
6491
6492
    #define PATH_UTIME_HAVE_FD 1
6493
#else
6494
    #define PATH_UTIME_HAVE_FD 0
6495
#endif
6496
6497
#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
6498
#  define UTIME_HAVE_NOFOLLOW_SYMLINKS
6499
#endif
6500
6501
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
6502
6503
static int
6504
utime_nofollow_symlinks(utime_t *ut, const char *path)
6505
0
{
6506
0
#ifdef HAVE_UTIMENSAT
6507
0
    if (HAVE_UTIMENSAT_RUNTIME) {
6508
0
        UTIME_TO_TIMESPEC;
6509
0
        return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
6510
0
    } else
6511
#ifndef HAVE_LUTIMES
6512
    {
6513
        /* Not sure if this can happen */
6514
        PyErr_SetString(
6515
            PyExc_RuntimeError,
6516
            "neither utimensat nor lutimes are supported"
6517
            " on this system");
6518
        return -1;
6519
    }
6520
#endif
6521
0
#endif
6522
6523
0
#ifdef HAVE_LUTIMES
6524
0
    {
6525
0
    UTIME_TO_TIMEVAL;
6526
0
    return lutimes(path, time);
6527
0
    }
6528
0
#endif
6529
0
}
6530
6531
#endif
6532
6533
#ifndef MS_WINDOWS
6534
6535
static int
6536
utime_default(utime_t *ut, const char *path)
6537
0
{
6538
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
6539
    if (HAVE_UTIMENSAT_RUNTIME) {
6540
        UTIME_TO_TIMESPEC;
6541
        return utimensat(DEFAULT_DIR_FD, path, time, 0);
6542
    } else {
6543
        UTIME_TO_TIMEVAL;
6544
        return utimes(path, time);
6545
    }
6546
#elif defined(HAVE_UTIMENSAT)
6547
0
    UTIME_TO_TIMESPEC;
6548
0
    return utimensat(DEFAULT_DIR_FD, path, time, 0);
6549
#elif defined(HAVE_UTIMES)
6550
    UTIME_TO_TIMEVAL;
6551
    return utimes(path, time);
6552
#elif defined(HAVE_UTIME_H)
6553
    UTIME_TO_UTIMBUF;
6554
    return utime(path, time);
6555
#else
6556
    UTIME_TO_TIME_T;
6557
    return utime(path, time);
6558
#endif
6559
0
}
6560
6561
#endif
6562
6563
static int
6564
split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
6565
0
{
6566
0
    int result = 0;
6567
0
    PyObject *divmod;
6568
0
    divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
6569
0
    if (!divmod)
6570
0
        goto exit;
6571
0
    if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
6572
0
        PyErr_Format(PyExc_TypeError,
6573
0
                     "%.200s.__divmod__() must return a 2-tuple, not %.200s",
6574
0
                     _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
6575
0
        goto exit;
6576
0
    }
6577
0
    *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
6578
0
    if ((*s == -1) && PyErr_Occurred())
6579
0
        goto exit;
6580
0
    *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
6581
0
    if ((*ns == -1) && PyErr_Occurred())
6582
0
        goto exit;
6583
6584
0
    result = 1;
6585
0
exit:
6586
0
    Py_XDECREF(divmod);
6587
0
    return result;
6588
0
}
6589
6590
6591
/*[clinic input]
6592
os.utime
6593
6594
    path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
6595
    times: object = None
6596
    *
6597
    ns: object = NULL
6598
    dir_fd: dir_fd(requires='futimensat') = None
6599
    follow_symlinks: bool=True
6600
6601
# "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
6602
6603
Set the access and modified time of path.
6604
6605
path may always be specified as a string.
6606
On some platforms, path may also be specified as an open file descriptor.
6607
  If this functionality is unavailable, using it raises an exception.
6608
6609
If times is not None, it must be a tuple (atime, mtime);
6610
    atime and mtime should be expressed as float seconds since the epoch.
6611
If ns is specified, it must be a tuple (atime_ns, mtime_ns);
6612
    atime_ns and mtime_ns should be expressed as integer nanoseconds
6613
    since the epoch.
6614
If times is None and ns is unspecified, utime uses the current time.
6615
Specifying tuples for both times and ns is an error.
6616
6617
If dir_fd is not None, it should be a file descriptor open to a directory,
6618
  and path should be relative; path will then be relative to that directory.
6619
If follow_symlinks is False, and the last element of the path is a symbolic
6620
  link, utime will modify the symbolic link itself instead of the file the
6621
  link points to.
6622
It is an error to use dir_fd or follow_symlinks when specifying path
6623
  as an open file descriptor.
6624
dir_fd and follow_symlinks may not be available on your platform.
6625
  If they are unavailable, using them will raise a NotImplementedError.
6626
6627
[clinic start generated code]*/
6628
6629
static PyObject *
6630
os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
6631
              int dir_fd, int follow_symlinks)
6632
/*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
6633
0
{
6634
#ifdef MS_WINDOWS
6635
    HANDLE hFile;
6636
    FILETIME atime, mtime;
6637
#else
6638
0
    int result;
6639
0
#endif
6640
6641
0
    utime_t utime;
6642
6643
0
    memset(&utime, 0, sizeof(utime_t));
6644
6645
0
    if (times != Py_None && ns) {
6646
0
        PyErr_SetString(PyExc_ValueError,
6647
0
                     "utime: you may specify either 'times'"
6648
0
                     " or 'ns' but not both");
6649
0
        return NULL;
6650
0
    }
6651
6652
0
    if (times != Py_None) {
6653
0
        time_t a_sec, m_sec;
6654
0
        long a_nsec, m_nsec;
6655
0
        if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
6656
0
            PyErr_SetString(PyExc_TypeError,
6657
0
                         "utime: 'times' must be either"
6658
0
                         " a tuple of two ints or None");
6659
0
            return NULL;
6660
0
        }
6661
0
        utime.now = 0;
6662
0
        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
6663
0
                                     &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
6664
0
            _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
6665
0
                                     &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
6666
0
            return NULL;
6667
0
        }
6668
0
        utime.atime_s = a_sec;
6669
0
        utime.atime_ns = a_nsec;
6670
0
        utime.mtime_s = m_sec;
6671
0
        utime.mtime_ns = m_nsec;
6672
0
    }
6673
0
    else if (ns) {
6674
0
        if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
6675
0
            PyErr_SetString(PyExc_TypeError,
6676
0
                         "utime: 'ns' must be a tuple of two ints");
6677
0
            return NULL;
6678
0
        }
6679
0
        utime.now = 0;
6680
0
        if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
6681
0
                                      &utime.atime_s, &utime.atime_ns) ||
6682
0
            !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
6683
0
                                       &utime.mtime_s, &utime.mtime_ns)) {
6684
0
            return NULL;
6685
0
        }
6686
0
    }
6687
0
    else {
6688
        /* times and ns are both None/unspecified. use "now". */
6689
0
        utime.now = 1;
6690
0
    }
6691
6692
#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
6693
    if (follow_symlinks_specified("utime", follow_symlinks))
6694
        return NULL;
6695
#endif
6696
6697
0
    if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
6698
0
        dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
6699
0
        fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
6700
0
        return NULL;
6701
6702
#if !defined(HAVE_UTIMENSAT)
6703
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
6704
        PyErr_SetString(PyExc_ValueError,
6705
                     "utime: cannot use dir_fd and follow_symlinks "
6706
                     "together on this platform");
6707
        return NULL;
6708
    }
6709
#endif
6710
6711
0
    if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
6712
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6713
0
        return NULL;
6714
0
    }
6715
6716
#ifdef MS_WINDOWS
6717
    Py_BEGIN_ALLOW_THREADS
6718
    hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
6719
                        NULL, OPEN_EXISTING,
6720
                        FILE_FLAG_BACKUP_SEMANTICS, NULL);
6721
    Py_END_ALLOW_THREADS
6722
    if (hFile == INVALID_HANDLE_VALUE) {
6723
        path_error(path);
6724
        return NULL;
6725
    }
6726
6727
    if (utime.now) {
6728
        GetSystemTimeAsFileTime(&mtime);
6729
        atime = mtime;
6730
    }
6731
    else {
6732
        _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
6733
        _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
6734
    }
6735
    if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
6736
        path_error(path);
6737
        CloseHandle(hFile);
6738
        return NULL;
6739
    }
6740
    CloseHandle(hFile);
6741
#else /* MS_WINDOWS */
6742
0
    Py_BEGIN_ALLOW_THREADS
6743
6744
0
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
6745
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
6746
0
        result = utime_nofollow_symlinks(&utime, path->narrow);
6747
0
    else
6748
0
#endif
6749
6750
0
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
6751
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
6752
0
        result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
6753
6754
0
    } else
6755
0
#endif
6756
6757
0
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
6758
0
    if (path->fd != -1)
6759
0
        result = utime_fd(&utime, path->fd);
6760
0
    else
6761
0
#endif
6762
6763
0
    result = utime_default(&utime, path->narrow);
6764
6765
0
    Py_END_ALLOW_THREADS
6766
6767
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
6768
    /* See utime_dir_fd implementation */
6769
    if (result == -1 && errno == ENOSYS) {
6770
        argument_unavailable_error(NULL, "dir_fd");
6771
        return NULL;
6772
    }
6773
#endif
6774
6775
0
    if (result < 0) {
6776
0
        path_error(path);
6777
0
        return NULL;
6778
0
    }
6779
6780
0
#endif /* MS_WINDOWS */
6781
6782
0
    Py_RETURN_NONE;
6783
0
}
6784
6785
/* Process operations */
6786
6787
6788
/*[clinic input]
6789
os._exit
6790
6791
    status: int
6792
6793
Exit to the system with specified status, without normal exit processing.
6794
[clinic start generated code]*/
6795
6796
static PyObject *
6797
os__exit_impl(PyObject *module, int status)
6798
/*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
6799
0
{
6800
0
    _exit(status);
6801
0
    return NULL; /* Make gcc -Wall happy */
6802
0
}
6803
6804
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
6805
#define EXECV_CHAR wchar_t
6806
#else
6807
0
#define EXECV_CHAR char
6808
#endif
6809
6810
#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
6811
static void
6812
free_string_array(EXECV_CHAR **array, Py_ssize_t count)
6813
0
{
6814
0
    Py_ssize_t i;
6815
0
    for (i = 0; i < count; i++)
6816
0
        PyMem_Free(array[i]);
6817
0
    PyMem_Free(array);
6818
0
}
6819
6820
static int
6821
fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
6822
0
{
6823
0
    Py_ssize_t size;
6824
0
    PyObject *ub;
6825
0
    int result = 0;
6826
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
6827
    if (!PyUnicode_FSDecoder(o, &ub))
6828
        return 0;
6829
    *out = PyUnicode_AsWideCharString(ub, &size);
6830
    if (*out)
6831
        result = 1;
6832
#else
6833
0
    if (!PyUnicode_FSConverter(o, &ub))
6834
0
        return 0;
6835
0
    size = PyBytes_GET_SIZE(ub);
6836
0
    *out = PyMem_Malloc(size + 1);
6837
0
    if (*out) {
6838
0
        memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
6839
0
        result = 1;
6840
0
    } else
6841
0
        PyErr_NoMemory();
6842
0
#endif
6843
0
    Py_DECREF(ub);
6844
0
    return result;
6845
0
}
6846
#endif
6847
6848
#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
6849
static EXECV_CHAR**
6850
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
6851
0
{
6852
0
    Py_ssize_t i, pos, envc;
6853
0
    PyObject *keys=NULL, *vals=NULL;
6854
0
    PyObject *key2, *val2, *keyval;
6855
0
    EXECV_CHAR **envlist;
6856
6857
0
    i = PyMapping_Size(env);
6858
0
    if (i < 0)
6859
0
        return NULL;
6860
0
    envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
6861
0
    if (envlist == NULL) {
6862
0
        PyErr_NoMemory();
6863
0
        return NULL;
6864
0
    }
6865
0
    envc = 0;
6866
0
    keys = PyMapping_Keys(env);
6867
0
    if (!keys)
6868
0
        goto error;
6869
0
    vals = PyMapping_Values(env);
6870
0
    if (!vals)
6871
0
        goto error;
6872
0
    if (!PyList_Check(keys) || !PyList_Check(vals)) {
6873
0
        PyErr_Format(PyExc_TypeError,
6874
0
                     "env.keys() or env.values() is not a list");
6875
0
        goto error;
6876
0
    }
6877
6878
0
    for (pos = 0; pos < i; pos++) {
6879
0
        PyObject *key = PyList_GetItem(keys, pos);  // Borrowed ref.
6880
0
        if (key == NULL) {
6881
0
            goto error;
6882
0
        }
6883
0
        PyObject *val = PyList_GetItem(vals, pos);  // Borrowed ref.
6884
0
        if (val == NULL) {
6885
0
            goto error;
6886
0
        }
6887
6888
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
6889
        if (!PyUnicode_FSDecoder(key, &key2))
6890
            goto error;
6891
        if (!PyUnicode_FSDecoder(val, &val2)) {
6892
            Py_DECREF(key2);
6893
            goto error;
6894
        }
6895
        /* Search from index 1 because on Windows starting '=' is allowed for
6896
           defining hidden environment variables. */
6897
        if (PyUnicode_GET_LENGTH(key2) == 0 ||
6898
            PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
6899
        {
6900
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
6901
            Py_DECREF(key2);
6902
            Py_DECREF(val2);
6903
            goto error;
6904
        }
6905
        keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
6906
#else
6907
0
        if (!PyUnicode_FSConverter(key, &key2))
6908
0
            goto error;
6909
0
        if (!PyUnicode_FSConverter(val, &val2)) {
6910
0
            Py_DECREF(key2);
6911
0
            goto error;
6912
0
        }
6913
0
        if (PyBytes_GET_SIZE(key2) == 0 ||
6914
0
            strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
6915
0
        {
6916
0
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
6917
0
            Py_DECREF(key2);
6918
0
            Py_DECREF(val2);
6919
0
            goto error;
6920
0
        }
6921
0
        keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
6922
0
                                             PyBytes_AS_STRING(val2));
6923
0
#endif
6924
0
        Py_DECREF(key2);
6925
0
        Py_DECREF(val2);
6926
0
        if (!keyval)
6927
0
            goto error;
6928
6929
0
        if (!fsconvert_strdup(keyval, &envlist[envc++])) {
6930
0
            Py_DECREF(keyval);
6931
0
            goto error;
6932
0
        }
6933
6934
0
        Py_DECREF(keyval);
6935
0
    }
6936
0
    Py_DECREF(vals);
6937
0
    Py_DECREF(keys);
6938
6939
0
    envlist[envc] = 0;
6940
0
    *envc_ptr = envc;
6941
0
    return envlist;
6942
6943
0
error:
6944
0
    Py_XDECREF(keys);
6945
0
    Py_XDECREF(vals);
6946
0
    free_string_array(envlist, envc);
6947
0
    return NULL;
6948
0
}
6949
6950
static EXECV_CHAR**
6951
parse_arglist(PyObject* argv, Py_ssize_t *argc)
6952
0
{
6953
0
    int i;
6954
0
    EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
6955
0
    if (argvlist == NULL) {
6956
0
        PyErr_NoMemory();
6957
0
        return NULL;
6958
0
    }
6959
0
    for (i = 0; i < *argc; i++) {
6960
0
        PyObject* item = PySequence_ITEM(argv, i);
6961
0
        if (item == NULL)
6962
0
            goto fail;
6963
0
        if (!fsconvert_strdup(item, &argvlist[i])) {
6964
0
            Py_DECREF(item);
6965
0
            goto fail;
6966
0
        }
6967
0
        Py_DECREF(item);
6968
0
    }
6969
0
    argvlist[*argc] = NULL;
6970
0
    return argvlist;
6971
0
fail:
6972
0
    *argc = i;
6973
0
    free_string_array(argvlist, *argc);
6974
0
    return NULL;
6975
0
}
6976
6977
#endif
6978
6979
6980
#ifdef HAVE_EXECV
6981
/*[clinic input]
6982
os.execv
6983
6984
    path: path_t
6985
        Path of executable file.
6986
    argv: object
6987
        Tuple or list of strings.
6988
    /
6989
6990
Execute an executable path with arguments, replacing current process.
6991
[clinic start generated code]*/
6992
6993
static PyObject *
6994
os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
6995
/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
6996
0
{
6997
0
    EXECV_CHAR **argvlist;
6998
0
    Py_ssize_t argc;
6999
7000
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7001
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7002
0
        PyErr_SetString(PyExc_RuntimeError,
7003
0
                        "exec not supported for isolated subinterpreters");
7004
0
        return NULL;
7005
0
    }
7006
7007
    /* execv has two arguments: (path, argv), where
7008
       argv is a list or tuple of strings. */
7009
7010
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7011
0
        PyErr_SetString(PyExc_TypeError,
7012
0
                        "execv() arg 2 must be a tuple or list");
7013
0
        return NULL;
7014
0
    }
7015
0
    argc = PySequence_Size(argv);
7016
0
    if (argc < 1) {
7017
0
        PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
7018
0
        return NULL;
7019
0
    }
7020
7021
0
    argvlist = parse_arglist(argv, &argc);
7022
0
    if (argvlist == NULL) {
7023
0
        return NULL;
7024
0
    }
7025
0
    if (!argvlist[0][0]) {
7026
0
        PyErr_SetString(PyExc_ValueError,
7027
0
            "execv() arg 2 first element cannot be empty");
7028
0
        free_string_array(argvlist, argc);
7029
0
        return NULL;
7030
0
    }
7031
7032
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
7033
0
        free_string_array(argvlist, argc);
7034
0
        return NULL;
7035
0
    }
7036
7037
0
    _Py_BEGIN_SUPPRESS_IPH
7038
#ifdef HAVE_WEXECV
7039
    _wexecv(path->wide, argvlist);
7040
#else
7041
0
    execv(path->narrow, argvlist);
7042
0
#endif
7043
0
    _Py_END_SUPPRESS_IPH
7044
7045
    /* If we get here it's definitely an error */
7046
7047
0
    posix_error();
7048
0
    free_string_array(argvlist, argc);
7049
0
    return NULL;
7050
0
}
7051
7052
7053
/*[clinic input]
7054
os.execve
7055
7056
    path: path_t(allow_fd='PATH_HAVE_FEXECVE')
7057
        Path of executable file.
7058
    argv: object
7059
        Tuple or list of strings.
7060
    env: object
7061
        Dictionary of strings mapping to strings.
7062
7063
Execute an executable path with arguments, replacing current process.
7064
[clinic start generated code]*/
7065
7066
static PyObject *
7067
os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
7068
/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
7069
0
{
7070
0
    EXECV_CHAR **argvlist = NULL;
7071
0
    EXECV_CHAR **envlist;
7072
0
    Py_ssize_t argc, envc;
7073
7074
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7075
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7076
0
        PyErr_SetString(PyExc_RuntimeError,
7077
0
                        "exec not supported for isolated subinterpreters");
7078
0
        return NULL;
7079
0
    }
7080
7081
    /* execve has three arguments: (path, argv, env), where
7082
       argv is a list or tuple of strings and env is a dictionary
7083
       like posix.environ. */
7084
7085
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7086
0
        PyErr_SetString(PyExc_TypeError,
7087
0
                        "execve: argv must be a tuple or list");
7088
0
        goto fail_0;
7089
0
    }
7090
0
    argc = PySequence_Size(argv);
7091
0
    if (argc < 1) {
7092
0
        PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
7093
0
        return NULL;
7094
0
    }
7095
7096
0
    if (!PyMapping_Check(env)) {
7097
0
        PyErr_SetString(PyExc_TypeError,
7098
0
                        "execve: environment must be a mapping object");
7099
0
        goto fail_0;
7100
0
    }
7101
7102
0
    argvlist = parse_arglist(argv, &argc);
7103
0
    if (argvlist == NULL) {
7104
0
        goto fail_0;
7105
0
    }
7106
0
    if (!argvlist[0][0]) {
7107
0
        PyErr_SetString(PyExc_ValueError,
7108
0
            "execve: argv first element cannot be empty");
7109
0
        goto fail_0;
7110
0
    }
7111
7112
0
    envlist = parse_envlist(env, &envc);
7113
0
    if (envlist == NULL)
7114
0
        goto fail_0;
7115
7116
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
7117
0
        goto fail_1;
7118
0
    }
7119
7120
0
    _Py_BEGIN_SUPPRESS_IPH
7121
0
#ifdef HAVE_FEXECVE
7122
0
    if (path->fd > -1)
7123
0
        fexecve(path->fd, argvlist, envlist);
7124
0
    else
7125
0
#endif
7126
#ifdef HAVE_WEXECV
7127
        _wexecve(path->wide, argvlist, envlist);
7128
#else
7129
0
        execve(path->narrow, argvlist, envlist);
7130
0
#endif
7131
0
    _Py_END_SUPPRESS_IPH
7132
7133
    /* If we get here it's definitely an error */
7134
7135
0
    posix_path_error(path);
7136
0
  fail_1:
7137
0
    free_string_array(envlist, envc);
7138
0
  fail_0:
7139
0
    if (argvlist)
7140
0
        free_string_array(argvlist, argc);
7141
0
    return NULL;
7142
0
}
7143
7144
#endif /* HAVE_EXECV */
7145
7146
#ifdef HAVE_POSIX_SPAWN
7147
7148
enum posix_spawn_file_actions_identifier {
7149
    POSIX_SPAWN_OPEN,
7150
    POSIX_SPAWN_CLOSE,
7151
    POSIX_SPAWN_DUP2
7152
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7153
    ,POSIX_SPAWN_CLOSEFROM
7154
#endif
7155
};
7156
7157
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
7158
static int
7159
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
7160
#endif
7161
7162
static int
7163
parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
7164
                        int resetids, int setsid, PyObject *setsigmask,
7165
                        PyObject *setsigdef, PyObject *scheduler,
7166
                        posix_spawnattr_t *attrp)
7167
0
{
7168
0
    long all_flags = 0;
7169
7170
0
    errno = posix_spawnattr_init(attrp);
7171
0
    if (errno) {
7172
0
        posix_error();
7173
0
        return -1;
7174
0
    }
7175
7176
0
    if (setpgroup) {
7177
0
        pid_t pgid = PyLong_AsPid(setpgroup);
7178
0
        if (pgid == (pid_t)-1 && PyErr_Occurred()) {
7179
0
            goto fail;
7180
0
        }
7181
0
        errno = posix_spawnattr_setpgroup(attrp, pgid);
7182
0
        if (errno) {
7183
0
            posix_error();
7184
0
            goto fail;
7185
0
        }
7186
0
        all_flags |= POSIX_SPAWN_SETPGROUP;
7187
0
    }
7188
7189
0
    if (resetids) {
7190
0
        all_flags |= POSIX_SPAWN_RESETIDS;
7191
0
    }
7192
7193
0
    if (setsid) {
7194
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7195
        if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
7196
#endif
7197
0
#ifdef POSIX_SPAWN_SETSID
7198
0
        all_flags |= POSIX_SPAWN_SETSID;
7199
#elif defined(POSIX_SPAWN_SETSID_NP)
7200
        all_flags |= POSIX_SPAWN_SETSID_NP;
7201
#else
7202
        argument_unavailable_error(func_name, "setsid");
7203
        return -1;
7204
#endif
7205
7206
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7207
        } else {
7208
            argument_unavailable_error(func_name, "setsid");
7209
            return -1;
7210
        }
7211
#endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
7212
7213
0
    }
7214
7215
0
#ifdef HAVE_SIGSET_T
7216
0
   if (setsigmask) {
7217
0
        sigset_t set;
7218
0
        if (!_Py_Sigset_Converter(setsigmask, &set)) {
7219
0
            goto fail;
7220
0
        }
7221
0
        errno = posix_spawnattr_setsigmask(attrp, &set);
7222
0
        if (errno) {
7223
0
            posix_error();
7224
0
            goto fail;
7225
0
        }
7226
0
        all_flags |= POSIX_SPAWN_SETSIGMASK;
7227
0
    }
7228
7229
0
    if (setsigdef) {
7230
0
        sigset_t set;
7231
0
        if (!_Py_Sigset_Converter(setsigdef, &set)) {
7232
0
            goto fail;
7233
0
        }
7234
0
        errno = posix_spawnattr_setsigdefault(attrp, &set);
7235
0
        if (errno) {
7236
0
            posix_error();
7237
0
            goto fail;
7238
0
        }
7239
0
        all_flags |= POSIX_SPAWN_SETSIGDEF;
7240
0
    }
7241
#else
7242
    if (setsigmask || setsigdef) {
7243
        PyErr_SetString(PyExc_NotImplementedError,
7244
                        "sigset is not supported on this platform");
7245
        goto fail;
7246
    }
7247
#endif
7248
7249
0
    if (scheduler) {
7250
0
#ifdef POSIX_SPAWN_SETSCHEDULER
7251
0
        PyObject *py_schedpolicy;
7252
0
        PyObject *schedparam_obj;
7253
0
        struct sched_param schedparam;
7254
7255
0
        if (!PyArg_ParseTuple(scheduler, "OO"
7256
0
                        ";A scheduler tuple must have two elements",
7257
0
                        &py_schedpolicy, &schedparam_obj)) {
7258
0
            goto fail;
7259
0
        }
7260
0
        if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
7261
0
            goto fail;
7262
0
        }
7263
0
        if (py_schedpolicy != Py_None) {
7264
0
            int schedpolicy = PyLong_AsInt(py_schedpolicy);
7265
7266
0
            if (schedpolicy == -1 && PyErr_Occurred()) {
7267
0
                goto fail;
7268
0
            }
7269
0
            errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
7270
0
            if (errno) {
7271
0
                posix_error();
7272
0
                goto fail;
7273
0
            }
7274
0
            all_flags |= POSIX_SPAWN_SETSCHEDULER;
7275
0
        }
7276
0
        errno = posix_spawnattr_setschedparam(attrp, &schedparam);
7277
0
        if (errno) {
7278
0
            posix_error();
7279
0
            goto fail;
7280
0
        }
7281
0
        all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
7282
#else
7283
        PyErr_SetString(PyExc_NotImplementedError,
7284
                "The scheduler option is not supported in this system.");
7285
        goto fail;
7286
#endif
7287
0
    }
7288
7289
0
    errno = posix_spawnattr_setflags(attrp, all_flags);
7290
0
    if (errno) {
7291
0
        posix_error();
7292
0
        goto fail;
7293
0
    }
7294
7295
0
    return 0;
7296
7297
0
fail:
7298
0
    (void)posix_spawnattr_destroy(attrp);
7299
0
    return -1;
7300
0
}
7301
7302
static int
7303
parse_file_actions(PyObject *file_actions,
7304
                   posix_spawn_file_actions_t *file_actionsp,
7305
                   PyObject *temp_buffer)
7306
0
{
7307
0
    PyObject *seq;
7308
0
    PyObject *file_action = NULL;
7309
0
    PyObject *tag_obj;
7310
7311
0
    seq = PySequence_Fast(file_actions,
7312
0
                          "file_actions must be a sequence or None");
7313
0
    if (seq == NULL) {
7314
0
        return -1;
7315
0
    }
7316
7317
0
    errno = posix_spawn_file_actions_init(file_actionsp);
7318
0
    if (errno) {
7319
0
        posix_error();
7320
0
        Py_DECREF(seq);
7321
0
        return -1;
7322
0
    }
7323
7324
0
    for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
7325
0
        file_action = PySequence_Fast_GET_ITEM(seq, i);
7326
0
        Py_INCREF(file_action);
7327
0
        if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
7328
0
            PyErr_SetString(PyExc_TypeError,
7329
0
                "Each file_actions element must be a non-empty tuple");
7330
0
            goto fail;
7331
0
        }
7332
0
        long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
7333
0
        if (tag == -1 && PyErr_Occurred()) {
7334
0
            goto fail;
7335
0
        }
7336
7337
        /* Populate the file_actions object */
7338
0
        switch (tag) {
7339
0
            case POSIX_SPAWN_OPEN: {
7340
0
                int fd, oflag;
7341
0
                PyObject *path;
7342
0
                unsigned long mode;
7343
0
                if (!PyArg_ParseTuple(file_action, "OiO&ik"
7344
0
                        ";A open file_action tuple must have 5 elements",
7345
0
                        &tag_obj, &fd, PyUnicode_FSConverter, &path,
7346
0
                        &oflag, &mode))
7347
0
                {
7348
0
                    goto fail;
7349
0
                }
7350
0
                if (PyList_Append(temp_buffer, path)) {
7351
0
                    Py_DECREF(path);
7352
0
                    goto fail;
7353
0
                }
7354
0
                errno = posix_spawn_file_actions_addopen(file_actionsp,
7355
0
                        fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
7356
0
                if (errno) {
7357
0
                    posix_error();
7358
0
                    Py_DECREF(path);
7359
0
                    goto fail;
7360
0
                }
7361
0
                Py_DECREF(path);
7362
0
                break;
7363
0
            }
7364
0
            case POSIX_SPAWN_CLOSE: {
7365
0
                int fd;
7366
0
                if (!PyArg_ParseTuple(file_action, "Oi"
7367
0
                        ";A close file_action tuple must have 2 elements",
7368
0
                        &tag_obj, &fd))
7369
0
                {
7370
0
                    goto fail;
7371
0
                }
7372
0
                errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
7373
0
                if (errno) {
7374
0
                    posix_error();
7375
0
                    goto fail;
7376
0
                }
7377
0
                break;
7378
0
            }
7379
0
            case POSIX_SPAWN_DUP2: {
7380
0
                int fd1, fd2;
7381
0
                if (!PyArg_ParseTuple(file_action, "Oii"
7382
0
                        ";A dup2 file_action tuple must have 3 elements",
7383
0
                        &tag_obj, &fd1, &fd2))
7384
0
                {
7385
0
                    goto fail;
7386
0
                }
7387
0
                errno = posix_spawn_file_actions_adddup2(file_actionsp,
7388
0
                                                         fd1, fd2);
7389
0
                if (errno) {
7390
0
                    posix_error();
7391
0
                    goto fail;
7392
0
                }
7393
0
                break;
7394
0
            }
7395
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7396
            case POSIX_SPAWN_CLOSEFROM: {
7397
                int fd;
7398
                if (!PyArg_ParseTuple(file_action, "Oi"
7399
                        ";A closefrom file_action tuple must have 2 elements",
7400
                        &tag_obj, &fd))
7401
                {
7402
                    goto fail;
7403
                }
7404
                errno = posix_spawn_file_actions_addclosefrom_np(file_actionsp,
7405
                                                                 fd);
7406
                if (errno) {
7407
                    posix_error();
7408
                    goto fail;
7409
                }
7410
                break;
7411
            }
7412
#endif
7413
0
            default: {
7414
0
                PyErr_SetString(PyExc_TypeError,
7415
0
                                "Unknown file_actions identifier");
7416
0
                goto fail;
7417
0
            }
7418
0
        }
7419
0
        Py_DECREF(file_action);
7420
0
    }
7421
7422
0
    Py_DECREF(seq);
7423
0
    return 0;
7424
7425
0
fail:
7426
0
    Py_DECREF(seq);
7427
0
    Py_DECREF(file_action);
7428
0
    (void)posix_spawn_file_actions_destroy(file_actionsp);
7429
0
    return -1;
7430
0
}
7431
7432
7433
static PyObject *
7434
py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
7435
               PyObject *env, PyObject *file_actions,
7436
               PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
7437
               PyObject *setsigdef, PyObject *scheduler)
7438
0
{
7439
0
    const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
7440
0
    EXECV_CHAR **argvlist = NULL;
7441
0
    EXECV_CHAR **envlist = NULL;
7442
0
    posix_spawn_file_actions_t file_actions_buf;
7443
0
    posix_spawn_file_actions_t *file_actionsp = NULL;
7444
0
    posix_spawnattr_t attr;
7445
0
    posix_spawnattr_t *attrp = NULL;
7446
0
    Py_ssize_t argc, envc;
7447
0
    PyObject *result = NULL;
7448
0
    PyObject *temp_buffer = NULL;
7449
0
    pid_t pid;
7450
0
    int err_code;
7451
7452
    /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
7453
       argv is a list or tuple of strings and env is a dictionary
7454
       like posix.environ. */
7455
7456
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7457
0
        PyErr_Format(PyExc_TypeError,
7458
0
                     "%s: argv must be a tuple or list", func_name);
7459
0
        goto exit;
7460
0
    }
7461
0
    argc = PySequence_Size(argv);
7462
0
    if (argc < 1) {
7463
0
        PyErr_Format(PyExc_ValueError,
7464
0
                     "%s: argv must not be empty", func_name);
7465
0
        return NULL;
7466
0
    }
7467
7468
0
    if (!PyMapping_Check(env) && env != Py_None) {
7469
0
        PyErr_Format(PyExc_TypeError,
7470
0
                     "%s: environment must be a mapping object or None", func_name);
7471
0
        goto exit;
7472
0
    }
7473
7474
0
    argvlist = parse_arglist(argv, &argc);
7475
0
    if (argvlist == NULL) {
7476
0
        goto exit;
7477
0
    }
7478
0
    if (!argvlist[0][0]) {
7479
0
        PyErr_Format(PyExc_ValueError,
7480
0
                     "%s: argv first element cannot be empty", func_name);
7481
0
        goto exit;
7482
0
    }
7483
7484
#ifdef USE_DARWIN_NS_GET_ENVIRON
7485
    // There is no environ global in this situation.
7486
    char **environ = NULL;
7487
#endif
7488
7489
0
    if (env == Py_None) {
7490
#ifdef USE_DARWIN_NS_GET_ENVIRON
7491
        environ = *_NSGetEnviron();
7492
#endif
7493
0
        envlist = environ;
7494
0
    } else {
7495
0
        envlist = parse_envlist(env, &envc);
7496
0
        if (envlist == NULL) {
7497
0
            goto exit;
7498
0
        }
7499
0
    }
7500
7501
0
    if (file_actions != NULL && file_actions != Py_None) {
7502
        /* There is a bug in old versions of glibc that makes some of the
7503
         * helper functions for manipulating file actions not copy the provided
7504
         * buffers. The problem is that posix_spawn_file_actions_addopen does not
7505
         * copy the value of path for some old versions of glibc (<2.20).
7506
         * The use of temp_buffer here is a workaround that keeps the
7507
         * python objects that own the buffers alive until posix_spawn gets called.
7508
         * Check https://bugs.python.org/issue33630 and
7509
         * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
7510
0
        temp_buffer = PyList_New(0);
7511
0
        if (!temp_buffer) {
7512
0
            goto exit;
7513
0
        }
7514
0
        if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
7515
0
            goto exit;
7516
0
        }
7517
0
        file_actionsp = &file_actions_buf;
7518
0
    }
7519
7520
0
    if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
7521
0
                                setsigmask, setsigdef, scheduler, &attr)) {
7522
0
        goto exit;
7523
0
    }
7524
0
    attrp = &attr;
7525
7526
0
    if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
7527
0
        goto exit;
7528
0
    }
7529
7530
0
    _Py_BEGIN_SUPPRESS_IPH
7531
0
#ifdef HAVE_POSIX_SPAWNP
7532
0
    if (use_posix_spawnp) {
7533
0
        err_code = posix_spawnp(&pid, path->narrow,
7534
0
                                file_actionsp, attrp, argvlist, envlist);
7535
0
    }
7536
0
    else
7537
0
#endif /* HAVE_POSIX_SPAWNP */
7538
0
    {
7539
0
        err_code = posix_spawn(&pid, path->narrow,
7540
0
                               file_actionsp, attrp, argvlist, envlist);
7541
0
    }
7542
0
    _Py_END_SUPPRESS_IPH
7543
7544
0
    if (err_code) {
7545
0
        errno = err_code;
7546
0
        PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
7547
0
        goto exit;
7548
0
    }
7549
#ifdef _Py_MEMORY_SANITIZER
7550
    __msan_unpoison(&pid, sizeof(pid));
7551
#endif
7552
0
    result = PyLong_FromPid(pid);
7553
7554
0
exit:
7555
0
    if (file_actionsp) {
7556
0
        (void)posix_spawn_file_actions_destroy(file_actionsp);
7557
0
    }
7558
0
    if (attrp) {
7559
0
        (void)posix_spawnattr_destroy(attrp);
7560
0
    }
7561
0
    if (envlist && envlist != environ) {
7562
0
        free_string_array(envlist, envc);
7563
0
    }
7564
0
    if (argvlist) {
7565
0
        free_string_array(argvlist, argc);
7566
0
    }
7567
0
    Py_XDECREF(temp_buffer);
7568
0
    return result;
7569
0
}
7570
7571
7572
/*[clinic input]
7573
7574
os.posix_spawn
7575
    path: path_t
7576
        Path of executable file.
7577
    argv: object
7578
        Tuple or list of strings.
7579
    env: object
7580
        Dictionary of strings mapping to strings.
7581
    /
7582
    *
7583
    file_actions: object(c_default='NULL') = ()
7584
        A sequence of file action tuples.
7585
    setpgroup: object = NULL
7586
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
7587
    resetids: bool = False
7588
        If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
7589
    setsid: bool = False
7590
        If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
7591
    setsigmask: object(c_default='NULL') = ()
7592
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
7593
    setsigdef: object(c_default='NULL') = ()
7594
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
7595
    scheduler: object = NULL
7596
        A tuple with the scheduler policy (optional) and parameters.
7597
7598
Execute the program specified by path in a new process.
7599
[clinic start generated code]*/
7600
7601
static PyObject *
7602
os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
7603
                    PyObject *env, PyObject *file_actions,
7604
                    PyObject *setpgroup, int resetids, int setsid,
7605
                    PyObject *setsigmask, PyObject *setsigdef,
7606
                    PyObject *scheduler)
7607
/*[clinic end generated code: output=14a1098c566bc675 input=808aed1090d84e33]*/
7608
0
{
7609
0
    return py_posix_spawn(0, module, path, argv, env, file_actions,
7610
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
7611
0
                          scheduler);
7612
0
}
7613
 #endif /* HAVE_POSIX_SPAWN */
7614
7615
7616
7617
#ifdef HAVE_POSIX_SPAWNP
7618
/*[clinic input]
7619
7620
os.posix_spawnp
7621
    path: path_t
7622
        Path of executable file.
7623
    argv: object
7624
        Tuple or list of strings.
7625
    env: object
7626
        Dictionary of strings mapping to strings.
7627
    /
7628
    *
7629
    file_actions: object(c_default='NULL') = ()
7630
        A sequence of file action tuples.
7631
    setpgroup: object = NULL
7632
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
7633
    resetids: bool = False
7634
        If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
7635
    setsid: bool = False
7636
        If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
7637
    setsigmask: object(c_default='NULL') = ()
7638
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
7639
    setsigdef: object(c_default='NULL') = ()
7640
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
7641
    scheduler: object = NULL
7642
        A tuple with the scheduler policy (optional) and parameters.
7643
7644
Execute the program specified by path in a new process.
7645
[clinic start generated code]*/
7646
7647
static PyObject *
7648
os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
7649
                     PyObject *env, PyObject *file_actions,
7650
                     PyObject *setpgroup, int resetids, int setsid,
7651
                     PyObject *setsigmask, PyObject *setsigdef,
7652
                     PyObject *scheduler)
7653
/*[clinic end generated code: output=7b9aaefe3031238d input=9e89e616116752a1]*/
7654
0
{
7655
0
    return py_posix_spawn(1, module, path, argv, env, file_actions,
7656
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
7657
0
                          scheduler);
7658
0
}
7659
#endif /* HAVE_POSIX_SPAWNP */
7660
7661
#ifdef HAVE_RTPSPAWN
7662
static intptr_t
7663
_rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
7664
               const char  *envp[])
7665
{
7666
     RTP_ID rtpid;
7667
     int status;
7668
     pid_t res;
7669
     int async_err = 0;
7670
7671
     /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
7672
        uStackSize=0 cannot be used, the default stack size is too small for
7673
        Python. */
7674
     if (envp) {
7675
         rtpid = rtpSpawn(rtpFileName, argv, envp,
7676
                          100, 0x1000000, 0, VX_FP_TASK);
7677
     }
7678
     else {
7679
         rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
7680
                          100, 0x1000000, 0, VX_FP_TASK);
7681
     }
7682
     if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
7683
         do {
7684
             res = waitpid((pid_t)rtpid, &status, 0);
7685
         } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7686
7687
         if (res < 0)
7688
             return RTP_ID_ERROR;
7689
         return ((intptr_t)status);
7690
     }
7691
     return ((intptr_t)rtpid);
7692
}
7693
#endif
7694
7695
#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
7696
/*[clinic input]
7697
os.spawnv
7698
7699
    mode: int
7700
        Mode of process creation.
7701
    path: path_t
7702
        Path of executable file.
7703
    argv: object
7704
        Tuple or list of strings.
7705
    /
7706
7707
Execute the program specified by path in a new process.
7708
[clinic start generated code]*/
7709
7710
static PyObject *
7711
os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
7712
/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
7713
{
7714
    EXECV_CHAR **argvlist;
7715
    int i;
7716
    Py_ssize_t argc;
7717
    intptr_t spawnval;
7718
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
7719
7720
    /* spawnv has three arguments: (mode, path, argv), where
7721
       argv is a list or tuple of strings. */
7722
7723
    if (PyList_Check(argv)) {
7724
        argc = PyList_Size(argv);
7725
        getitem = PyList_GetItem;
7726
    }
7727
    else if (PyTuple_Check(argv)) {
7728
        argc = PyTuple_Size(argv);
7729
        getitem = PyTuple_GetItem;
7730
    }
7731
    else {
7732
        PyErr_SetString(PyExc_TypeError,
7733
                        "spawnv() arg 2 must be a tuple or list");
7734
        return NULL;
7735
    }
7736
    if (argc == 0) {
7737
        PyErr_SetString(PyExc_ValueError,
7738
            "spawnv() arg 2 cannot be empty");
7739
        return NULL;
7740
    }
7741
7742
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
7743
    if (argvlist == NULL) {
7744
        return PyErr_NoMemory();
7745
    }
7746
    for (i = 0; i < argc; i++) {
7747
        if (!fsconvert_strdup((*getitem)(argv, i),
7748
                              &argvlist[i])) {
7749
            free_string_array(argvlist, i);
7750
            PyErr_SetString(
7751
                PyExc_TypeError,
7752
                "spawnv() arg 2 must contain only strings");
7753
            return NULL;
7754
        }
7755
        if (i == 0 && !argvlist[0][0]) {
7756
            free_string_array(argvlist, i + 1);
7757
            PyErr_SetString(
7758
                PyExc_ValueError,
7759
                "spawnv() arg 2 first element cannot be empty");
7760
            return NULL;
7761
        }
7762
    }
7763
    argvlist[argc] = NULL;
7764
7765
#if !defined(HAVE_RTPSPAWN)
7766
    if (mode == _OLD_P_OVERLAY)
7767
        mode = _P_OVERLAY;
7768
#endif
7769
7770
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
7771
                    Py_None) < 0) {
7772
        free_string_array(argvlist, argc);
7773
        return NULL;
7774
    }
7775
7776
    Py_BEGIN_ALLOW_THREADS
7777
    _Py_BEGIN_SUPPRESS_IPH
7778
#ifdef HAVE_WSPAWNV
7779
    spawnval = _wspawnv(mode, path->wide, argvlist);
7780
#elif defined(HAVE_RTPSPAWN)
7781
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
7782
#else
7783
    spawnval = _spawnv(mode, path->narrow, argvlist);
7784
#endif
7785
    _Py_END_SUPPRESS_IPH
7786
    Py_END_ALLOW_THREADS
7787
7788
    int saved_errno = errno;
7789
    free_string_array(argvlist, argc);
7790
7791
    if (spawnval == -1) {
7792
        errno = saved_errno;
7793
        posix_error();
7794
        return NULL;
7795
    }
7796
    return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
7797
}
7798
7799
/*[clinic input]
7800
os.spawnve
7801
7802
    mode: int
7803
        Mode of process creation.
7804
    path: path_t
7805
        Path of executable file.
7806
    argv: object
7807
        Tuple or list of strings.
7808
    env: object
7809
        Dictionary of strings mapping to strings.
7810
    /
7811
7812
Execute the program specified by path in a new process.
7813
[clinic start generated code]*/
7814
7815
static PyObject *
7816
os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
7817
                PyObject *env)
7818
/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
7819
{
7820
    EXECV_CHAR **argvlist;
7821
    EXECV_CHAR **envlist;
7822
    PyObject *res = NULL;
7823
    Py_ssize_t argc, i, envc;
7824
    intptr_t spawnval;
7825
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
7826
    Py_ssize_t lastarg = 0;
7827
7828
    /* spawnve has four arguments: (mode, path, argv, env), where
7829
       argv is a list or tuple of strings and env is a dictionary
7830
       like posix.environ. */
7831
7832
    if (PyList_Check(argv)) {
7833
        argc = PyList_Size(argv);
7834
        getitem = PyList_GetItem;
7835
    }
7836
    else if (PyTuple_Check(argv)) {
7837
        argc = PyTuple_Size(argv);
7838
        getitem = PyTuple_GetItem;
7839
    }
7840
    else {
7841
        PyErr_SetString(PyExc_TypeError,
7842
                        "spawnve() arg 2 must be a tuple or list");
7843
        goto fail_0;
7844
    }
7845
    if (argc == 0) {
7846
        PyErr_SetString(PyExc_ValueError,
7847
            "spawnve() arg 2 cannot be empty");
7848
        goto fail_0;
7849
    }
7850
    if (!PyMapping_Check(env)) {
7851
        PyErr_SetString(PyExc_TypeError,
7852
                        "spawnve() arg 3 must be a mapping object");
7853
        goto fail_0;
7854
    }
7855
7856
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
7857
    if (argvlist == NULL) {
7858
        PyErr_NoMemory();
7859
        goto fail_0;
7860
    }
7861
    for (i = 0; i < argc; i++) {
7862
        if (!fsconvert_strdup((*getitem)(argv, i),
7863
                              &argvlist[i]))
7864
        {
7865
            lastarg = i;
7866
            goto fail_1;
7867
        }
7868
        if (i == 0 && !argvlist[0][0]) {
7869
            lastarg = i + 1;
7870
            PyErr_SetString(
7871
                PyExc_ValueError,
7872
                "spawnv() arg 2 first element cannot be empty");
7873
            goto fail_1;
7874
        }
7875
    }
7876
    lastarg = argc;
7877
    argvlist[argc] = NULL;
7878
7879
    envlist = parse_envlist(env, &envc);
7880
    if (envlist == NULL)
7881
        goto fail_1;
7882
7883
#if !defined(HAVE_RTPSPAWN)
7884
    if (mode == _OLD_P_OVERLAY)
7885
        mode = _P_OVERLAY;
7886
#endif
7887
7888
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
7889
        goto fail_2;
7890
    }
7891
7892
    Py_BEGIN_ALLOW_THREADS
7893
    _Py_BEGIN_SUPPRESS_IPH
7894
#ifdef HAVE_WSPAWNV
7895
    spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
7896
#elif defined(HAVE_RTPSPAWN)
7897
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
7898
                           (const char **)envlist);
7899
#else
7900
    spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
7901
#endif
7902
    _Py_END_SUPPRESS_IPH
7903
    Py_END_ALLOW_THREADS
7904
7905
    if (spawnval == -1)
7906
        (void) posix_error();
7907
    else
7908
        res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
7909
7910
  fail_2:
7911
    while (--envc >= 0) {
7912
        PyMem_Free(envlist[envc]);
7913
    }
7914
    PyMem_Free(envlist);
7915
  fail_1:
7916
    free_string_array(argvlist, lastarg);
7917
  fail_0:
7918
    return res;
7919
}
7920
7921
#endif /* HAVE_SPAWNV */
7922
7923
#ifdef HAVE_FORK
7924
7925
/* Helper function to validate arguments.
7926
   Returns 0 on success.  non-zero on failure with a TypeError raised.
7927
   If obj is non-NULL it must be callable.  */
7928
static int
7929
check_null_or_callable(PyObject *obj, const char* obj_name)
7930
6
{
7931
6
    if (obj && !PyCallable_Check(obj)) {
7932
0
        PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
7933
0
                     obj_name, _PyType_Name(Py_TYPE(obj)));
7934
0
        return -1;
7935
0
    }
7936
6
    return 0;
7937
6
}
7938
7939
/*[clinic input]
7940
os.register_at_fork
7941
7942
    *
7943
    before: object=NULL
7944
        A callable to be called in the parent before the fork() syscall.
7945
    after_in_child: object=NULL
7946
        A callable to be called in the child after fork().
7947
    after_in_parent: object=NULL
7948
        A callable to be called in the parent after fork().
7949
7950
Register callables to be called when forking a new process.
7951
7952
'before' callbacks are called in reverse order.
7953
'after_in_child' and 'after_in_parent' callbacks are called in order.
7954
7955
[clinic start generated code]*/
7956
7957
static PyObject *
7958
os_register_at_fork_impl(PyObject *module, PyObject *before,
7959
                         PyObject *after_in_child, PyObject *after_in_parent)
7960
/*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
7961
2
{
7962
2
    PyInterpreterState *interp;
7963
7964
2
    if (!before && !after_in_child && !after_in_parent) {
7965
0
        PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
7966
0
        return NULL;
7967
0
    }
7968
2
    if (check_null_or_callable(before, "before") ||
7969
2
        check_null_or_callable(after_in_child, "after_in_child") ||
7970
2
        check_null_or_callable(after_in_parent, "after_in_parent")) {
7971
0
        return NULL;
7972
0
    }
7973
2
    interp = _PyInterpreterState_GET();
7974
7975
2
    if (register_at_forker(&interp->before_forkers, before)) {
7976
0
        return NULL;
7977
0
    }
7978
2
    if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
7979
0
        return NULL;
7980
0
    }
7981
2
    if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
7982
0
        return NULL;
7983
0
    }
7984
2
    Py_RETURN_NONE;
7985
2
}
7986
#endif /* HAVE_FORK */
7987
7988
#if defined(HAVE_FORK1) || defined(HAVE_FORKPTY) || defined(HAVE_FORK)
7989
// Common code to raise a warning if we detect there is more than one thread
7990
// running in the process. Best effort, silent if unable to count threads.
7991
// Constraint: Quick. Never overcounts. Never leaves an error set.
7992
//
7993
// This should only be called from the parent process after
7994
// PyOS_AfterFork_Parent().
7995
static void
7996
warn_about_fork_with_threads(const char* name)
7997
0
{
7998
    // It's not safe to issue the warning while the world is stopped, because
7999
    // other threads might be holding locks that we need, which would deadlock.
8000
0
    assert(!_PyRuntime.stoptheworld.world_stopped);
8001
8002
    // TODO: Consider making an `os` module API to return the current number
8003
    // of threads in the process. That'd presumably use this platform code but
8004
    // raise an error rather than using the inaccurate fallback.
8005
0
    Py_ssize_t num_python_threads = 0;
8006
#if defined(__APPLE__) && defined(HAVE_GETPID)
8007
    mach_port_t macos_self = mach_task_self();
8008
    mach_port_t macos_task;
8009
    if (task_for_pid(macos_self, getpid(), &macos_task) == KERN_SUCCESS) {
8010
        thread_array_t macos_threads;
8011
        mach_msg_type_number_t macos_n_threads;
8012
        if (task_threads(macos_task, &macos_threads,
8013
                         &macos_n_threads) == KERN_SUCCESS) {
8014
            num_python_threads = macos_n_threads;
8015
        }
8016
    }
8017
#elif defined(__linux__)
8018
    // Linux /proc/self/stat 20th field is the number of threads.
8019
0
    FILE* proc_stat = fopen("/proc/self/stat", "r");
8020
0
    if (proc_stat) {
8021
0
        size_t n;
8022
        // Size chosen arbitrarily. ~60% more bytes than a 20th column index
8023
        // observed on the author's workstation.
8024
0
        char stat_line[160];
8025
0
        n = fread(&stat_line, 1, 159, proc_stat);
8026
0
        stat_line[n] = '\0';
8027
0
        fclose(proc_stat);
8028
8029
0
        char *saveptr = NULL;
8030
0
        char *field = strtok_r(stat_line, " ", &saveptr);
8031
0
        unsigned int idx;
8032
0
        for (idx = 19; idx && field; --idx) {
8033
0
            field = strtok_r(NULL, " ", &saveptr);
8034
0
        }
8035
0
        if (idx == 0 && field) {  // found the 20th field
8036
0
            num_python_threads = atoi(field);  // 0 on error
8037
0
        }
8038
0
    }
8039
0
#endif
8040
0
    if (num_python_threads <= 0) {
8041
        // Fall back to just the number our threading module knows about.
8042
        // An incomplete view of the world, but better than nothing.
8043
0
        PyObject *threading = PyImport_GetModule(&_Py_ID(threading));
8044
0
        if (!threading) {
8045
0
            PyErr_Clear();
8046
0
            return;
8047
0
        }
8048
0
        PyObject *threading_active =
8049
0
                PyObject_GetAttr(threading, &_Py_ID(_active));
8050
0
        if (!threading_active) {
8051
0
            PyErr_Clear();
8052
0
            Py_DECREF(threading);
8053
0
            return;
8054
0
        }
8055
0
        PyObject *threading_limbo =
8056
0
                PyObject_GetAttr(threading, &_Py_ID(_limbo));
8057
0
        if (!threading_limbo) {
8058
0
            PyErr_Clear();
8059
0
            Py_DECREF(threading);
8060
0
            Py_DECREF(threading_active);
8061
0
            return;
8062
0
        }
8063
0
        Py_DECREF(threading);
8064
        // Duplicating what threading.active_count() does but without holding
8065
        // threading._active_limbo_lock so our count could be inaccurate if
8066
        // these dicts are mid-update from another thread.  Not a big deal.
8067
        // Worst case if someone replaced threading._active or threading._limbo
8068
        // with non-dicts, we get -1 from *Length() below and undercount.
8069
        // Nobody should, but we're best effort so we clear errors and move on.
8070
0
        num_python_threads = (PyMapping_Length(threading_active)
8071
0
                              + PyMapping_Length(threading_limbo));
8072
0
        PyErr_Clear();
8073
0
        Py_DECREF(threading_active);
8074
0
        Py_DECREF(threading_limbo);
8075
0
    }
8076
0
    if (num_python_threads > 1) {
8077
0
        PyErr_WarnFormat(
8078
0
                PyExc_DeprecationWarning, 1,
8079
0
#ifdef HAVE_GETPID
8080
0
                "This process (pid=%d) is multi-threaded, "
8081
#else
8082
                "This process is multi-threaded, "
8083
#endif
8084
0
                "use of %s() may lead to deadlocks in the child.",
8085
0
#ifdef HAVE_GETPID
8086
0
                getpid(),
8087
0
#endif
8088
0
                name);
8089
0
        PyErr_Clear();
8090
0
    }
8091
0
}
8092
#endif  // HAVE_FORK1 || HAVE_FORKPTY || HAVE_FORK
8093
8094
#ifdef HAVE_FORK1
8095
/*[clinic input]
8096
os.fork1
8097
8098
Fork a child process with a single multiplexed (i.e., not bound) thread.
8099
8100
Return 0 to child process and PID of child to parent process.
8101
[clinic start generated code]*/
8102
8103
static PyObject *
8104
os_fork1_impl(PyObject *module)
8105
/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
8106
{
8107
    pid_t pid;
8108
8109
    PyInterpreterState *interp = _PyInterpreterState_GET();
8110
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8111
        PyErr_SetString(PyExc_PythonFinalizationError,
8112
                        "can't fork at interpreter shutdown");
8113
        return NULL;
8114
    }
8115
    if (!_Py_IsMainInterpreter(interp)) {
8116
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
8117
        return NULL;
8118
    }
8119
    PyOS_BeforeFork();
8120
    pid = fork1();
8121
    int saved_errno = errno;
8122
    if (pid == 0) {
8123
        /* child: this clobbers and resets the import lock. */
8124
        PyOS_AfterFork_Child();
8125
    } else {
8126
        /* parent: release the import lock. */
8127
        PyOS_AfterFork_Parent();
8128
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8129
        warn_about_fork_with_threads("fork1");
8130
    }
8131
    if (pid == -1) {
8132
        errno = saved_errno;
8133
        return posix_error();
8134
    }
8135
    return PyLong_FromPid(pid);
8136
}
8137
#endif /* HAVE_FORK1 */
8138
8139
8140
#ifdef HAVE_FORK
8141
/*[clinic input]
8142
os.fork
8143
8144
Fork a child process.
8145
8146
Return 0 to child process and PID of child to parent process.
8147
[clinic start generated code]*/
8148
8149
static PyObject *
8150
os_fork_impl(PyObject *module)
8151
/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
8152
0
{
8153
0
    pid_t pid;
8154
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
8155
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8156
0
        PyErr_SetString(PyExc_PythonFinalizationError,
8157
0
                        "can't fork at interpreter shutdown");
8158
0
        return NULL;
8159
0
    }
8160
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) {
8161
0
        PyErr_SetString(PyExc_RuntimeError,
8162
0
                        "fork not supported for isolated subinterpreters");
8163
0
        return NULL;
8164
0
    }
8165
0
    if (PySys_Audit("os.fork", NULL) < 0) {
8166
0
        return NULL;
8167
0
    }
8168
0
    PyOS_BeforeFork();
8169
0
    pid = fork();
8170
0
    int saved_errno = errno;
8171
0
    if (pid == 0) {
8172
        /* child: this clobbers and resets the import lock. */
8173
0
        PyOS_AfterFork_Child();
8174
0
    } else {
8175
        /* parent: release the import lock. */
8176
0
        PyOS_AfterFork_Parent();
8177
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8178
0
        warn_about_fork_with_threads("fork");
8179
0
    }
8180
0
    if (pid == -1) {
8181
0
        errno = saved_errno;
8182
0
        return posix_error();
8183
0
    }
8184
0
    return PyLong_FromPid(pid);
8185
0
}
8186
#endif /* HAVE_FORK */
8187
8188
8189
#ifdef HAVE_SCHED_H
8190
#ifdef HAVE_SCHED_GET_PRIORITY_MAX
8191
/*[clinic input]
8192
os.sched_get_priority_max
8193
8194
    policy: int
8195
8196
Get the maximum scheduling priority for policy.
8197
[clinic start generated code]*/
8198
8199
static PyObject *
8200
os_sched_get_priority_max_impl(PyObject *module, int policy)
8201
/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
8202
0
{
8203
0
    int max;
8204
8205
0
    max = sched_get_priority_max(policy);
8206
0
    if (max < 0)
8207
0
        return posix_error();
8208
0
    return PyLong_FromLong(max);
8209
0
}
8210
8211
8212
/*[clinic input]
8213
os.sched_get_priority_min
8214
8215
    policy: int
8216
8217
Get the minimum scheduling priority for policy.
8218
[clinic start generated code]*/
8219
8220
static PyObject *
8221
os_sched_get_priority_min_impl(PyObject *module, int policy)
8222
/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
8223
0
{
8224
0
    int min = sched_get_priority_min(policy);
8225
0
    if (min < 0)
8226
0
        return posix_error();
8227
0
    return PyLong_FromLong(min);
8228
0
}
8229
#endif /* HAVE_SCHED_GET_PRIORITY_MAX */
8230
8231
8232
#ifdef HAVE_SCHED_SETSCHEDULER
8233
/*[clinic input]
8234
os.sched_getscheduler
8235
    pid: pid_t
8236
    /
8237
8238
Get the scheduling policy for the process identified by pid.
8239
8240
Passing 0 for pid returns the scheduling policy for the calling process.
8241
[clinic start generated code]*/
8242
8243
static PyObject *
8244
os_sched_getscheduler_impl(PyObject *module, pid_t pid)
8245
/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
8246
0
{
8247
0
    int policy;
8248
8249
0
    policy = sched_getscheduler(pid);
8250
0
    if (policy < 0)
8251
0
        return posix_error();
8252
0
    return PyLong_FromLong(policy);
8253
0
}
8254
#endif /* HAVE_SCHED_SETSCHEDULER */
8255
8256
8257
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
8258
/*[clinic input]
8259
class os.sched_param "PyObject *" "SchedParamType"
8260
8261
@classmethod
8262
os.sched_param.__new__
8263
8264
    sched_priority: object
8265
        A scheduling parameter.
8266
8267
Currently has only one field: sched_priority
8268
[clinic start generated code]*/
8269
8270
static PyObject *
8271
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
8272
/*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
8273
0
{
8274
0
    PyObject *res;
8275
8276
0
    res = PyStructSequence_New(type);
8277
0
    if (!res)
8278
0
        return NULL;
8279
0
    PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority));
8280
0
    return res;
8281
0
}
8282
8283
static PyObject *
8284
os_sched_param_reduce(PyObject *self, PyObject *Py_UNUSED(dummy))
8285
0
{
8286
0
    return Py_BuildValue("(O(N))", Py_TYPE(self), PyStructSequence_GetItem(self, 0));
8287
0
}
8288
8289
static PyMethodDef os_sched_param_reduce_method = {
8290
    "__reduce__", os_sched_param_reduce, METH_NOARGS | METH_COEXIST, NULL,
8291
};
8292
8293
PyDoc_VAR(os_sched_param__doc__);
8294
8295
static PyStructSequence_Field sched_param_fields[] = {
8296
    {"sched_priority", "the scheduling priority"},
8297
    {0}
8298
};
8299
8300
static PyStructSequence_Desc sched_param_desc = {
8301
    "sched_param", /* name */
8302
    os_sched_param__doc__, /* doc */
8303
    sched_param_fields,
8304
    1
8305
};
8306
8307
static int
8308
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
8309
0
{
8310
0
    long priority;
8311
8312
0
    if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
8313
0
        PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
8314
0
        return 0;
8315
0
    }
8316
0
    priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
8317
0
    if (priority == -1 && PyErr_Occurred())
8318
0
        return 0;
8319
0
    if (priority > INT_MAX || priority < INT_MIN) {
8320
0
        PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
8321
0
        return 0;
8322
0
    }
8323
0
    res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
8324
0
    return 1;
8325
0
}
8326
#endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
8327
8328
8329
#ifdef HAVE_SCHED_SETSCHEDULER
8330
/*[clinic input]
8331
os.sched_setscheduler
8332
8333
    pid: pid_t
8334
    policy: int
8335
    param as param_obj: object
8336
    /
8337
8338
Set the scheduling policy for the process identified by pid.
8339
8340
If pid is 0, the calling process is changed.
8341
param is an instance of sched_param.
8342
[clinic start generated code]*/
8343
8344
static PyObject *
8345
os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
8346
                           PyObject *param_obj)
8347
/*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
8348
0
{
8349
0
    struct sched_param param;
8350
0
    if (!convert_sched_param(module, param_obj, &param)) {
8351
0
        return NULL;
8352
0
    }
8353
8354
    /*
8355
    ** sched_setscheduler() returns 0 in Linux, but the previous
8356
    ** scheduling policy under Solaris/Illumos, and others.
8357
    ** On error, -1 is returned in all Operating Systems.
8358
    */
8359
0
    if (sched_setscheduler(pid, policy, &param) == -1)
8360
0
        return posix_error();
8361
0
    Py_RETURN_NONE;
8362
0
}
8363
#endif  /* HAVE_SCHED_SETSCHEDULER*/
8364
8365
8366
#ifdef HAVE_SCHED_SETPARAM
8367
/*[clinic input]
8368
os.sched_getparam
8369
    pid: pid_t
8370
    /
8371
8372
Returns scheduling parameters for the process identified by pid.
8373
8374
If pid is 0, returns parameters for the calling process.
8375
Return value is an instance of sched_param.
8376
[clinic start generated code]*/
8377
8378
static PyObject *
8379
os_sched_getparam_impl(PyObject *module, pid_t pid)
8380
/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
8381
0
{
8382
0
    struct sched_param param;
8383
0
    PyObject *result;
8384
0
    PyObject *priority;
8385
8386
0
    if (sched_getparam(pid, &param))
8387
0
        return posix_error();
8388
0
    PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
8389
0
    result = PyStructSequence_New((PyTypeObject *)SchedParamType);
8390
0
    if (!result)
8391
0
        return NULL;
8392
0
    priority = PyLong_FromLong(param.sched_priority);
8393
0
    if (!priority) {
8394
0
        Py_DECREF(result);
8395
0
        return NULL;
8396
0
    }
8397
0
    PyStructSequence_SET_ITEM(result, 0, priority);
8398
0
    return result;
8399
0
}
8400
8401
8402
/*[clinic input]
8403
os.sched_setparam
8404
    pid: pid_t
8405
    param as param_obj: object
8406
    /
8407
8408
Set scheduling parameters for the process identified by pid.
8409
8410
If pid is 0, sets parameters for the calling process.
8411
param should be an instance of sched_param.
8412
[clinic start generated code]*/
8413
8414
static PyObject *
8415
os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
8416
/*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
8417
0
{
8418
0
    struct sched_param param;
8419
0
    if (!convert_sched_param(module, param_obj, &param)) {
8420
0
        return NULL;
8421
0
    }
8422
8423
0
    if (sched_setparam(pid, &param))
8424
0
        return posix_error();
8425
0
    Py_RETURN_NONE;
8426
0
}
8427
#endif /* HAVE_SCHED_SETPARAM */
8428
8429
8430
#ifdef HAVE_SCHED_RR_GET_INTERVAL
8431
/*[clinic input]
8432
os.sched_rr_get_interval -> double
8433
    pid: pid_t
8434
    /
8435
8436
Return the round-robin quantum for the process identified by pid, in seconds.
8437
8438
Value returned is a float.
8439
[clinic start generated code]*/
8440
8441
static double
8442
os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
8443
/*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
8444
0
{
8445
0
    struct timespec interval;
8446
0
    if (sched_rr_get_interval(pid, &interval)) {
8447
0
        posix_error();
8448
0
        return -1.0;
8449
0
    }
8450
#ifdef _Py_MEMORY_SANITIZER
8451
    __msan_unpoison(&interval, sizeof(interval));
8452
#endif
8453
0
    return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
8454
0
}
8455
#endif /* HAVE_SCHED_RR_GET_INTERVAL */
8456
8457
8458
/*[clinic input]
8459
os.sched_yield
8460
8461
Voluntarily relinquish the CPU.
8462
[clinic start generated code]*/
8463
8464
static PyObject *
8465
os_sched_yield_impl(PyObject *module)
8466
/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
8467
0
{
8468
0
    int result;
8469
0
    Py_BEGIN_ALLOW_THREADS
8470
0
    result = sched_yield();
8471
0
    Py_END_ALLOW_THREADS
8472
0
    if (result < 0) {
8473
0
        return posix_error();
8474
0
    }
8475
0
    Py_RETURN_NONE;
8476
0
}
8477
8478
#ifdef HAVE_SCHED_SETAFFINITY
8479
/* The minimum number of CPUs allocated in a cpu_set_t */
8480
static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
8481
8482
/*[clinic input]
8483
os.sched_setaffinity
8484
    pid: pid_t
8485
    mask : object
8486
    /
8487
8488
Set the CPU affinity of the process identified by pid to mask.
8489
8490
mask should be an iterable of integers identifying CPUs.
8491
[clinic start generated code]*/
8492
8493
static PyObject *
8494
os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
8495
/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
8496
0
{
8497
0
    int ncpus;
8498
0
    size_t setsize;
8499
0
    cpu_set_t *cpu_set = NULL;
8500
0
    PyObject *iterator = NULL, *item;
8501
8502
0
    iterator = PyObject_GetIter(mask);
8503
0
    if (iterator == NULL)
8504
0
        return NULL;
8505
8506
0
    ncpus = NCPUS_START;
8507
0
    setsize = CPU_ALLOC_SIZE(ncpus);
8508
0
    cpu_set = CPU_ALLOC(ncpus);
8509
0
    if (cpu_set == NULL) {
8510
0
        PyErr_NoMemory();
8511
0
        goto error;
8512
0
    }
8513
0
    CPU_ZERO_S(setsize, cpu_set);
8514
8515
0
    while ((item = PyIter_Next(iterator))) {
8516
0
        long cpu;
8517
0
        if (!PyIndex_Check(item)) {
8518
0
            PyErr_Format(PyExc_TypeError,
8519
0
                        "expected an iterator of ints, "
8520
0
                        "but iterator yielded %R",
8521
0
                        Py_TYPE(item));
8522
0
            Py_DECREF(item);
8523
0
            goto error;
8524
0
        }
8525
0
        cpu = PyLong_AsLong(item);
8526
0
        Py_DECREF(item);
8527
0
        if (cpu < 0) {
8528
0
            if (!PyErr_Occurred())
8529
0
                PyErr_SetString(PyExc_ValueError, "negative CPU number");
8530
0
            goto error;
8531
0
        }
8532
0
        if (cpu > INT_MAX - 1) {
8533
0
            PyErr_SetString(PyExc_OverflowError, "CPU number too large");
8534
0
            goto error;
8535
0
        }
8536
0
        if (cpu >= ncpus) {
8537
            /* Grow CPU mask to fit the CPU number */
8538
0
            int newncpus = ncpus;
8539
0
            cpu_set_t *newmask;
8540
0
            size_t newsetsize;
8541
0
            while (newncpus <= cpu) {
8542
0
                if (newncpus > INT_MAX / 2)
8543
0
                    newncpus = cpu + 1;
8544
0
                else
8545
0
                    newncpus = newncpus * 2;
8546
0
            }
8547
0
            newmask = CPU_ALLOC(newncpus);
8548
0
            if (newmask == NULL) {
8549
0
                PyErr_NoMemory();
8550
0
                goto error;
8551
0
            }
8552
0
            newsetsize = CPU_ALLOC_SIZE(newncpus);
8553
0
            CPU_ZERO_S(newsetsize, newmask);
8554
0
            memcpy(newmask, cpu_set, setsize);
8555
0
            CPU_FREE(cpu_set);
8556
0
            setsize = newsetsize;
8557
0
            cpu_set = newmask;
8558
0
            ncpus = newncpus;
8559
0
        }
8560
0
        CPU_SET_S(cpu, setsize, cpu_set);
8561
0
    }
8562
0
    if (PyErr_Occurred()) {
8563
0
        goto error;
8564
0
    }
8565
0
    Py_CLEAR(iterator);
8566
8567
0
    if (sched_setaffinity(pid, setsize, cpu_set)) {
8568
0
        posix_error();
8569
0
        goto error;
8570
0
    }
8571
0
    CPU_FREE(cpu_set);
8572
0
    Py_RETURN_NONE;
8573
8574
0
error:
8575
0
    if (cpu_set)
8576
0
        CPU_FREE(cpu_set);
8577
0
    Py_XDECREF(iterator);
8578
0
    return NULL;
8579
0
}
8580
8581
8582
/*[clinic input]
8583
os.sched_getaffinity
8584
    pid: pid_t
8585
    /
8586
8587
Return the affinity of the process identified by pid (or the current process if zero).
8588
8589
The affinity is returned as a set of CPU identifiers.
8590
[clinic start generated code]*/
8591
8592
static PyObject *
8593
os_sched_getaffinity_impl(PyObject *module, pid_t pid)
8594
/*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
8595
0
{
8596
0
    int ncpus = NCPUS_START;
8597
0
    size_t setsize;
8598
0
    cpu_set_t *mask;
8599
8600
0
    while (1) {
8601
0
        setsize = CPU_ALLOC_SIZE(ncpus);
8602
0
        mask = CPU_ALLOC(ncpus);
8603
0
        if (mask == NULL) {
8604
0
            return PyErr_NoMemory();
8605
0
        }
8606
0
        if (sched_getaffinity(pid, setsize, mask) == 0) {
8607
0
            break;
8608
0
        }
8609
0
        CPU_FREE(mask);
8610
0
        if (errno != EINVAL) {
8611
0
            return posix_error();
8612
0
        }
8613
0
        if (ncpus > INT_MAX / 2) {
8614
0
            PyErr_SetString(PyExc_OverflowError,
8615
0
                            "could not allocate a large enough CPU set");
8616
0
            return NULL;
8617
0
        }
8618
0
        ncpus *= 2;
8619
0
    }
8620
8621
0
    PyObject *res = PySet_New(NULL);
8622
0
    if (res == NULL) {
8623
0
        goto error;
8624
0
    }
8625
8626
0
    int cpu = 0;
8627
0
    int count = CPU_COUNT_S(setsize, mask);
8628
0
    for (; count; cpu++) {
8629
0
        if (CPU_ISSET_S(cpu, setsize, mask)) {
8630
0
            PyObject *cpu_num = PyLong_FromLong(cpu);
8631
0
            --count;
8632
0
            if (cpu_num == NULL) {
8633
0
                goto error;
8634
0
            }
8635
0
            if (PySet_Add(res, cpu_num)) {
8636
0
                Py_DECREF(cpu_num);
8637
0
                goto error;
8638
0
            }
8639
0
            Py_DECREF(cpu_num);
8640
0
        }
8641
0
    }
8642
0
    CPU_FREE(mask);
8643
0
    return res;
8644
8645
0
error:
8646
0
    if (mask) {
8647
0
        CPU_FREE(mask);
8648
0
    }
8649
0
    Py_XDECREF(res);
8650
0
    return NULL;
8651
0
}
8652
#endif /* HAVE_SCHED_SETAFFINITY */
8653
8654
#endif /* HAVE_SCHED_H */
8655
8656
8657
#ifdef HAVE_POSIX_OPENPT
8658
/*[clinic input]
8659
os.posix_openpt -> int
8660
8661
    oflag: int
8662
    /
8663
8664
Open and return a file descriptor for a master pseudo-terminal device.
8665
8666
Performs a posix_openpt() C function call. The oflag argument is used to
8667
set file status flags and file access modes as specified in the manual page
8668
of posix_openpt() of your system.
8669
[clinic start generated code]*/
8670
8671
static int
8672
os_posix_openpt_impl(PyObject *module, int oflag)
8673
/*[clinic end generated code: output=ee0bc2624305fc79 input=0de33d0e29693caa]*/
8674
0
{
8675
0
    int fd;
8676
8677
0
#if defined(O_CLOEXEC)
8678
0
    oflag |= O_CLOEXEC;
8679
0
#endif
8680
8681
0
    fd = posix_openpt(oflag);
8682
0
    if (fd == -1) {
8683
0
        posix_error();
8684
0
        return -1;
8685
0
    }
8686
8687
    // Just in case, likely a no-op given O_CLOEXEC above.
8688
0
    if (_Py_set_inheritable(fd, 0, NULL) < 0) {
8689
0
        close(fd);
8690
0
        return -1;
8691
0
    }
8692
8693
0
    return fd;
8694
0
}
8695
#endif /* HAVE_POSIX_OPENPT */
8696
8697
#ifdef HAVE_GRANTPT
8698
/*[clinic input]
8699
os.grantpt
8700
8701
    fd: fildes
8702
        File descriptor of a master pseudo-terminal device.
8703
    /
8704
8705
Grant access to the slave pseudo-terminal device.
8706
8707
Performs a grantpt() C function call.
8708
[clinic start generated code]*/
8709
8710
static PyObject *
8711
os_grantpt_impl(PyObject *module, int fd)
8712
/*[clinic end generated code: output=dfd580015cf548ab input=0668e3b96760e849]*/
8713
0
{
8714
0
    int ret;
8715
0
    int saved_errno;
8716
0
    PyOS_sighandler_t sig_saved;
8717
8718
0
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
8719
8720
0
    ret = grantpt(fd);
8721
0
    if (ret == -1)
8722
0
        saved_errno = errno;
8723
8724
0
    PyOS_setsig(SIGCHLD, sig_saved);
8725
8726
0
    if (ret == -1) {
8727
0
        errno = saved_errno;
8728
0
        return posix_error();
8729
0
    }
8730
8731
0
    Py_RETURN_NONE;
8732
0
}
8733
#endif /* HAVE_GRANTPT */
8734
8735
#ifdef HAVE_UNLOCKPT
8736
/*[clinic input]
8737
os.unlockpt
8738
8739
    fd: fildes
8740
        File descriptor of a master pseudo-terminal device.
8741
    /
8742
8743
Unlock a pseudo-terminal master/slave pair.
8744
8745
Performs an unlockpt() C function call.
8746
[clinic start generated code]*/
8747
8748
static PyObject *
8749
os_unlockpt_impl(PyObject *module, int fd)
8750
/*[clinic end generated code: output=e08d354dec12d30c input=de7ab1f59f69a2b4]*/
8751
0
{
8752
0
    if (unlockpt(fd) == -1)
8753
0
        return posix_error();
8754
8755
0
    Py_RETURN_NONE;
8756
0
}
8757
#endif /* HAVE_UNLOCKPT */
8758
8759
#if defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R)
8760
static PyObject *
8761
py_ptsname(int fd)
8762
0
{
8763
0
    // POSIX manpage: Upon failure, ptsname() shall return a null pointer
8764
0
    // and may set errno. Always initialize errno to avoid undefined behavior.
8765
0
    errno = 0;
8766
0
    char *name = ptsname(fd);
8767
0
    if (name == NULL) {
8768
0
        return posix_error();
8769
0
    }
8770
0
    return PyUnicode_DecodeFSDefault(name);
8771
0
}
8772
8773
/*[clinic input]
8774
os.ptsname
8775
8776
    fd: fildes
8777
        File descriptor of a master pseudo-terminal device.
8778
    /
8779
8780
Return the name of the slave pseudo-terminal device.
8781
8782
If the ptsname_r() C function is available, it is called;
8783
otherwise, performs a ptsname() C function call.
8784
[clinic start generated code]*/
8785
8786
static PyObject *
8787
os_ptsname_impl(PyObject *module, int fd)
8788
/*[clinic end generated code: output=ef300fadc5675872 input=1369ccc0546f3130]*/
8789
0
{
8790
0
#ifdef HAVE_PTSNAME_R
8791
0
    int ret;
8792
0
    char name[MAXPATHLEN+1];
8793
8794
0
    if (HAVE_PTSNAME_R_RUNTIME) {
8795
0
        ret = ptsname_r(fd, name, sizeof(name));
8796
0
    }
8797
0
    else {
8798
        // fallback to ptsname() if ptsname_r() is not available in runtime.
8799
0
        return py_ptsname(fd);
8800
0
    }
8801
0
    if (ret != 0) {
8802
0
        errno = ret;
8803
0
        return posix_error();
8804
0
    }
8805
8806
0
    return PyUnicode_DecodeFSDefault(name);
8807
#else
8808
    return py_ptsname(fd);
8809
#endif /* HAVE_PTSNAME_R */
8810
0
}
8811
#endif /* defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) */
8812
8813
/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
8814
#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
8815
#  define DEV_PTY_FILE "/dev/ptc"
8816
#  define HAVE_DEV_PTMX
8817
#else
8818
#  define DEV_PTY_FILE "/dev/ptmx"
8819
#endif
8820
8821
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
8822
#ifdef HAVE_PTY_H
8823
#include <pty.h>
8824
#elif defined(HAVE_LIBUTIL_H)
8825
#include <libutil.h>
8826
#elif defined(HAVE_UTIL_H)
8827
#include <util.h>
8828
#endif /* HAVE_PTY_H */
8829
#ifdef HAVE_UTMP_H
8830
#include <utmp.h>
8831
#endif /* HAVE_UTMP_H */
8832
#ifdef HAVE_STROPTS_H
8833
#include <stropts.h>
8834
#endif
8835
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
8836
8837
8838
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
8839
/*[clinic input]
8840
os.openpty
8841
8842
Open a pseudo-terminal.
8843
8844
Return a tuple of (master_fd, slave_fd) containing open file descriptors
8845
for both the master and slave ends.
8846
[clinic start generated code]*/
8847
8848
static PyObject *
8849
os_openpty_impl(PyObject *module)
8850
/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
8851
0
{
8852
0
    int master_fd = -1, slave_fd = -1;
8853
#ifndef HAVE_OPENPTY
8854
    char * slave_name;
8855
#endif
8856
#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
8857
    PyOS_sighandler_t sig_saved;
8858
#if defined(__sun) && defined(__SVR4)
8859
    extern char *ptsname(int fildes);
8860
#endif
8861
#endif
8862
8863
0
#ifdef HAVE_OPENPTY
8864
0
    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
8865
0
        goto posix_error;
8866
8867
0
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
8868
0
        goto error;
8869
0
    if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
8870
0
        goto error;
8871
8872
#elif defined(HAVE__GETPTY)
8873
    slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
8874
    if (slave_name == NULL)
8875
        goto posix_error;
8876
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
8877
        goto error;
8878
8879
    slave_fd = _Py_open(slave_name, O_RDWR);
8880
    if (slave_fd < 0)
8881
        goto error;
8882
8883
#else
8884
    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
8885
    if (master_fd < 0)
8886
        goto posix_error;
8887
8888
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
8889
8890
    /* change permission of slave */
8891
    if (grantpt(master_fd) < 0) {
8892
        int saved_errno = errno;
8893
        PyOS_setsig(SIGCHLD, sig_saved);
8894
        errno = saved_errno;
8895
        goto posix_error;
8896
    }
8897
8898
    /* unlock slave */
8899
    if (unlockpt(master_fd) < 0) {
8900
        int saved_errno = errno;
8901
        PyOS_setsig(SIGCHLD, sig_saved);
8902
        errno = saved_errno;
8903
        goto posix_error;
8904
    }
8905
8906
    PyOS_setsig(SIGCHLD, sig_saved);
8907
8908
    slave_name = ptsname(master_fd); /* get name of slave */
8909
    if (slave_name == NULL)
8910
        goto posix_error;
8911
8912
    slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
8913
    if (slave_fd == -1)
8914
        goto error;
8915
8916
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
8917
        goto posix_error;
8918
8919
#if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
8920
    ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
8921
    ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
8922
#ifndef __hpux
8923
    ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
8924
#endif /* __hpux */
8925
#endif /* HAVE_CYGWIN */
8926
#endif /* HAVE_OPENPTY */
8927
8928
0
    return Py_BuildValue("(ii)", master_fd, slave_fd);
8929
8930
0
posix_error:
8931
0
    posix_error();
8932
0
error:
8933
0
    if (master_fd != -1)
8934
0
        close(master_fd);
8935
0
    if (slave_fd != -1)
8936
0
        close(slave_fd);
8937
0
    return NULL;
8938
0
}
8939
#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
8940
8941
8942
#if defined(HAVE_SETSID) && defined(TIOCSCTTY)
8943
#define HAVE_FALLBACK_LOGIN_TTY 1
8944
#endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
8945
8946
#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
8947
/*[clinic input]
8948
os.login_tty
8949
8950
    fd: fildes
8951
    /
8952
8953
Prepare the tty of which fd is a file descriptor for a new login session.
8954
8955
Make the calling process a session leader; make the tty the
8956
controlling tty, the stdin, the stdout, and the stderr of the
8957
calling process; close fd.
8958
[clinic start generated code]*/
8959
8960
static PyObject *
8961
os_login_tty_impl(PyObject *module, int fd)
8962
/*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
8963
0
{
8964
0
#ifdef HAVE_LOGIN_TTY
8965
0
    if (login_tty(fd) == -1) {
8966
0
        return posix_error();
8967
0
    }
8968
#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
8969
    /* Establish a new session. */
8970
    if (setsid() == -1) {
8971
        return posix_error();
8972
    }
8973
8974
    /* The tty becomes the controlling terminal. */
8975
    if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
8976
        return posix_error();
8977
    }
8978
8979
    /* The tty becomes stdin/stdout/stderr */
8980
    if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
8981
        return posix_error();
8982
    }
8983
    if (fd > 2) {
8984
        close(fd);
8985
    }
8986
#endif /* HAVE_LOGIN_TTY */
8987
0
    Py_RETURN_NONE;
8988
0
}
8989
#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
8990
8991
8992
#ifdef HAVE_FORKPTY
8993
/*[clinic input]
8994
os.forkpty
8995
8996
Fork a new process with a new pseudo-terminal as controlling tty.
8997
8998
Returns a tuple of (pid, master_fd).
8999
Like fork(), return pid of 0 to the child process,
9000
and pid of child to the parent process.
9001
To both, return fd of newly opened pseudo-terminal.
9002
[clinic start generated code]*/
9003
9004
static PyObject *
9005
os_forkpty_impl(PyObject *module)
9006
/*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
9007
0
{
9008
0
    int master_fd = -1;
9009
0
    pid_t pid;
9010
9011
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
9012
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
9013
0
        PyErr_SetString(PyExc_PythonFinalizationError,
9014
0
                        "can't fork at interpreter shutdown");
9015
0
        return NULL;
9016
0
    }
9017
0
    if (!_Py_IsMainInterpreter(interp)) {
9018
0
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
9019
0
        return NULL;
9020
0
    }
9021
0
    if (PySys_Audit("os.forkpty", NULL) < 0) {
9022
0
        return NULL;
9023
0
    }
9024
0
    PyOS_BeforeFork();
9025
0
    pid = forkpty(&master_fd, NULL, NULL, NULL);
9026
0
    if (pid == 0) {
9027
        /* child: this clobbers and resets the import lock. */
9028
0
        PyOS_AfterFork_Child();
9029
0
    } else {
9030
        /* parent: release the import lock. */
9031
0
        PyOS_AfterFork_Parent();
9032
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
9033
0
        warn_about_fork_with_threads("forkpty");
9034
0
    }
9035
0
    if (pid == -1) {
9036
0
        return posix_error();
9037
0
    }
9038
0
    return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
9039
0
}
9040
#endif /* HAVE_FORKPTY */
9041
9042
9043
#ifdef HAVE_GETEGID
9044
/*[clinic input]
9045
os.getegid
9046
9047
Return the current process's effective group id.
9048
[clinic start generated code]*/
9049
9050
static PyObject *
9051
os_getegid_impl(PyObject *module)
9052
/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
9053
16
{
9054
16
    return _PyLong_FromGid(getegid());
9055
16
}
9056
#endif /* HAVE_GETEGID */
9057
9058
9059
#ifdef HAVE_GETEUID
9060
/*[clinic input]
9061
os.geteuid
9062
9063
Return the current process's effective user id.
9064
[clinic start generated code]*/
9065
9066
static PyObject *
9067
os_geteuid_impl(PyObject *module)
9068
/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
9069
16
{
9070
16
    return _PyLong_FromUid(geteuid());
9071
16
}
9072
#endif /* HAVE_GETEUID */
9073
9074
9075
#ifdef HAVE_GETGID
9076
/*[clinic input]
9077
os.getgid
9078
9079
Return the current process's group id.
9080
[clinic start generated code]*/
9081
9082
static PyObject *
9083
os_getgid_impl(PyObject *module)
9084
/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
9085
16
{
9086
16
    return _PyLong_FromGid(getgid());
9087
16
}
9088
#endif /* HAVE_GETGID */
9089
9090
9091
#if defined(HAVE_GETPID)
9092
/*[clinic input]
9093
os.getpid
9094
9095
Return the current process id.
9096
[clinic start generated code]*/
9097
9098
static PyObject *
9099
os_getpid_impl(PyObject *module)
9100
/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
9101
0
{
9102
0
#if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
9103
0
    return PyLong_FromPid(getpid());
9104
#else
9105
    return PyLong_FromUnsignedLong(GetCurrentProcessId());
9106
#endif
9107
0
}
9108
#endif /* defined(HAVE_GETPID) */
9109
9110
#ifdef NGROUPS_MAX
9111
0
#define MAX_GROUPS NGROUPS_MAX
9112
#else
9113
    /* defined to be 16 on Solaris7, so this should be a small number */
9114
#define MAX_GROUPS 64
9115
#endif
9116
9117
#ifdef HAVE_GETGROUPLIST
9118
9119
#ifdef __APPLE__
9120
/*[clinic input]
9121
os.getgrouplist
9122
9123
    user: str
9124
        username to lookup
9125
    group as basegid: int
9126
        base group id of the user
9127
    /
9128
9129
Returns a list of groups to which a user belongs.
9130
[clinic start generated code]*/
9131
9132
static PyObject *
9133
os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
9134
/*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
9135
#else
9136
/*[clinic input]
9137
os.getgrouplist
9138
9139
    user: str
9140
        username to lookup
9141
    group as basegid: gid_t
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, gid_t basegid)
9150
/*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
9151
#endif
9152
0
{
9153
0
    int i, ngroups;
9154
0
    PyObject *list;
9155
#ifdef __APPLE__
9156
    int *groups;
9157
#else
9158
0
    gid_t *groups;
9159
0
#endif
9160
9161
    /*
9162
     * NGROUPS_MAX is defined by POSIX.1 as the maximum
9163
     * number of supplemental groups a users can belong to.
9164
     * We have to increment it by one because
9165
     * getgrouplist() returns both the supplemental groups
9166
     * and the primary group, i.e. all of the groups the
9167
     * user belongs to.
9168
     */
9169
0
    ngroups = 1 + MAX_GROUPS;
9170
9171
0
    while (1) {
9172
#ifdef __APPLE__
9173
        groups = PyMem_New(int, ngroups);
9174
#else
9175
0
        groups = PyMem_New(gid_t, ngroups);
9176
0
#endif
9177
0
        if (groups == NULL) {
9178
0
            return PyErr_NoMemory();
9179
0
        }
9180
9181
0
        int old_ngroups = ngroups;
9182
0
        if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
9183
            /* Success */
9184
0
            break;
9185
0
        }
9186
9187
        /* getgrouplist() fails if the group list is too small */
9188
0
        PyMem_Free(groups);
9189
9190
0
        if (ngroups > old_ngroups) {
9191
            /* If the group list is too small, the glibc implementation of
9192
               getgrouplist() sets ngroups to the total number of groups and
9193
               returns -1. */
9194
0
        }
9195
0
        else {
9196
            /* Double the group list size */
9197
0
            if (ngroups > INT_MAX / 2) {
9198
0
                return PyErr_NoMemory();
9199
0
            }
9200
0
            ngroups *= 2;
9201
0
        }
9202
9203
        /* Retry getgrouplist() with a larger group list */
9204
0
    }
9205
9206
#ifdef _Py_MEMORY_SANITIZER
9207
    /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
9208
    __msan_unpoison(&ngroups, sizeof(ngroups));
9209
    __msan_unpoison(groups, ngroups*sizeof(*groups));
9210
#endif
9211
9212
0
    list = PyList_New(ngroups);
9213
0
    if (list == NULL) {
9214
0
        PyMem_Free(groups);
9215
0
        return NULL;
9216
0
    }
9217
9218
0
    for (i = 0; i < ngroups; i++) {
9219
#ifdef __APPLE__
9220
        PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
9221
#else
9222
0
        PyObject *o = _PyLong_FromGid(groups[i]);
9223
0
#endif
9224
0
        if (o == NULL) {
9225
0
            Py_DECREF(list);
9226
0
            PyMem_Free(groups);
9227
0
            return NULL;
9228
0
        }
9229
0
        PyList_SET_ITEM(list, i, o);
9230
0
    }
9231
9232
0
    PyMem_Free(groups);
9233
9234
0
    return list;
9235
0
}
9236
#endif /* HAVE_GETGROUPLIST */
9237
9238
9239
#ifdef HAVE_GETGROUPS
9240
/*[clinic input]
9241
os.getgroups
9242
9243
Return list of supplemental group IDs for the process.
9244
[clinic start generated code]*/
9245
9246
static PyObject *
9247
os_getgroups_impl(PyObject *module)
9248
/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
9249
0
{
9250
    // Call getgroups with length 0 to get the actual number of groups
9251
0
    int n = getgroups(0, NULL);
9252
0
    if (n < 0) {
9253
0
        return posix_error();
9254
0
    }
9255
9256
0
    if (n == 0) {
9257
0
        return PyList_New(0);
9258
0
    }
9259
9260
0
    gid_t *grouplist = PyMem_New(gid_t, n);
9261
0
    if (grouplist == NULL) {
9262
0
        return PyErr_NoMemory();
9263
0
    }
9264
9265
0
    n = getgroups(n, grouplist);
9266
0
    if (n == -1) {
9267
0
        posix_error();
9268
0
        PyMem_Free(grouplist);
9269
0
        return NULL;
9270
0
    }
9271
9272
0
    PyObject *result = PyList_New(n);
9273
0
    if (result == NULL) {
9274
0
        goto error;
9275
0
    }
9276
9277
0
    for (int i = 0; i < n; ++i) {
9278
0
        PyObject *group = _PyLong_FromGid(grouplist[i]);
9279
0
        if (group == NULL) {
9280
0
            goto error;
9281
0
        }
9282
0
        PyList_SET_ITEM(result, i, group);
9283
0
    }
9284
0
    PyMem_Free(grouplist);
9285
9286
0
    return result;
9287
9288
0
error:
9289
0
    PyMem_Free(grouplist);
9290
0
    Py_XDECREF(result);
9291
0
    return NULL;
9292
0
}
9293
#endif /* HAVE_GETGROUPS */
9294
9295
#ifdef HAVE_INITGROUPS
9296
#ifdef __APPLE__
9297
/*[clinic input]
9298
os.initgroups
9299
9300
    username as oname: FSConverter
9301
    gid: int
9302
    /
9303
9304
Initialize the group access list.
9305
9306
Call the system initgroups() to initialize the group access list with all of
9307
the groups of which the specified username is a member, plus the specified
9308
group id.
9309
[clinic start generated code]*/
9310
9311
static PyObject *
9312
os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
9313
/*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/
9314
#else
9315
/*[clinic input]
9316
os.initgroups
9317
9318
    username as oname: FSConverter
9319
    gid: gid_t
9320
    /
9321
9322
Initialize the group access list.
9323
9324
Call the system initgroups() to initialize the group access list with all of
9325
the groups of which the specified username is a member, plus the specified
9326
group id.
9327
[clinic start generated code]*/
9328
9329
static PyObject *
9330
os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
9331
/*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/
9332
#endif
9333
0
{
9334
0
    const char *username = PyBytes_AS_STRING(oname);
9335
9336
0
    if (initgroups(username, gid) == -1)
9337
0
        return PyErr_SetFromErrno(PyExc_OSError);
9338
9339
0
    Py_RETURN_NONE;
9340
0
}
9341
#endif /* HAVE_INITGROUPS */
9342
9343
9344
#ifdef HAVE_GETPGID
9345
/*[clinic input]
9346
os.getpgid
9347
9348
    pid: pid_t
9349
9350
Call the system call getpgid(), and return the result.
9351
[clinic start generated code]*/
9352
9353
static PyObject *
9354
os_getpgid_impl(PyObject *module, pid_t pid)
9355
/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
9356
0
{
9357
0
    pid_t pgid = getpgid(pid);
9358
0
    if (pgid < 0)
9359
0
        return posix_error();
9360
0
    return PyLong_FromPid(pgid);
9361
0
}
9362
#endif /* HAVE_GETPGID */
9363
9364
9365
#ifdef HAVE_GETPGRP
9366
/*[clinic input]
9367
os.getpgrp
9368
9369
Return the current process group id.
9370
[clinic start generated code]*/
9371
9372
static PyObject *
9373
os_getpgrp_impl(PyObject *module)
9374
/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
9375
0
{
9376
#ifdef GETPGRP_HAVE_ARG
9377
    return PyLong_FromPid(getpgrp(0));
9378
#else /* GETPGRP_HAVE_ARG */
9379
0
    return PyLong_FromPid(getpgrp());
9380
0
#endif /* GETPGRP_HAVE_ARG */
9381
0
}
9382
#endif /* HAVE_GETPGRP */
9383
9384
9385
#ifdef HAVE_SETPGRP
9386
/*[clinic input]
9387
os.setpgrp
9388
9389
Make the current process the leader of its process group.
9390
[clinic start generated code]*/
9391
9392
static PyObject *
9393
os_setpgrp_impl(PyObject *module)
9394
/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
9395
0
{
9396
#ifdef SETPGRP_HAVE_ARG
9397
    if (setpgrp(0, 0) < 0)
9398
#else /* SETPGRP_HAVE_ARG */
9399
0
    if (setpgrp() < 0)
9400
0
#endif /* SETPGRP_HAVE_ARG */
9401
0
        return posix_error();
9402
0
    Py_RETURN_NONE;
9403
0
}
9404
#endif /* HAVE_SETPGRP */
9405
9406
#ifdef HAVE_GETPPID
9407
9408
#ifdef MS_WINDOWS
9409
#include <winternl.h>
9410
#include <ProcessSnapshot.h>
9411
9412
// The structure definition in winternl.h may be incomplete.
9413
// This structure is the full version from the MSDN documentation.
9414
typedef struct _PROCESS_BASIC_INFORMATION_FULL {
9415
    NTSTATUS ExitStatus;
9416
    PVOID PebBaseAddress;
9417
    ULONG_PTR AffinityMask;
9418
    LONG BasePriority;
9419
    ULONG_PTR UniqueProcessId;
9420
    ULONG_PTR InheritedFromUniqueProcessId;
9421
} PROCESS_BASIC_INFORMATION_FULL;
9422
9423
typedef NTSTATUS (NTAPI *PNT_QUERY_INFORMATION_PROCESS) (
9424
    IN    HANDLE           ProcessHandle,
9425
    IN    PROCESSINFOCLASS ProcessInformationClass,
9426
    OUT   PVOID            ProcessInformation,
9427
    IN    ULONG            ProcessInformationLength,
9428
    OUT   PULONG           ReturnLength OPTIONAL);
9429
9430
// This function returns the process ID of the parent process.
9431
// Returns 0 on failure.
9432
static ULONG
9433
win32_getppid_fast(void)
9434
{
9435
    NTSTATUS status;
9436
    HMODULE ntdll;
9437
    PNT_QUERY_INFORMATION_PROCESS pNtQueryInformationProcess;
9438
    PROCESS_BASIC_INFORMATION_FULL basic_information;
9439
    static ULONG cached_ppid = 0;
9440
9441
    if (cached_ppid) {
9442
        // No need to query the kernel again.
9443
        return cached_ppid;
9444
    }
9445
9446
    ntdll = GetModuleHandleW(L"ntdll.dll");
9447
    if (!ntdll) {
9448
        return 0;
9449
    }
9450
9451
    pNtQueryInformationProcess = (PNT_QUERY_INFORMATION_PROCESS) GetProcAddress(ntdll, "NtQueryInformationProcess");
9452
    if (!pNtQueryInformationProcess) {
9453
        return 0;
9454
    }
9455
9456
    status = pNtQueryInformationProcess(GetCurrentProcess(),
9457
                                        ProcessBasicInformation,
9458
                                        &basic_information,
9459
                                        sizeof(basic_information),
9460
                                        NULL);
9461
9462
    if (!NT_SUCCESS(status)) {
9463
        return 0;
9464
    }
9465
9466
    // Perform sanity check on the parent process ID we received from NtQueryInformationProcess.
9467
    // The check covers values which exceed the 32-bit range (if running on x64) as well as
9468
    // zero and (ULONG) -1.
9469
9470
    if (basic_information.InheritedFromUniqueProcessId == 0 ||
9471
        basic_information.InheritedFromUniqueProcessId >= ULONG_MAX)
9472
    {
9473
        return 0;
9474
    }
9475
9476
    // Now that we have reached this point, the BasicInformation.InheritedFromUniqueProcessId
9477
    // structure member contains a ULONG_PTR which represents the process ID of our parent
9478
    // process. This process ID will be correctly returned even if the parent process has
9479
    // exited or been terminated.
9480
9481
    cached_ppid = (ULONG) basic_information.InheritedFromUniqueProcessId;
9482
    return cached_ppid;
9483
}
9484
9485
static PyObject*
9486
win32_getppid(void)
9487
{
9488
    DWORD error;
9489
    PyObject* result = NULL;
9490
    HANDLE process = GetCurrentProcess();
9491
    HPSS snapshot = NULL;
9492
    ULONG pid;
9493
9494
    pid = win32_getppid_fast();
9495
    if (pid != 0) {
9496
        return PyLong_FromUnsignedLong(pid);
9497
    }
9498
9499
    // If failure occurs in win32_getppid_fast(), fall back to using the PSS API.
9500
9501
    error = PssCaptureSnapshot(process, PSS_CAPTURE_NONE, 0, &snapshot);
9502
    if (error != ERROR_SUCCESS) {
9503
        return PyErr_SetFromWindowsErr(error);
9504
    }
9505
9506
    PSS_PROCESS_INFORMATION info;
9507
    error = PssQuerySnapshot(snapshot, PSS_QUERY_PROCESS_INFORMATION, &info,
9508
                             sizeof(info));
9509
    if (error == ERROR_SUCCESS) {
9510
        result = PyLong_FromUnsignedLong(info.ParentProcessId);
9511
    }
9512
    else {
9513
        result = PyErr_SetFromWindowsErr(error);
9514
    }
9515
9516
    PssFreeSnapshot(process, snapshot);
9517
    return result;
9518
}
9519
#endif /*MS_WINDOWS*/
9520
9521
9522
/*[clinic input]
9523
os.getppid
9524
9525
Return the parent's process id.
9526
9527
If the parent process has already exited, Windows machines will still
9528
return its id; others systems will return the id of the 'init' process (1).
9529
[clinic start generated code]*/
9530
9531
static PyObject *
9532
os_getppid_impl(PyObject *module)
9533
/*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
9534
0
{
9535
#ifdef MS_WINDOWS
9536
    return win32_getppid();
9537
#else
9538
0
    return PyLong_FromPid(getppid());
9539
0
#endif
9540
0
}
9541
#endif /* HAVE_GETPPID */
9542
9543
9544
#ifdef HAVE_GETLOGIN
9545
/*[clinic input]
9546
os.getlogin
9547
9548
Return the actual login name.
9549
[clinic start generated code]*/
9550
9551
static PyObject *
9552
os_getlogin_impl(PyObject *module)
9553
/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
9554
0
{
9555
0
    PyObject *result = NULL;
9556
#ifdef MS_WINDOWS
9557
    wchar_t user_name[UNLEN + 1];
9558
    DWORD num_chars = Py_ARRAY_LENGTH(user_name);
9559
9560
    if (GetUserNameW(user_name, &num_chars)) {
9561
        /* num_chars is the number of unicode chars plus null terminator */
9562
        result = PyUnicode_FromWideChar(user_name, num_chars - 1);
9563
    }
9564
    else
9565
        result = PyErr_SetFromWindowsErr(GetLastError());
9566
#elif defined (HAVE_GETLOGIN_R)
9567
# if defined (HAVE_MAXLOGNAME)
9568
    char name[MAXLOGNAME + 1];
9569
# elif defined (HAVE_UT_NAMESIZE)
9570
    char name[UT_NAMESIZE + 1];
9571
# else
9572
    char name[256];
9573
# endif
9574
0
    int err = getlogin_r(name, sizeof(name));
9575
0
    if (err) {
9576
0
        int old_errno = errno;
9577
0
        errno = -err;
9578
0
        posix_error();
9579
0
        errno = old_errno;
9580
0
    }
9581
0
    else {
9582
0
        result = PyUnicode_DecodeFSDefault(name);
9583
0
    }
9584
#else
9585
    char *name;
9586
    int old_errno = errno;
9587
9588
    errno = 0;
9589
    name = getlogin();
9590
    if (name == NULL) {
9591
        if (errno)
9592
            posix_error();
9593
        else
9594
            PyErr_SetString(PyExc_OSError, "unable to determine login name");
9595
    }
9596
    else
9597
        result = PyUnicode_DecodeFSDefault(name);
9598
    errno = old_errno;
9599
#endif
9600
0
    return result;
9601
0
}
9602
#endif /* HAVE_GETLOGIN */
9603
9604
9605
#ifdef HAVE_GETUID
9606
/*[clinic input]
9607
os.getuid
9608
9609
Return the current process's user id.
9610
[clinic start generated code]*/
9611
9612
static PyObject *
9613
os_getuid_impl(PyObject *module)
9614
/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
9615
16
{
9616
16
    return _PyLong_FromUid(getuid());
9617
16
}
9618
#endif /* HAVE_GETUID */
9619
9620
9621
#ifdef MS_WINDOWS
9622
#define HAVE_KILL
9623
#endif /* MS_WINDOWS */
9624
9625
#ifdef HAVE_KILL
9626
/*[clinic input]
9627
os.kill
9628
9629
    pid: pid_t
9630
    signal: Py_ssize_t
9631
    /
9632
9633
Kill a process with a signal.
9634
[clinic start generated code]*/
9635
9636
static PyObject *
9637
os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
9638
/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
9639
0
{
9640
0
    if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
9641
0
        return NULL;
9642
0
    }
9643
0
#ifndef MS_WINDOWS
9644
0
    if (kill(pid, (int)signal) == -1) {
9645
0
        return posix_error();
9646
0
    }
9647
9648
    // Check immediately if the signal was sent to the current process.
9649
    // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
9650
    // is cheap.
9651
0
    if (PyErr_CheckSignals()) {
9652
0
        return NULL;
9653
0
    }
9654
9655
0
    Py_RETURN_NONE;
9656
#else /* !MS_WINDOWS */
9657
    DWORD sig = (DWORD)signal;
9658
9659
#ifdef HAVE_WINDOWS_CONSOLE_IO
9660
    /* Console processes which share a common console can be sent CTRL+C or
9661
       CTRL+BREAK events, provided they handle said events. */
9662
    if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
9663
        if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
9664
            return PyErr_SetFromWindowsErr(0);
9665
        }
9666
        Py_RETURN_NONE;
9667
    }
9668
#endif /* HAVE_WINDOWS_CONSOLE_IO */
9669
9670
    /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
9671
       attempt to open and terminate the process. */
9672
    HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
9673
    if (handle == NULL) {
9674
        return PyErr_SetFromWindowsErr(0);
9675
    }
9676
9677
    BOOL res = TerminateProcess(handle, sig);
9678
    CloseHandle(handle);
9679
    if (res == 0) {
9680
        return PyErr_SetFromWindowsErr(0);
9681
    }
9682
9683
    Py_RETURN_NONE;
9684
#endif /* !MS_WINDOWS */
9685
0
}
9686
#endif /* HAVE_KILL */
9687
9688
9689
#ifdef HAVE_KILLPG
9690
/*[clinic input]
9691
os.killpg
9692
9693
    pgid: pid_t
9694
    signal: int
9695
    /
9696
9697
Kill a process group with a signal.
9698
[clinic start generated code]*/
9699
9700
static PyObject *
9701
os_killpg_impl(PyObject *module, pid_t pgid, int signal)
9702
/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
9703
0
{
9704
0
    if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
9705
0
        return NULL;
9706
0
    }
9707
    /* XXX some man pages make the `pgid` parameter an int, others
9708
       a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
9709
       take the same type. Moreover, pid_t is always at least as wide as
9710
       int (else compilation of this module fails), which is safe. */
9711
0
    if (killpg(pgid, signal) == -1)
9712
0
        return posix_error();
9713
0
    Py_RETURN_NONE;
9714
0
}
9715
#endif /* HAVE_KILLPG */
9716
9717
9718
#ifdef HAVE_PLOCK
9719
#ifdef HAVE_SYS_LOCK_H
9720
#include <sys/lock.h>
9721
#endif
9722
9723
/*[clinic input]
9724
os.plock
9725
    op: int
9726
    /
9727
9728
Lock program segments into memory.");
9729
[clinic start generated code]*/
9730
9731
static PyObject *
9732
os_plock_impl(PyObject *module, int op)
9733
/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
9734
{
9735
    if (plock(op) == -1)
9736
        return posix_error();
9737
    Py_RETURN_NONE;
9738
}
9739
#endif /* HAVE_PLOCK */
9740
9741
9742
#ifdef HAVE_SETUID
9743
/*[clinic input]
9744
os.setuid
9745
9746
    uid: uid_t
9747
    /
9748
9749
Set the current process's user id.
9750
[clinic start generated code]*/
9751
9752
static PyObject *
9753
os_setuid_impl(PyObject *module, uid_t uid)
9754
/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
9755
0
{
9756
0
    if (setuid(uid) < 0)
9757
0
        return posix_error();
9758
0
    Py_RETURN_NONE;
9759
0
}
9760
#endif /* HAVE_SETUID */
9761
9762
9763
#ifdef HAVE_SETEUID
9764
/*[clinic input]
9765
os.seteuid
9766
9767
    euid: uid_t
9768
    /
9769
9770
Set the current process's effective user id.
9771
[clinic start generated code]*/
9772
9773
static PyObject *
9774
os_seteuid_impl(PyObject *module, uid_t euid)
9775
/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
9776
0
{
9777
0
    if (seteuid(euid) < 0)
9778
0
        return posix_error();
9779
0
    Py_RETURN_NONE;
9780
0
}
9781
#endif /* HAVE_SETEUID */
9782
9783
9784
#ifdef HAVE_SETEGID
9785
/*[clinic input]
9786
os.setegid
9787
9788
    egid: gid_t
9789
    /
9790
9791
Set the current process's effective group id.
9792
[clinic start generated code]*/
9793
9794
static PyObject *
9795
os_setegid_impl(PyObject *module, gid_t egid)
9796
/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
9797
0
{
9798
0
    if (setegid(egid) < 0)
9799
0
        return posix_error();
9800
0
    Py_RETURN_NONE;
9801
0
}
9802
#endif /* HAVE_SETEGID */
9803
9804
9805
#ifdef HAVE_SETREUID
9806
/*[clinic input]
9807
os.setreuid
9808
9809
    ruid: uid_t
9810
    euid: uid_t
9811
    /
9812
9813
Set the current process's real and effective user ids.
9814
[clinic start generated code]*/
9815
9816
static PyObject *
9817
os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
9818
/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
9819
0
{
9820
0
    if (setreuid(ruid, euid) < 0) {
9821
0
        return posix_error();
9822
0
    } else {
9823
0
        Py_RETURN_NONE;
9824
0
    }
9825
0
}
9826
#endif /* HAVE_SETREUID */
9827
9828
9829
#ifdef HAVE_SETREGID
9830
/*[clinic input]
9831
os.setregid
9832
9833
    rgid: gid_t
9834
    egid: gid_t
9835
    /
9836
9837
Set the current process's real and effective group ids.
9838
[clinic start generated code]*/
9839
9840
static PyObject *
9841
os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
9842
/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
9843
0
{
9844
0
    if (setregid(rgid, egid) < 0)
9845
0
        return posix_error();
9846
0
    Py_RETURN_NONE;
9847
0
}
9848
#endif /* HAVE_SETREGID */
9849
9850
9851
#ifdef HAVE_SETGID
9852
/*[clinic input]
9853
os.setgid
9854
    gid: gid_t
9855
    /
9856
9857
Set the current process's group id.
9858
[clinic start generated code]*/
9859
9860
static PyObject *
9861
os_setgid_impl(PyObject *module, gid_t gid)
9862
/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
9863
0
{
9864
0
    if (setgid(gid) < 0)
9865
0
        return posix_error();
9866
0
    Py_RETURN_NONE;
9867
0
}
9868
#endif /* HAVE_SETGID */
9869
9870
9871
#ifdef HAVE_SETGROUPS
9872
/*[clinic input]
9873
os.setgroups
9874
9875
    groups: object
9876
    /
9877
9878
Set the groups of the current process to list.
9879
[clinic start generated code]*/
9880
9881
static PyObject *
9882
os_setgroups(PyObject *module, PyObject *groups)
9883
/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
9884
0
{
9885
0
    if (!PySequence_Check(groups)) {
9886
0
        PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
9887
0
        return NULL;
9888
0
    }
9889
0
    Py_ssize_t len = PySequence_Size(groups);
9890
0
    if (len < 0) {
9891
0
        return NULL;
9892
0
    }
9893
0
    if (len > MAX_GROUPS) {
9894
0
        PyErr_SetString(PyExc_ValueError, "too many groups");
9895
0
        return NULL;
9896
0
    }
9897
9898
0
    gid_t *grouplist = PyMem_New(gid_t, len);
9899
0
    if (grouplist == NULL) {
9900
0
        PyErr_NoMemory();
9901
0
        return NULL;
9902
0
    }
9903
0
    for (Py_ssize_t i = 0; i < len; i++) {
9904
0
        PyObject *elem;
9905
0
        elem = PySequence_GetItem(groups, i);
9906
0
        if (!elem) {
9907
0
            PyMem_Free(grouplist);
9908
0
            return NULL;
9909
0
        }
9910
0
        if (!PyIndex_Check(elem)) {
9911
0
            PyErr_SetString(PyExc_TypeError,
9912
0
                            "groups must be integers");
9913
0
            Py_DECREF(elem);
9914
0
            PyMem_Free(grouplist);
9915
0
            return NULL;
9916
0
        } else {
9917
0
            if (!_Py_Gid_Converter(elem, &grouplist[i])) {
9918
0
                Py_DECREF(elem);
9919
0
                PyMem_Free(grouplist);
9920
0
                return NULL;
9921
0
            }
9922
0
        }
9923
0
        Py_DECREF(elem);
9924
0
    }
9925
9926
0
    if (setgroups(len, grouplist) < 0) {
9927
0
        posix_error();
9928
0
        PyMem_Free(grouplist);
9929
0
        return NULL;
9930
0
    }
9931
0
    PyMem_Free(grouplist);
9932
0
    Py_RETURN_NONE;
9933
0
}
9934
#endif /* HAVE_SETGROUPS */
9935
9936
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
9937
static PyObject *
9938
wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
9939
0
{
9940
0
    PyObject *result;
9941
0
    PyObject *struct_rusage;
9942
9943
0
    if (pid == -1)
9944
0
        return posix_error();
9945
9946
    // If wait succeeded but no child was ready to report status, ru will not
9947
    // have been populated.
9948
0
    if (pid == 0) {
9949
0
        memset(ru, 0, sizeof(*ru));
9950
0
    }
9951
9952
0
    struct_rusage = PyImport_ImportModuleAttrString("resource", "struct_rusage");
9953
0
    if (struct_rusage == NULL)
9954
0
        return NULL;
9955
9956
    /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
9957
0
    result = PyStructSequence_New((PyTypeObject*) struct_rusage);
9958
0
    Py_DECREF(struct_rusage);
9959
0
    if (!result)
9960
0
        return NULL;
9961
9962
0
    int pos = 0;
9963
9964
0
#ifndef doubletime
9965
0
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
9966
0
#endif
9967
9968
0
#define SET_RESULT(CALL)                                     \
9969
0
    do {                                                     \
9970
0
        PyObject *item = (CALL);                             \
9971
0
        if (item == NULL) {                                  \
9972
0
            Py_DECREF(result);                               \
9973
0
            return NULL;                                     \
9974
0
        }                                                    \
9975
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
9976
0
    } while(0)
9977
9978
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_utime)));
9979
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_stime)));
9980
0
    SET_RESULT(PyLong_FromLong(ru->ru_maxrss));
9981
0
    SET_RESULT(PyLong_FromLong(ru->ru_ixrss));
9982
0
    SET_RESULT(PyLong_FromLong(ru->ru_idrss));
9983
0
    SET_RESULT(PyLong_FromLong(ru->ru_isrss));
9984
0
    SET_RESULT(PyLong_FromLong(ru->ru_minflt));
9985
0
    SET_RESULT(PyLong_FromLong(ru->ru_majflt));
9986
0
    SET_RESULT(PyLong_FromLong(ru->ru_nswap));
9987
0
    SET_RESULT(PyLong_FromLong(ru->ru_inblock));
9988
0
    SET_RESULT(PyLong_FromLong(ru->ru_oublock));
9989
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgsnd));
9990
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgrcv));
9991
0
    SET_RESULT(PyLong_FromLong(ru->ru_nsignals));
9992
0
    SET_RESULT(PyLong_FromLong(ru->ru_nvcsw));
9993
0
    SET_RESULT(PyLong_FromLong(ru->ru_nivcsw));
9994
0
#undef SET_RESULT
9995
9996
0
    return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
9997
0
}
9998
#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
9999
10000
10001
#ifdef HAVE_WAIT3
10002
/*[clinic input]
10003
os.wait3
10004
10005
    options: int
10006
Wait for completion of a child process.
10007
10008
Returns a tuple of information about the child process:
10009
  (pid, status, rusage)
10010
[clinic start generated code]*/
10011
10012
static PyObject *
10013
os_wait3_impl(PyObject *module, int options)
10014
/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
10015
0
{
10016
0
    pid_t pid;
10017
0
    struct rusage ru;
10018
0
    int async_err = 0;
10019
0
    WAIT_TYPE status;
10020
0
    WAIT_STATUS_INT(status) = 0;
10021
10022
0
    do {
10023
0
        Py_BEGIN_ALLOW_THREADS
10024
0
        pid = wait3(&status, options, &ru);
10025
0
        Py_END_ALLOW_THREADS
10026
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10027
0
    if (pid < 0)
10028
0
        return (!async_err) ? posix_error() : NULL;
10029
10030
0
    return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
10031
0
}
10032
#endif /* HAVE_WAIT3 */
10033
10034
10035
#ifdef HAVE_WAIT4
10036
/*[clinic input]
10037
10038
os.wait4
10039
10040
    pid: pid_t
10041
    options: int
10042
10043
Wait for completion of a specific child process.
10044
10045
Returns a tuple of information about the child process:
10046
  (pid, status, rusage)
10047
[clinic start generated code]*/
10048
10049
static PyObject *
10050
os_wait4_impl(PyObject *module, pid_t pid, int options)
10051
/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
10052
0
{
10053
0
    pid_t res;
10054
0
    struct rusage ru;
10055
0
    int async_err = 0;
10056
0
    WAIT_TYPE status;
10057
0
    WAIT_STATUS_INT(status) = 0;
10058
10059
0
    do {
10060
0
        Py_BEGIN_ALLOW_THREADS
10061
0
        res = wait4(pid, &status, options, &ru);
10062
0
        Py_END_ALLOW_THREADS
10063
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10064
0
    if (res < 0)
10065
0
        return (!async_err) ? posix_error() : NULL;
10066
10067
0
    return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
10068
0
}
10069
#endif /* HAVE_WAIT4 */
10070
10071
10072
#if defined(HAVE_WAITID)
10073
/*[clinic input]
10074
os.waitid
10075
10076
    idtype: idtype_t
10077
        Must be one of be P_PID, P_PGID or P_ALL.
10078
    id: id_t
10079
        The id to wait on.
10080
    options: int
10081
        Constructed from the ORing of one or more of WEXITED, WSTOPPED
10082
        or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
10083
    /
10084
10085
Returns the result of waiting for a process or processes.
10086
10087
Returns either waitid_result or None if WNOHANG is specified and there are
10088
no children in a waitable state.
10089
[clinic start generated code]*/
10090
10091
static PyObject *
10092
os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
10093
/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
10094
0
{
10095
0
    PyObject *result;
10096
0
    int res;
10097
0
    int async_err = 0;
10098
0
    siginfo_t si;
10099
0
    si.si_pid = 0;
10100
10101
0
    do {
10102
0
        Py_BEGIN_ALLOW_THREADS
10103
0
        res = waitid(idtype, id, &si, options);
10104
0
        Py_END_ALLOW_THREADS
10105
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10106
0
    if (res < 0)
10107
0
        return (!async_err) ? posix_error() : NULL;
10108
10109
0
    if (si.si_pid == 0)
10110
0
        Py_RETURN_NONE;
10111
10112
0
    PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
10113
0
    result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
10114
0
    if (!result)
10115
0
        return NULL;
10116
10117
0
    int pos = 0;
10118
10119
0
#define SET_RESULT(CALL)                                     \
10120
0
    do {                                                     \
10121
0
        PyObject *item = (CALL);                             \
10122
0
        if (item == NULL) {                                  \
10123
0
            Py_DECREF(result);                               \
10124
0
            return NULL;                                     \
10125
0
        }                                                    \
10126
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10127
0
    } while(0)
10128
10129
0
    SET_RESULT(PyLong_FromPid(si.si_pid));
10130
0
    SET_RESULT(_PyLong_FromUid(si.si_uid));
10131
0
    SET_RESULT(PyLong_FromLong((long)(si.si_signo)));
10132
0
    SET_RESULT(PyLong_FromLong((long)(si.si_status)));
10133
0
    SET_RESULT(PyLong_FromLong((long)(si.si_code)));
10134
10135
0
#undef SET_RESULT
10136
10137
0
    return result;
10138
0
}
10139
#endif /* defined(HAVE_WAITID) */
10140
10141
10142
#if defined(HAVE_WAITPID)
10143
/*[clinic input]
10144
os.waitpid
10145
    pid: pid_t
10146
    options: int
10147
    /
10148
10149
Wait for completion of a given child process.
10150
10151
Returns a tuple of information regarding the child process:
10152
    (pid, status)
10153
10154
The options argument is ignored on Windows.
10155
[clinic start generated code]*/
10156
10157
static PyObject *
10158
os_waitpid_impl(PyObject *module, pid_t pid, int options)
10159
/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
10160
0
{
10161
0
    pid_t res;
10162
0
    int async_err = 0;
10163
0
    WAIT_TYPE status;
10164
0
    WAIT_STATUS_INT(status) = 0;
10165
10166
0
    do {
10167
0
        Py_BEGIN_ALLOW_THREADS
10168
0
        res = waitpid(pid, &status, options);
10169
0
        Py_END_ALLOW_THREADS
10170
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10171
0
    if (res < 0)
10172
0
        return (!async_err) ? posix_error() : NULL;
10173
10174
0
    return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
10175
0
}
10176
#elif defined(HAVE_CWAIT)
10177
/* MS C has a variant of waitpid() that's usable for most purposes. */
10178
/*[clinic input]
10179
os.waitpid
10180
    pid: intptr_t
10181
    options: int
10182
    /
10183
10184
Wait for completion of a given process.
10185
10186
Returns a tuple of information regarding the process:
10187
    (pid, status << 8)
10188
10189
The options argument is ignored on Windows.
10190
[clinic start generated code]*/
10191
10192
static PyObject *
10193
os_waitpid_impl(PyObject *module, intptr_t pid, int options)
10194
/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
10195
{
10196
    int status;
10197
    intptr_t res;
10198
    int async_err = 0;
10199
10200
    do {
10201
        Py_BEGIN_ALLOW_THREADS
10202
        _Py_BEGIN_SUPPRESS_IPH
10203
        res = _cwait(&status, pid, options);
10204
        _Py_END_SUPPRESS_IPH
10205
        Py_END_ALLOW_THREADS
10206
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10207
    if (res < 0)
10208
        return (!async_err) ? posix_error() : NULL;
10209
10210
    unsigned long long ustatus = (unsigned int)status;
10211
10212
    /* shift the status left a byte so this is more like the POSIX waitpid */
10213
    return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
10214
}
10215
#endif
10216
10217
10218
#ifdef HAVE_WAIT
10219
/*[clinic input]
10220
os.wait
10221
10222
Wait for completion of a child process.
10223
10224
Returns a tuple of information about the child process:
10225
    (pid, status)
10226
[clinic start generated code]*/
10227
10228
static PyObject *
10229
os_wait_impl(PyObject *module)
10230
/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
10231
0
{
10232
0
    pid_t pid;
10233
0
    int async_err = 0;
10234
0
    WAIT_TYPE status;
10235
0
    WAIT_STATUS_INT(status) = 0;
10236
10237
0
    do {
10238
0
        Py_BEGIN_ALLOW_THREADS
10239
0
        pid = wait(&status);
10240
0
        Py_END_ALLOW_THREADS
10241
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10242
0
    if (pid < 0)
10243
0
        return (!async_err) ? posix_error() : NULL;
10244
10245
0
    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
10246
0
}
10247
#endif /* HAVE_WAIT */
10248
10249
10250
// This system call always crashes on older Android versions.
10251
#if defined(__linux__) && defined(__NR_pidfd_open) && \
10252
    !(defined(__ANDROID__) && __ANDROID_API__ < 31)
10253
/*[clinic input]
10254
os.pidfd_open
10255
  pid: pid_t
10256
  flags: unsigned_int = 0
10257
10258
Return a file descriptor referring to the process *pid*.
10259
10260
The descriptor can be used to perform process management without races and
10261
signals.
10262
[clinic start generated code]*/
10263
10264
static PyObject *
10265
os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
10266
/*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
10267
0
{
10268
0
    int fd = syscall(__NR_pidfd_open, pid, flags);
10269
0
    if (fd < 0) {
10270
0
        return posix_error();
10271
0
    }
10272
0
    return PyLong_FromLong(fd);
10273
0
}
10274
#endif
10275
10276
10277
#ifdef HAVE_SETNS
10278
/*[clinic input]
10279
os.setns
10280
  fd: fildes
10281
    A file descriptor to a namespace.
10282
  nstype: int = 0
10283
    Type of namespace.
10284
10285
Move the calling thread into different namespaces.
10286
[clinic start generated code]*/
10287
10288
static PyObject *
10289
os_setns_impl(PyObject *module, int fd, int nstype)
10290
/*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/
10291
0
{
10292
0
    int res;
10293
10294
0
    Py_BEGIN_ALLOW_THREADS
10295
0
    res = setns(fd, nstype);
10296
0
    Py_END_ALLOW_THREADS
10297
10298
0
    if (res != 0) {
10299
0
        return posix_error();
10300
0
    }
10301
10302
0
    Py_RETURN_NONE;
10303
0
}
10304
#endif
10305
10306
10307
#ifdef HAVE_UNSHARE
10308
/*[clinic input]
10309
os.unshare
10310
  flags: int
10311
    Namespaces to be unshared.
10312
10313
Disassociate parts of a process (or thread) execution context.
10314
[clinic start generated code]*/
10315
10316
static PyObject *
10317
os_unshare_impl(PyObject *module, int flags)
10318
/*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/
10319
0
{
10320
0
    int res;
10321
10322
0
    Py_BEGIN_ALLOW_THREADS
10323
0
    res = unshare(flags);
10324
0
    Py_END_ALLOW_THREADS
10325
10326
0
    if (res != 0) {
10327
0
        return posix_error();
10328
0
    }
10329
10330
0
    Py_RETURN_NONE;
10331
0
}
10332
#endif
10333
10334
10335
#if defined(HAVE_READLINK) || defined(MS_WINDOWS)
10336
/*[clinic input]
10337
os.readlink
10338
10339
    path: path_t
10340
    *
10341
    dir_fd: dir_fd(requires='readlinkat') = None
10342
10343
Return a string representing the path to which the symbolic link points.
10344
10345
If dir_fd is not None, it should be a file descriptor open to a directory,
10346
and path should be relative; path will then be relative to that directory.
10347
10348
dir_fd may not be implemented on your platform.  If it is unavailable,
10349
using it will raise a NotImplementedError.
10350
[clinic start generated code]*/
10351
10352
static PyObject *
10353
os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
10354
/*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
10355
0
{
10356
0
#if defined(HAVE_READLINK)
10357
0
    char buffer[MAXPATHLEN+1];
10358
0
    ssize_t length;
10359
0
#ifdef HAVE_READLINKAT
10360
0
    int readlinkat_unavailable = 0;
10361
0
#endif
10362
10363
0
    Py_BEGIN_ALLOW_THREADS
10364
0
#ifdef HAVE_READLINKAT
10365
0
    if (dir_fd != DEFAULT_DIR_FD) {
10366
0
        if (HAVE_READLINKAT_RUNTIME) {
10367
0
            length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
10368
0
        } else {
10369
0
            readlinkat_unavailable = 1;
10370
0
        }
10371
0
    } else
10372
0
#endif
10373
0
        length = readlink(path->narrow, buffer, MAXPATHLEN);
10374
0
    Py_END_ALLOW_THREADS
10375
10376
0
#ifdef HAVE_READLINKAT
10377
0
    if (readlinkat_unavailable) {
10378
0
        argument_unavailable_error(NULL, "dir_fd");
10379
0
        return NULL;
10380
0
    }
10381
0
#endif
10382
10383
0
    if (length < 0) {
10384
0
        return path_error(path);
10385
0
    }
10386
0
    buffer[length] = '\0';
10387
10388
0
    if (PyUnicode_Check(path->object))
10389
0
        return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
10390
0
    else
10391
0
        return PyBytes_FromStringAndSize(buffer, length);
10392
#elif defined(MS_WINDOWS)
10393
    DWORD n_bytes_returned;
10394
    DWORD io_result = 0;
10395
    HANDLE reparse_point_handle;
10396
    char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
10397
    _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
10398
    PyObject *result = NULL;
10399
10400
    /* First get a handle to the reparse point */
10401
    Py_BEGIN_ALLOW_THREADS
10402
    reparse_point_handle = CreateFileW(
10403
        path->wide,
10404
        0,
10405
        0,
10406
        0,
10407
        OPEN_EXISTING,
10408
        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
10409
        0);
10410
    if (reparse_point_handle != INVALID_HANDLE_VALUE) {
10411
        /* New call DeviceIoControl to read the reparse point */
10412
        io_result = DeviceIoControl(
10413
            reparse_point_handle,
10414
            FSCTL_GET_REPARSE_POINT,
10415
            0, 0, /* in buffer */
10416
            target_buffer, sizeof(target_buffer),
10417
            &n_bytes_returned,
10418
            0 /* we're not using OVERLAPPED_IO */
10419
            );
10420
        CloseHandle(reparse_point_handle);
10421
    }
10422
    Py_END_ALLOW_THREADS
10423
10424
    if (io_result == 0) {
10425
        return path_error(path);
10426
    }
10427
10428
    wchar_t *name = NULL;
10429
    Py_ssize_t nameLen = 0;
10430
    if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
10431
    {
10432
        name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
10433
                           rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
10434
        nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10435
    }
10436
    else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
10437
    {
10438
        name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
10439
                           rdb->MountPointReparseBuffer.SubstituteNameOffset);
10440
        nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10441
    }
10442
    else
10443
    {
10444
        PyErr_SetString(PyExc_ValueError, "not a symbolic link");
10445
    }
10446
    if (name) {
10447
        if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
10448
            /* Our buffer is mutable, so this is okay */
10449
            name[1] = L'\\';
10450
        }
10451
        result = PyUnicode_FromWideChar(name, nameLen);
10452
        if (result && PyBytes_Check(path->object)) {
10453
            Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
10454
        }
10455
    }
10456
    return result;
10457
#endif
10458
0
}
10459
#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
10460
10461
#if defined(MS_WINDOWS)
10462
10463
/* Remove the last portion of the path - return 0 on success */
10464
static int
10465
_dirnameW(WCHAR *path)
10466
{
10467
    WCHAR *ptr;
10468
    size_t length = wcsnlen_s(path, MAX_PATH);
10469
    if (length == MAX_PATH) {
10470
        return -1;
10471
    }
10472
10473
    /* walk the path from the end until a backslash is encountered */
10474
    for(ptr = path + length; ptr != path; ptr--) {
10475
        if (*ptr == L'\\' || *ptr == L'/') {
10476
            break;
10477
        }
10478
    }
10479
    *ptr = 0;
10480
    return 0;
10481
}
10482
10483
#endif
10484
10485
#ifdef HAVE_SYMLINK
10486
10487
#if defined(MS_WINDOWS)
10488
10489
/* Is this path absolute? */
10490
static int
10491
_is_absW(const WCHAR *path)
10492
{
10493
    return path[0] == L'\\' || path[0] == L'/' ||
10494
        (path[0] && path[1] == L':');
10495
}
10496
10497
/* join root and rest with a backslash - return 0 on success */
10498
static int
10499
_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
10500
{
10501
    if (_is_absW(rest)) {
10502
        return wcscpy_s(dest_path, MAX_PATH, rest);
10503
    }
10504
10505
    if (wcscpy_s(dest_path, MAX_PATH, root)) {
10506
        return -1;
10507
    }
10508
10509
    if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
10510
        return -1;
10511
    }
10512
10513
    return wcscat_s(dest_path, MAX_PATH, rest);
10514
}
10515
10516
/* Return True if the path at src relative to dest is a directory */
10517
static int
10518
_check_dirW(LPCWSTR src, LPCWSTR dest)
10519
{
10520
    WIN32_FILE_ATTRIBUTE_DATA src_info;
10521
    WCHAR dest_parent[MAX_PATH];
10522
    WCHAR src_resolved[MAX_PATH] = L"";
10523
10524
    /* dest_parent = os.path.dirname(dest) */
10525
    if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
10526
        _dirnameW(dest_parent)) {
10527
        return 0;
10528
    }
10529
    /* src_resolved = os.path.join(dest_parent, src) */
10530
    if (_joinW(src_resolved, dest_parent, src)) {
10531
        return 0;
10532
    }
10533
    return (
10534
        GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
10535
        && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
10536
    );
10537
}
10538
#endif
10539
10540
10541
/*[clinic input]
10542
os.symlink
10543
    src: path_t
10544
    dst: path_t
10545
    target_is_directory: bool = False
10546
    *
10547
    dir_fd: dir_fd(requires='symlinkat')=None
10548
10549
# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
10550
10551
Create a symbolic link pointing to src named dst.
10552
10553
target_is_directory is required on Windows if the target is to be
10554
  interpreted as a directory.  (On Windows, symlink requires
10555
  Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
10556
  target_is_directory is ignored on non-Windows platforms.
10557
10558
If dir_fd is not None, it should be a file descriptor open to a directory,
10559
  and path should be relative; path will then be relative to that directory.
10560
dir_fd may not be implemented on your platform.
10561
  If it is unavailable, using it will raise a NotImplementedError.
10562
10563
[clinic start generated code]*/
10564
10565
static PyObject *
10566
os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
10567
                int target_is_directory, int dir_fd)
10568
/*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
10569
0
{
10570
#ifdef MS_WINDOWS
10571
    DWORD result;
10572
    DWORD flags = 0;
10573
10574
    /* Assumed true, set to false if detected to not be available. */
10575
    static int windows_has_symlink_unprivileged_flag = TRUE;
10576
#else
10577
0
    int result;
10578
0
#ifdef HAVE_SYMLINKAT
10579
0
    int symlinkat_unavailable = 0;
10580
0
#endif
10581
0
#endif
10582
10583
0
    if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
10584
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
10585
0
        return NULL;
10586
0
    }
10587
10588
#ifdef MS_WINDOWS
10589
10590
    if (windows_has_symlink_unprivileged_flag) {
10591
        /* Allow non-admin symlinks if system allows it. */
10592
        flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
10593
    }
10594
10595
    Py_BEGIN_ALLOW_THREADS
10596
    _Py_BEGIN_SUPPRESS_IPH
10597
    /* if src is a directory, ensure flags==1 (target_is_directory bit) */
10598
    if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
10599
        flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
10600
    }
10601
10602
    result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
10603
    _Py_END_SUPPRESS_IPH
10604
    Py_END_ALLOW_THREADS
10605
10606
    if (windows_has_symlink_unprivileged_flag && !result &&
10607
        ERROR_INVALID_PARAMETER == GetLastError()) {
10608
10609
        Py_BEGIN_ALLOW_THREADS
10610
        _Py_BEGIN_SUPPRESS_IPH
10611
        /* This error might be caused by
10612
        SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
10613
        Try again, and update windows_has_symlink_unprivileged_flag if we
10614
        are successful this time.
10615
10616
        NOTE: There is a risk of a race condition here if there are other
10617
        conditions than the flag causing ERROR_INVALID_PARAMETER, and
10618
        another process (or thread) changes that condition in between our
10619
        calls to CreateSymbolicLink.
10620
        */
10621
        flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
10622
        result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
10623
        _Py_END_SUPPRESS_IPH
10624
        Py_END_ALLOW_THREADS
10625
10626
        if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
10627
            windows_has_symlink_unprivileged_flag = FALSE;
10628
        }
10629
    }
10630
10631
    if (!result)
10632
        return path_error2(src, dst);
10633
10634
#else
10635
10636
0
    Py_BEGIN_ALLOW_THREADS
10637
0
#ifdef HAVE_SYMLINKAT
10638
0
    if (dir_fd != DEFAULT_DIR_FD) {
10639
0
        if (HAVE_SYMLINKAT_RUNTIME) {
10640
0
            result = symlinkat(src->narrow, dir_fd, dst->narrow);
10641
0
        } else {
10642
0
            symlinkat_unavailable = 1;
10643
0
        }
10644
0
    } else
10645
0
#endif
10646
0
        result = symlink(src->narrow, dst->narrow);
10647
0
    Py_END_ALLOW_THREADS
10648
10649
0
#ifdef HAVE_SYMLINKAT
10650
0
    if (symlinkat_unavailable) {
10651
0
          argument_unavailable_error(NULL, "dir_fd");
10652
0
          return NULL;
10653
0
    }
10654
0
#endif
10655
10656
0
    if (result)
10657
0
        return path_error2(src, dst);
10658
0
#endif
10659
10660
0
    Py_RETURN_NONE;
10661
0
}
10662
#endif /* HAVE_SYMLINK */
10663
10664
10665
static PyStructSequence_Field times_result_fields[] = {
10666
    {"user",    "user time"},
10667
    {"system",   "system time"},
10668
    {"children_user",    "user time of children"},
10669
    {"children_system",    "system time of children"},
10670
    {"elapsed",    "elapsed time since an arbitrary point in the past"},
10671
    {NULL}
10672
};
10673
10674
PyDoc_STRVAR(times_result__doc__,
10675
"times_result: Result from os.times().\n\n\
10676
This object may be accessed either as a tuple of\n\
10677
  (user, system, children_user, children_system, elapsed),\n\
10678
or via the attributes user, system, children_user, children_system,\n\
10679
and elapsed.\n\
10680
\n\
10681
See os.times for more information.");
10682
10683
static PyStructSequence_Desc times_result_desc = {
10684
    "times_result", /* name */
10685
    times_result__doc__, /* doc */
10686
    times_result_fields,
10687
    5
10688
};
10689
10690
static PyObject *
10691
build_times_result(PyObject *module, double user, double system,
10692
    double children_user, double children_system,
10693
    double elapsed)
10694
0
{
10695
0
    PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
10696
0
    PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
10697
0
    if (value == NULL)
10698
0
        return NULL;
10699
10700
0
#define SET(i, field) \
10701
0
    { \
10702
0
    PyObject *o = PyFloat_FromDouble(field); \
10703
0
    if (!o) { \
10704
0
        Py_DECREF(value); \
10705
0
        return NULL; \
10706
0
    } \
10707
0
    PyStructSequence_SET_ITEM(value, i, o); \
10708
0
    } \
10709
0
10710
0
    SET(0, user);
10711
0
    SET(1, system);
10712
0
    SET(2, children_user);
10713
0
    SET(3, children_system);
10714
0
    SET(4, elapsed);
10715
10716
0
#undef SET
10717
10718
0
    return value;
10719
0
}
10720
10721
10722
/*[clinic input]
10723
os.times
10724
10725
Return a collection containing process timing information.
10726
10727
The object returned behaves like a named tuple with these fields:
10728
  (utime, stime, cutime, cstime, elapsed_time)
10729
All fields are floating-point numbers.
10730
[clinic start generated code]*/
10731
10732
static PyObject *
10733
os_times_impl(PyObject *module)
10734
/*[clinic end generated code: output=35f640503557d32a input=8dbfe33a2dcc3df3]*/
10735
0
{
10736
#ifdef MS_WINDOWS
10737
    FILETIME create, exit, kernel, user;
10738
    HANDLE hProc;
10739
    hProc = GetCurrentProcess();
10740
    GetProcessTimes(hProc, &create, &exit, &kernel, &user);
10741
    /* The fields of a FILETIME structure are the hi and lo part
10742
       of a 64-bit value expressed in 100 nanosecond units.
10743
       1e7 is one second in such units; 1e-7 the inverse.
10744
       429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
10745
    */
10746
    return build_times_result(module,
10747
        (double)(user.dwHighDateTime*429.4967296 +
10748
                 user.dwLowDateTime*1e-7),
10749
        (double)(kernel.dwHighDateTime*429.4967296 +
10750
                 kernel.dwLowDateTime*1e-7),
10751
        (double)0,
10752
        (double)0,
10753
        (double)0);
10754
#else /* MS_WINDOWS */
10755
0
    _posixstate *state = get_posix_state(module);
10756
0
    long ticks_per_second = state->ticks_per_second;
10757
10758
0
    struct tms process;
10759
0
    clock_t elapsed;
10760
0
    errno = 0;
10761
0
    elapsed = times(&process);
10762
0
    if (elapsed == (clock_t) -1) {
10763
0
        return posix_error();
10764
0
    }
10765
10766
0
    return build_times_result(module,
10767
0
        (double)process.tms_utime / ticks_per_second,
10768
0
        (double)process.tms_stime / ticks_per_second,
10769
0
        (double)process.tms_cutime / ticks_per_second,
10770
0
        (double)process.tms_cstime / ticks_per_second,
10771
0
        (double)elapsed / ticks_per_second);
10772
0
#endif /* MS_WINDOWS */
10773
0
}
10774
10775
10776
#if defined(HAVE_TIMERFD_CREATE)
10777
#define ONE_SECOND_IN_NS (1000 * 1000 * 1000)
10778
#define EXTRACT_NSEC(value)  (long)( ( (double)(value) - (time_t)(value) ) * 1e9)
10779
0
#define CONVERT_SEC_AND_NSEC_TO_DOUBLE(sec, nsec) ( (double)(sec) + (double)(nsec) * 1e-9 )
10780
10781
static PyObject *
10782
build_itimerspec(const struct itimerspec* curr_value)
10783
0
{
10784
0
    double _value = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_value.tv_sec,
10785
0
                                                          curr_value->it_value.tv_nsec);
10786
0
    PyObject *value = PyFloat_FromDouble(_value);
10787
0
    if (value == NULL) {
10788
0
        return NULL;
10789
0
    }
10790
0
    double _interval = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_interval.tv_sec,
10791
0
                                                   curr_value->it_interval.tv_nsec);
10792
0
    PyObject *interval = PyFloat_FromDouble(_interval);
10793
0
    if (interval == NULL) {
10794
0
        Py_DECREF(value);
10795
0
        return NULL;
10796
0
    }
10797
0
    PyObject *tuple = PyTuple_Pack(2, value, interval);
10798
0
    Py_DECREF(interval);
10799
0
    Py_DECREF(value);
10800
0
    return tuple;
10801
0
}
10802
10803
static PyObject *
10804
build_itimerspec_ns(const struct itimerspec* curr_value)
10805
0
{
10806
0
    PyTime_t value, interval;
10807
0
    if (_PyTime_FromTimespec(&value, &curr_value->it_value) < 0) {
10808
0
        return NULL;
10809
0
    }
10810
0
    if (_PyTime_FromTimespec(&interval, &curr_value->it_interval) < 0) {
10811
0
        return NULL;
10812
0
    }
10813
0
    return Py_BuildValue("LL", value, interval);
10814
0
}
10815
10816
/*[clinic input]
10817
os.timerfd_create
10818
10819
    clockid: int
10820
        A valid clock ID constant as timer file descriptor.
10821
10822
        time.CLOCK_REALTIME
10823
        time.CLOCK_MONOTONIC
10824
        time.CLOCK_BOOTTIME
10825
    /
10826
    *
10827
    flags: int = 0
10828
        0 or a bit mask of os.TFD_NONBLOCK or os.TFD_CLOEXEC.
10829
10830
        os.TFD_NONBLOCK
10831
            If *TFD_NONBLOCK* is set as a flag, read doesn't blocks.
10832
            If *TFD_NONBLOCK* is not set as a flag, read block until the timer fires.
10833
10834
        os.TFD_CLOEXEC
10835
            If *TFD_CLOEXEC* is set as a flag, enable the close-on-exec flag
10836
10837
Create and return a timer file descriptor.
10838
[clinic start generated code]*/
10839
10840
static PyObject *
10841
os_timerfd_create_impl(PyObject *module, int clockid, int flags)
10842
/*[clinic end generated code: output=1caae80fb168004a input=64b7020c5ac0b8f4]*/
10843
10844
0
{
10845
0
    int fd;
10846
0
    Py_BEGIN_ALLOW_THREADS
10847
0
    flags |= TFD_CLOEXEC;  // PEP 446: always create non-inheritable FD
10848
0
    fd = timerfd_create(clockid, flags);
10849
0
    Py_END_ALLOW_THREADS
10850
0
    if (fd == -1) {
10851
0
        return PyErr_SetFromErrno(PyExc_OSError);
10852
0
    }
10853
0
    return PyLong_FromLong(fd);
10854
0
}
10855
10856
/*[clinic input]
10857
os.timerfd_settime
10858
10859
    fd: fildes
10860
        A timer file descriptor.
10861
    /
10862
    *
10863
    flags: int = 0
10864
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
10865
    initial as initial_double: double = 0.0
10866
        The initial expiration time, in seconds.
10867
    interval as interval_double: double = 0.0
10868
        The timer's interval, in seconds.
10869
10870
Alter a timer file descriptor's internal timer in seconds.
10871
[clinic start generated code]*/
10872
10873
static PyObject *
10874
os_timerfd_settime_impl(PyObject *module, int fd, int flags,
10875
                        double initial_double, double interval_double)
10876
/*[clinic end generated code: output=df4c1bce6859224e input=81d2c0d7e936e8a7]*/
10877
0
{
10878
0
    PyTime_t initial, interval;
10879
0
    if (_PyTime_FromSecondsDouble(initial_double, _PyTime_ROUND_FLOOR,
10880
0
                                  &initial) < 0) {
10881
0
        return NULL;
10882
0
    }
10883
0
    if (_PyTime_FromSecondsDouble(interval_double, _PyTime_ROUND_FLOOR,
10884
0
                                  &interval) < 0) {
10885
0
        return NULL;
10886
0
    }
10887
10888
0
    struct itimerspec new_value, old_value;
10889
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
10890
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
10891
0
        return NULL;
10892
0
    }
10893
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
10894
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
10895
0
        return NULL;
10896
0
    }
10897
10898
0
    int result;
10899
0
    Py_BEGIN_ALLOW_THREADS
10900
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
10901
0
    Py_END_ALLOW_THREADS
10902
0
    if (result == -1) {
10903
0
        return PyErr_SetFromErrno(PyExc_OSError);
10904
0
    }
10905
0
    return build_itimerspec(&old_value);
10906
0
}
10907
10908
10909
/*[clinic input]
10910
os.timerfd_settime_ns
10911
10912
    fd: fildes
10913
        A timer file descriptor.
10914
    /
10915
    *
10916
    flags: int = 0
10917
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
10918
    initial: long_long = 0
10919
        initial expiration timing in seconds.
10920
    interval: long_long = 0
10921
        interval for the timer in seconds.
10922
10923
Alter a timer file descriptor's internal timer in nanoseconds.
10924
[clinic start generated code]*/
10925
10926
static PyObject *
10927
os_timerfd_settime_ns_impl(PyObject *module, int fd, int flags,
10928
                           long long initial, long long interval)
10929
/*[clinic end generated code: output=6273ec7d7b4cc0b3 input=261e105d6e42f5bc]*/
10930
0
{
10931
0
    struct itimerspec new_value;
10932
0
    struct itimerspec old_value;
10933
0
    int result;
10934
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
10935
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
10936
0
        return NULL;
10937
0
    }
10938
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
10939
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
10940
0
        return NULL;
10941
0
    }
10942
0
    Py_BEGIN_ALLOW_THREADS
10943
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
10944
0
    Py_END_ALLOW_THREADS
10945
0
    if (result == -1) {
10946
0
        return PyErr_SetFromErrno(PyExc_OSError);
10947
0
    }
10948
0
    return build_itimerspec_ns(&old_value);
10949
0
}
10950
10951
/*[clinic input]
10952
os.timerfd_gettime
10953
10954
    fd: fildes
10955
        A timer file descriptor.
10956
    /
10957
10958
Return a tuple of a timer file descriptor's (interval, next expiration) in float seconds.
10959
[clinic start generated code]*/
10960
10961
static PyObject *
10962
os_timerfd_gettime_impl(PyObject *module, int fd)
10963
/*[clinic end generated code: output=ec5a94a66cfe6ab4 input=8148e3430870da1c]*/
10964
0
{
10965
0
    struct itimerspec curr_value;
10966
0
    int result;
10967
0
    Py_BEGIN_ALLOW_THREADS
10968
0
    result = timerfd_gettime(fd, &curr_value);
10969
0
    Py_END_ALLOW_THREADS
10970
0
    if (result == -1) {
10971
0
        return PyErr_SetFromErrno(PyExc_OSError);
10972
0
    }
10973
0
    return build_itimerspec(&curr_value);
10974
0
}
10975
10976
10977
/*[clinic input]
10978
os.timerfd_gettime_ns
10979
10980
    fd: fildes
10981
        A timer file descriptor.
10982
    /
10983
10984
Return a tuple of a timer file descriptor's (interval, next expiration) in nanoseconds.
10985
[clinic start generated code]*/
10986
10987
static PyObject *
10988
os_timerfd_gettime_ns_impl(PyObject *module, int fd)
10989
/*[clinic end generated code: output=580633a4465f39fe input=a825443e4c6b40ac]*/
10990
0
{
10991
0
    struct itimerspec curr_value;
10992
0
    int result;
10993
0
    Py_BEGIN_ALLOW_THREADS
10994
0
    result = timerfd_gettime(fd, &curr_value);
10995
0
    Py_END_ALLOW_THREADS
10996
0
    if (result == -1) {
10997
0
        return PyErr_SetFromErrno(PyExc_OSError);
10998
0
    }
10999
0
    return build_itimerspec_ns(&curr_value);
11000
0
}
11001
11002
#undef ONE_SECOND_IN_NS
11003
#undef EXTRACT_NSEC
11004
11005
#endif  /* HAVE_TIMERFD_CREATE */
11006
11007
#ifdef HAVE_GETSID
11008
/*[clinic input]
11009
os.getsid
11010
11011
    pid: pid_t
11012
    /
11013
11014
Call the system call getsid(pid) and return the result.
11015
[clinic start generated code]*/
11016
11017
static PyObject *
11018
os_getsid_impl(PyObject *module, pid_t pid)
11019
/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
11020
0
{
11021
0
    int sid;
11022
0
    sid = getsid(pid);
11023
0
    if (sid < 0)
11024
0
        return posix_error();
11025
0
    return PyLong_FromLong((long)sid);
11026
0
}
11027
#endif /* HAVE_GETSID */
11028
11029
11030
#ifdef HAVE_SETSID
11031
/*[clinic input]
11032
os.setsid
11033
11034
Call the system call setsid().
11035
[clinic start generated code]*/
11036
11037
static PyObject *
11038
os_setsid_impl(PyObject *module)
11039
/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
11040
0
{
11041
0
    if (setsid() < 0)
11042
0
        return posix_error();
11043
0
    Py_RETURN_NONE;
11044
0
}
11045
#endif /* HAVE_SETSID */
11046
11047
11048
#ifdef HAVE_SETPGID
11049
/*[clinic input]
11050
os.setpgid
11051
11052
    pid: pid_t
11053
    pgrp: pid_t
11054
    /
11055
11056
Call the system call setpgid(pid, pgrp).
11057
[clinic start generated code]*/
11058
11059
static PyObject *
11060
os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
11061
/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
11062
0
{
11063
0
    if (setpgid(pid, pgrp) < 0)
11064
0
        return posix_error();
11065
0
    Py_RETURN_NONE;
11066
0
}
11067
#endif /* HAVE_SETPGID */
11068
11069
11070
#ifdef HAVE_TCGETPGRP
11071
/*[clinic input]
11072
os.tcgetpgrp
11073
11074
    fd: int
11075
    /
11076
11077
Return the process group associated with the terminal specified by fd.
11078
[clinic start generated code]*/
11079
11080
static PyObject *
11081
os_tcgetpgrp_impl(PyObject *module, int fd)
11082
/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
11083
0
{
11084
0
    pid_t pgid = tcgetpgrp(fd);
11085
0
    if (pgid < 0)
11086
0
        return posix_error();
11087
0
    return PyLong_FromPid(pgid);
11088
0
}
11089
#endif /* HAVE_TCGETPGRP */
11090
11091
11092
#ifdef HAVE_TCSETPGRP
11093
/*[clinic input]
11094
os.tcsetpgrp
11095
11096
    fd: int
11097
    pgid: pid_t
11098
    /
11099
11100
Set the process group associated with the terminal specified by fd.
11101
[clinic start generated code]*/
11102
11103
static PyObject *
11104
os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
11105
/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
11106
0
{
11107
0
    if (tcsetpgrp(fd, pgid) < 0)
11108
0
        return posix_error();
11109
0
    Py_RETURN_NONE;
11110
0
}
11111
#endif /* HAVE_TCSETPGRP */
11112
11113
/* Functions acting on file descriptors */
11114
11115
#ifdef O_CLOEXEC
11116
extern int _Py_open_cloexec_works;
11117
#endif
11118
11119
11120
/*[clinic input]
11121
os.open -> int
11122
    path: path_t
11123
    flags: int
11124
    mode: int = 0o777
11125
    *
11126
    dir_fd: dir_fd(requires='openat') = None
11127
11128
# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
11129
11130
Open a file for low level IO.  Returns a file descriptor (integer).
11131
11132
If dir_fd is not None, it should be a file descriptor open to a directory,
11133
  and path should be relative; path will then be relative to that directory.
11134
dir_fd may not be implemented on your platform.
11135
  If it is unavailable, using it will raise a NotImplementedError.
11136
[clinic start generated code]*/
11137
11138
static int
11139
os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
11140
/*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
11141
216
{
11142
216
    int fd;
11143
216
    int async_err = 0;
11144
216
#ifdef HAVE_OPENAT
11145
216
    int openat_unavailable = 0;
11146
216
#endif
11147
11148
216
#ifdef O_CLOEXEC
11149
216
    int *atomic_flag_works = &_Py_open_cloexec_works;
11150
#elif !defined(MS_WINDOWS)
11151
    int *atomic_flag_works = NULL;
11152
#endif
11153
11154
#ifdef MS_WINDOWS
11155
    flags |= O_NOINHERIT;
11156
#elif defined(O_CLOEXEC)
11157
    flags |= O_CLOEXEC;
11158
216
#endif
11159
11160
216
    if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
11161
0
        return -1;
11162
0
    }
11163
11164
216
    _Py_BEGIN_SUPPRESS_IPH
11165
216
    do {
11166
216
        Py_BEGIN_ALLOW_THREADS
11167
#ifdef MS_WINDOWS
11168
        fd = _wopen(path->wide, flags, mode);
11169
#else
11170
216
#ifdef HAVE_OPENAT
11171
216
        if (dir_fd != DEFAULT_DIR_FD) {
11172
0
            if (HAVE_OPENAT_RUNTIME) {
11173
0
                fd = openat(dir_fd, path->narrow, flags, mode);
11174
11175
0
            } else {
11176
0
                openat_unavailable = 1;
11177
0
                fd = -1;
11178
0
            }
11179
0
        } else
11180
216
#endif /* HAVE_OPENAT */
11181
216
            fd = open(path->narrow, flags, mode);
11182
216
#endif /* !MS_WINDOWS */
11183
216
        Py_END_ALLOW_THREADS
11184
216
    } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11185
216
    _Py_END_SUPPRESS_IPH
11186
11187
216
#ifdef HAVE_OPENAT
11188
216
    if (openat_unavailable) {
11189
0
        argument_unavailable_error(NULL, "dir_fd");
11190
0
        return -1;
11191
0
    }
11192
216
#endif
11193
11194
216
    if (fd < 0) {
11195
0
        if (!async_err)
11196
0
            PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
11197
0
        return -1;
11198
0
    }
11199
11200
216
#ifndef MS_WINDOWS
11201
216
    if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
11202
0
        close(fd);
11203
0
        return -1;
11204
0
    }
11205
216
#endif
11206
11207
216
    return fd;
11208
216
}
11209
11210
11211
/*[clinic input]
11212
os.close
11213
11214
    fd: int
11215
11216
Close a file descriptor.
11217
[clinic start generated code]*/
11218
11219
static PyObject *
11220
os_close_impl(PyObject *module, int fd)
11221
/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
11222
0
{
11223
0
    int res;
11224
    /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
11225
     * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
11226
     * for more details.
11227
     */
11228
0
    Py_BEGIN_ALLOW_THREADS
11229
0
    _Py_BEGIN_SUPPRESS_IPH
11230
0
    res = close(fd);
11231
0
    _Py_END_SUPPRESS_IPH
11232
0
    Py_END_ALLOW_THREADS
11233
0
    if (res < 0)
11234
0
        return posix_error();
11235
0
    Py_RETURN_NONE;
11236
0
}
11237
11238
/*[clinic input]
11239
os.closerange
11240
11241
    fd_low: int
11242
    fd_high: int
11243
    /
11244
11245
Closes all file descriptors in [fd_low, fd_high), ignoring errors.
11246
[clinic start generated code]*/
11247
11248
static PyObject *
11249
os_closerange_impl(PyObject *module, int fd_low, int fd_high)
11250
/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
11251
0
{
11252
0
    Py_BEGIN_ALLOW_THREADS
11253
0
    _Py_closerange(fd_low, fd_high - 1);
11254
0
    Py_END_ALLOW_THREADS
11255
0
    Py_RETURN_NONE;
11256
0
}
11257
11258
11259
/*[clinic input]
11260
os.dup -> int
11261
11262
    fd: int
11263
    /
11264
11265
Return a duplicate of a file descriptor.
11266
[clinic start generated code]*/
11267
11268
static int
11269
os_dup_impl(PyObject *module, int fd)
11270
/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
11271
0
{
11272
0
    return _Py_dup(fd);
11273
0
}
11274
11275
// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
11276
// dup2.c provides working dup2() if and only if F_DUPFD is available.
11277
#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
11278
/*[clinic input]
11279
os.dup2 -> int
11280
    fd: int
11281
    fd2: int
11282
    inheritable: bool=True
11283
11284
Duplicate file descriptor.
11285
[clinic start generated code]*/
11286
11287
static int
11288
os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
11289
/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
11290
0
{
11291
0
    int res = 0;
11292
0
#if defined(HAVE_DUP3) && \
11293
0
    !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
11294
    /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
11295
0
    static int dup3_works = -1;
11296
0
#endif
11297
11298
    /* dup2() can fail with EINTR if the target FD is already open, because it
11299
     * then has to be closed. See os_close_impl() for why we don't handle EINTR
11300
     * upon close(), and therefore below.
11301
     */
11302
#ifdef MS_WINDOWS
11303
    Py_BEGIN_ALLOW_THREADS
11304
    _Py_BEGIN_SUPPRESS_IPH
11305
    res = dup2(fd, fd2);
11306
    _Py_END_SUPPRESS_IPH
11307
    Py_END_ALLOW_THREADS
11308
    if (res < 0) {
11309
        posix_error();
11310
        return -1;
11311
    }
11312
    res = fd2; // msvcrt dup2 returns 0 on success.
11313
11314
    /* Character files like console cannot be make non-inheritable */
11315
    if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11316
        close(fd2);
11317
        return -1;
11318
    }
11319
11320
#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
11321
    Py_BEGIN_ALLOW_THREADS
11322
    if (!inheritable)
11323
        res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
11324
    else
11325
        res = dup2(fd, fd2);
11326
    Py_END_ALLOW_THREADS
11327
    if (res < 0) {
11328
        posix_error();
11329
        return -1;
11330
    }
11331
11332
#else
11333
11334
0
#ifdef HAVE_DUP3
11335
0
    if (!inheritable && dup3_works != 0) {
11336
0
        Py_BEGIN_ALLOW_THREADS
11337
0
        res = dup3(fd, fd2, O_CLOEXEC);
11338
0
        Py_END_ALLOW_THREADS
11339
0
        if (res < 0) {
11340
0
            if (dup3_works == -1)
11341
0
                dup3_works = (errno != ENOSYS);
11342
0
            if (dup3_works) {
11343
0
                posix_error();
11344
0
                return -1;
11345
0
            }
11346
0
        }
11347
0
    }
11348
11349
0
    if (inheritable || dup3_works == 0)
11350
0
    {
11351
0
#endif
11352
0
        Py_BEGIN_ALLOW_THREADS
11353
0
        res = dup2(fd, fd2);
11354
0
        Py_END_ALLOW_THREADS
11355
0
        if (res < 0) {
11356
0
            posix_error();
11357
0
            return -1;
11358
0
        }
11359
11360
0
        if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11361
0
            close(fd2);
11362
0
            return -1;
11363
0
        }
11364
0
#ifdef HAVE_DUP3
11365
0
    }
11366
0
#endif
11367
11368
0
#endif
11369
11370
0
    return res;
11371
0
}
11372
#endif
11373
11374
11375
#ifdef HAVE_LOCKF
11376
/*[clinic input]
11377
os.lockf
11378
11379
    fd: int
11380
        An open file descriptor.
11381
    command: int
11382
        One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
11383
    length: Py_off_t
11384
        The number of bytes to lock, starting at the current position.
11385
    /
11386
11387
Apply, test or remove a POSIX lock on an open file descriptor.
11388
11389
[clinic start generated code]*/
11390
11391
static PyObject *
11392
os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
11393
/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
11394
0
{
11395
0
    int res;
11396
11397
0
    if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
11398
0
        return NULL;
11399
0
    }
11400
11401
0
    Py_BEGIN_ALLOW_THREADS
11402
0
    res = lockf(fd, command, length);
11403
0
    Py_END_ALLOW_THREADS
11404
11405
0
    if (res < 0)
11406
0
        return posix_error();
11407
11408
0
    Py_RETURN_NONE;
11409
0
}
11410
#endif /* HAVE_LOCKF */
11411
11412
11413
/*[clinic input]
11414
os.lseek -> Py_off_t
11415
11416
    fd: int
11417
        An open file descriptor, as returned by os.open().
11418
    position: Py_off_t
11419
        Position, interpreted relative to 'whence'.
11420
    whence as how: int
11421
        The relative position to seek from. Valid values are:
11422
        - SEEK_SET: seek from the start of the file.
11423
        - SEEK_CUR: seek from the current file position.
11424
        - SEEK_END: seek from the end of the file.
11425
    /
11426
11427
Set the position of a file descriptor.  Return the new position.
11428
11429
The return value is the number of bytes relative to the beginning of the file.
11430
[clinic start generated code]*/
11431
11432
static Py_off_t
11433
os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
11434
/*[clinic end generated code: output=971e1efb6b30bd2f input=f096e754c5367504]*/
11435
0
{
11436
0
    Py_off_t result;
11437
11438
0
#ifdef SEEK_SET
11439
    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
11440
0
    switch (how) {
11441
0
        case 0: how = SEEK_SET; break;
11442
0
        case 1: how = SEEK_CUR; break;
11443
0
        case 2: how = SEEK_END; break;
11444
0
    }
11445
0
#endif /* SEEK_END */
11446
11447
0
    Py_BEGIN_ALLOW_THREADS
11448
0
    _Py_BEGIN_SUPPRESS_IPH
11449
#ifdef MS_WINDOWS
11450
    result = _lseeki64(fd, position, how);
11451
#else
11452
0
    result = lseek(fd, position, how);
11453
0
#endif
11454
0
    _Py_END_SUPPRESS_IPH
11455
0
    Py_END_ALLOW_THREADS
11456
0
    if (result < 0)
11457
0
        posix_error();
11458
11459
0
    return result;
11460
0
}
11461
11462
11463
/*[clinic input]
11464
os.read
11465
    fd: int
11466
    length: Py_ssize_t
11467
    /
11468
11469
Read from a file descriptor.  Returns a bytes object.
11470
[clinic start generated code]*/
11471
11472
static PyObject *
11473
os_read_impl(PyObject *module, int fd, Py_ssize_t length)
11474
/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
11475
0
{
11476
0
    Py_ssize_t n;
11477
0
    PyObject *buffer;
11478
11479
0
    if (length < 0) {
11480
0
        errno = EINVAL;
11481
0
        return posix_error();
11482
0
    }
11483
11484
0
    length = Py_MIN(length, _PY_READ_MAX);
11485
11486
0
    buffer = PyBytes_FromStringAndSize((char *)NULL, length);
11487
0
    if (buffer == NULL)
11488
0
        return NULL;
11489
11490
0
    n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
11491
0
    if (n == -1) {
11492
0
        Py_DECREF(buffer);
11493
0
        return NULL;
11494
0
    }
11495
11496
0
    if (n != length)
11497
0
        _PyBytes_Resize(&buffer, n);
11498
11499
0
    return buffer;
11500
0
}
11501
11502
/*[clinic input]
11503
os.readinto -> Py_ssize_t
11504
    fd: int
11505
    buffer: Py_buffer(accept={rwbuffer})
11506
    /
11507
11508
Read into a buffer object from a file descriptor.
11509
11510
The buffer should be mutable and bytes-like. On success, returns the number of
11511
bytes read. Less bytes may be read than the size of the buffer. The underlying
11512
system call will be retried when interrupted by a signal, unless the signal
11513
handler raises an exception. Other errors will not be retried and an error will
11514
be raised.
11515
11516
Returns 0 if *fd* is at end of file or if the provided *buffer* has length 0
11517
(which can be used to check for errors without reading data). Never returns
11518
negative.
11519
[clinic start generated code]*/
11520
11521
static Py_ssize_t
11522
os_readinto_impl(PyObject *module, int fd, Py_buffer *buffer)
11523
/*[clinic end generated code: output=8091a3513c683a80 input=d40074d0a68de575]*/
11524
0
{
11525
0
    assert(buffer->len >= 0);
11526
0
    Py_ssize_t result = _Py_read(fd, buffer->buf, buffer->len);
11527
    /* Ensure negative is never returned without an error. Simplifies calling
11528
        code. _Py_read should succeed, possibly reading 0 bytes, _or_ set an
11529
        error. */
11530
0
    assert(result >= 0 || (result == -1 && PyErr_Occurred()));
11531
0
    return result;
11532
0
}
11533
11534
#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
11535
                                || defined(__APPLE__))) \
11536
    || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
11537
    || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
11538
static int
11539
iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
11540
0
{
11541
0
    Py_ssize_t i, j;
11542
11543
0
    *iov = PyMem_New(struct iovec, cnt);
11544
0
    if (*iov == NULL) {
11545
0
        PyErr_NoMemory();
11546
0
        return -1;
11547
0
    }
11548
11549
0
    *buf = PyMem_New(Py_buffer, cnt);
11550
0
    if (*buf == NULL) {
11551
0
        PyMem_Free(*iov);
11552
0
        PyErr_NoMemory();
11553
0
        return -1;
11554
0
    }
11555
11556
0
    for (i = 0; i < cnt; i++) {
11557
0
        PyObject *item = PySequence_GetItem(seq, i);
11558
0
        if (item == NULL)
11559
0
            goto fail;
11560
0
        if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
11561
0
            Py_DECREF(item);
11562
0
            goto fail;
11563
0
        }
11564
0
        Py_DECREF(item);
11565
0
        (*iov)[i].iov_base = (*buf)[i].buf;
11566
0
        (*iov)[i].iov_len = (*buf)[i].len;
11567
0
    }
11568
0
    return 0;
11569
11570
0
fail:
11571
0
    PyMem_Free(*iov);
11572
0
    for (j = 0; j < i; j++) {
11573
0
        PyBuffer_Release(&(*buf)[j]);
11574
0
    }
11575
0
    PyMem_Free(*buf);
11576
0
    return -1;
11577
0
}
11578
11579
static void
11580
iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
11581
0
{
11582
0
    int i;
11583
0
    PyMem_Free(iov);
11584
0
    for (i = 0; i < cnt; i++) {
11585
0
        PyBuffer_Release(&buf[i]);
11586
0
    }
11587
0
    PyMem_Free(buf);
11588
0
}
11589
#endif
11590
11591
11592
#ifdef HAVE_READV
11593
/*[clinic input]
11594
os.readv -> Py_ssize_t
11595
11596
    fd: int
11597
    buffers: object
11598
    /
11599
11600
Read from a file descriptor fd into an iterable of buffers.
11601
11602
The buffers should be mutable buffers accepting bytes.
11603
readv will transfer data into each buffer until it is full
11604
and then move on to the next buffer in the sequence to hold
11605
the rest of the data.
11606
11607
readv returns the total number of bytes read,
11608
which may be less than the total capacity of all the buffers.
11609
[clinic start generated code]*/
11610
11611
static Py_ssize_t
11612
os_readv_impl(PyObject *module, int fd, PyObject *buffers)
11613
/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
11614
0
{
11615
0
    Py_ssize_t cnt, n;
11616
0
    int async_err = 0;
11617
0
    struct iovec *iov;
11618
0
    Py_buffer *buf;
11619
11620
0
    if (!PySequence_Check(buffers)) {
11621
0
        PyErr_SetString(PyExc_TypeError,
11622
0
            "readv() arg 2 must be a sequence");
11623
0
        return -1;
11624
0
    }
11625
11626
0
    cnt = PySequence_Size(buffers);
11627
0
    if (cnt < 0)
11628
0
        return -1;
11629
11630
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
11631
0
        return -1;
11632
11633
0
    do {
11634
0
        Py_BEGIN_ALLOW_THREADS
11635
0
        n = readv(fd, iov, cnt);
11636
0
        Py_END_ALLOW_THREADS
11637
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11638
11639
0
    int saved_errno = errno;
11640
0
    iov_cleanup(iov, buf, cnt);
11641
0
    if (n < 0) {
11642
0
        if (!async_err) {
11643
0
            errno = saved_errno;
11644
0
            posix_error();
11645
0
        }
11646
0
        return -1;
11647
0
    }
11648
11649
0
    return n;
11650
0
}
11651
#endif /* HAVE_READV */
11652
11653
11654
#ifdef HAVE_PREAD
11655
/*[clinic input]
11656
os.pread
11657
11658
    fd: int
11659
    length: Py_ssize_t
11660
    offset: Py_off_t
11661
    /
11662
11663
Read a number of bytes from a file descriptor starting at a particular offset.
11664
11665
Read length bytes from file descriptor fd, starting at offset bytes from
11666
the beginning of the file.  The file offset remains unchanged.
11667
[clinic start generated code]*/
11668
11669
static PyObject *
11670
os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
11671
/*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/
11672
0
{
11673
0
    Py_ssize_t n;
11674
0
    int async_err = 0;
11675
0
    PyObject *buffer;
11676
11677
0
    if (length < 0) {
11678
0
        errno = EINVAL;
11679
0
        return posix_error();
11680
0
    }
11681
0
    buffer = PyBytes_FromStringAndSize((char *)NULL, length);
11682
0
    if (buffer == NULL)
11683
0
        return NULL;
11684
11685
0
    do {
11686
0
        Py_BEGIN_ALLOW_THREADS
11687
0
        _Py_BEGIN_SUPPRESS_IPH
11688
0
        n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
11689
0
        _Py_END_SUPPRESS_IPH
11690
0
        Py_END_ALLOW_THREADS
11691
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11692
11693
0
    if (n < 0) {
11694
0
        if (!async_err) {
11695
0
            posix_error();
11696
0
        }
11697
0
        Py_DECREF(buffer);
11698
0
        return NULL;
11699
0
    }
11700
0
    if (n != length)
11701
0
        _PyBytes_Resize(&buffer, n);
11702
0
    return buffer;
11703
0
}
11704
#endif /* HAVE_PREAD */
11705
11706
#if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
11707
/*[clinic input]
11708
os.preadv -> Py_ssize_t
11709
11710
    fd: int
11711
    buffers: object
11712
    offset: Py_off_t
11713
    flags: int = 0
11714
    /
11715
11716
Reads from a file descriptor into a number of mutable bytes-like objects.
11717
11718
Combines the functionality of readv() and pread(). As readv(), it will
11719
transfer data into each buffer until it is full and then move on to the next
11720
buffer in the sequence to hold the rest of the data. Its fourth argument,
11721
specifies the file offset at which the input operation is to be performed. It
11722
will return the total number of bytes read (which can be less than the total
11723
capacity of all the objects).
11724
11725
The flags argument contains a bitwise OR of zero or more of the following flags:
11726
11727
- RWF_HIPRI
11728
- RWF_NOWAIT
11729
11730
Using non-zero flags requires Linux 4.6 or newer.
11731
[clinic start generated code]*/
11732
11733
static Py_ssize_t
11734
os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
11735
               int flags)
11736
/*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
11737
0
{
11738
0
    Py_ssize_t cnt, n;
11739
0
    int async_err = 0;
11740
0
    struct iovec *iov;
11741
0
    Py_buffer *buf;
11742
11743
0
    if (!PySequence_Check(buffers)) {
11744
0
        PyErr_SetString(PyExc_TypeError,
11745
0
            "preadv2() arg 2 must be a sequence");
11746
0
        return -1;
11747
0
    }
11748
11749
0
    cnt = PySequence_Size(buffers);
11750
0
    if (cnt < 0) {
11751
0
        return -1;
11752
0
    }
11753
11754
#ifndef HAVE_PREADV2
11755
    if(flags != 0) {
11756
        argument_unavailable_error("preadv2", "flags");
11757
        return -1;
11758
    }
11759
#endif
11760
11761
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
11762
0
        return -1;
11763
0
    }
11764
0
#ifdef HAVE_PREADV2
11765
0
    do {
11766
0
        Py_BEGIN_ALLOW_THREADS
11767
0
        _Py_BEGIN_SUPPRESS_IPH
11768
0
        n = preadv2(fd, iov, cnt, offset, flags);
11769
0
        _Py_END_SUPPRESS_IPH
11770
0
        Py_END_ALLOW_THREADS
11771
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11772
#else
11773
    do {
11774
#if defined(__APPLE__) && defined(__clang__)
11775
/* This entire function will be removed from the module dict when the API
11776
 * is not available.
11777
 */
11778
#pragma clang diagnostic push
11779
#pragma clang diagnostic ignored "-Wunguarded-availability"
11780
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
11781
#endif
11782
        Py_BEGIN_ALLOW_THREADS
11783
        _Py_BEGIN_SUPPRESS_IPH
11784
        n = preadv(fd, iov, cnt, offset);
11785
        _Py_END_SUPPRESS_IPH
11786
        Py_END_ALLOW_THREADS
11787
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11788
11789
#if defined(__APPLE__) && defined(__clang__)
11790
#pragma clang diagnostic pop
11791
#endif
11792
11793
#endif
11794
11795
0
    int saved_errno = errno;
11796
0
    iov_cleanup(iov, buf, cnt);
11797
0
    if (n < 0) {
11798
0
        if (!async_err) {
11799
0
            errno = saved_errno;
11800
0
            posix_error();
11801
0
        }
11802
0
        return -1;
11803
0
    }
11804
11805
0
    return n;
11806
0
}
11807
#endif /* HAVE_PREADV */
11808
11809
11810
/*[clinic input]
11811
os.write -> Py_ssize_t
11812
11813
    fd: int
11814
    data: Py_buffer
11815
    /
11816
11817
Write a bytes object to a file descriptor.
11818
[clinic start generated code]*/
11819
11820
static Py_ssize_t
11821
os_write_impl(PyObject *module, int fd, Py_buffer *data)
11822
/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
11823
0
{
11824
0
    return _Py_write(fd, data->buf, data->len);
11825
0
}
11826
11827
#ifdef HAVE_SENDFILE
11828
#ifdef __APPLE__
11829
/*[clinic input]
11830
os.sendfile
11831
11832
    out_fd: int
11833
    in_fd: int
11834
    offset: Py_off_t
11835
    count as sbytes: Py_off_t
11836
    headers: object(c_default="NULL") = ()
11837
    trailers: object(c_default="NULL") = ()
11838
    flags: int = 0
11839
11840
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
11841
[clinic start generated code]*/
11842
11843
static PyObject *
11844
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
11845
                 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
11846
                 int flags)
11847
/*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
11848
#elif defined(__FreeBSD__) || defined(__DragonFly__)
11849
/*[clinic input]
11850
os.sendfile
11851
11852
    out_fd: int
11853
    in_fd: int
11854
    offset: Py_off_t
11855
    count: Py_ssize_t
11856
    headers: object(c_default="NULL") = ()
11857
    trailers: object(c_default="NULL") = ()
11858
    flags: int = 0
11859
11860
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
11861
[clinic start generated code]*/
11862
11863
static PyObject *
11864
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
11865
                 Py_ssize_t count, PyObject *headers, PyObject *trailers,
11866
                 int flags)
11867
/*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/
11868
#else
11869
/*[clinic input]
11870
os.sendfile
11871
11872
    out_fd: int
11873
    in_fd: int
11874
    offset as offobj: object
11875
    count: Py_ssize_t
11876
11877
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
11878
[clinic start generated code]*/
11879
11880
static PyObject *
11881
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
11882
                 Py_ssize_t count)
11883
/*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/
11884
#endif
11885
0
{
11886
0
    Py_ssize_t ret;
11887
0
    int async_err = 0;
11888
11889
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
11890
#ifndef __APPLE__
11891
    off_t sbytes;
11892
#endif
11893
    Py_buffer *hbuf, *tbuf;
11894
    struct sf_hdtr sf;
11895
11896
    sf.headers = NULL;
11897
    sf.trailers = NULL;
11898
11899
    if (headers != NULL) {
11900
        if (!PySequence_Check(headers)) {
11901
            PyErr_SetString(PyExc_TypeError,
11902
                "sendfile() headers must be a sequence");
11903
            return NULL;
11904
        } else {
11905
            Py_ssize_t i = PySequence_Size(headers);
11906
            if (i < 0)
11907
                return NULL;
11908
            if (i > INT_MAX) {
11909
                PyErr_SetString(PyExc_OverflowError,
11910
                    "sendfile() header is too large");
11911
                return NULL;
11912
            }
11913
            if (i > 0) {
11914
                sf.hdr_cnt = (int)i;
11915
                if (iov_setup(&(sf.headers), &hbuf,
11916
                              headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
11917
                    return NULL;
11918
#ifdef __APPLE__
11919
                for (i = 0; i < sf.hdr_cnt; i++) {
11920
                    Py_ssize_t blen = sf.headers[i].iov_len;
11921
# define OFF_T_MAX 0x7fffffffffffffff
11922
                    if (sbytes >= OFF_T_MAX - blen) {
11923
                        PyErr_SetString(PyExc_OverflowError,
11924
                            "sendfile() header is too large");
11925
                        return NULL;
11926
                    }
11927
                    sbytes += blen;
11928
                }
11929
#endif
11930
            }
11931
        }
11932
    }
11933
    if (trailers != NULL) {
11934
        if (!PySequence_Check(trailers)) {
11935
            PyErr_SetString(PyExc_TypeError,
11936
                "sendfile() trailers must be a sequence");
11937
            return NULL;
11938
        } else {
11939
            Py_ssize_t i = PySequence_Size(trailers);
11940
            if (i < 0)
11941
                return NULL;
11942
            if (i > INT_MAX) {
11943
                PyErr_SetString(PyExc_OverflowError,
11944
                    "sendfile() trailer is too large");
11945
                return NULL;
11946
            }
11947
            if (i > 0) {
11948
                sf.trl_cnt = (int)i;
11949
                if (iov_setup(&(sf.trailers), &tbuf,
11950
                              trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
11951
                    return NULL;
11952
            }
11953
        }
11954
    }
11955
11956
    _Py_BEGIN_SUPPRESS_IPH
11957
    do {
11958
        Py_BEGIN_ALLOW_THREADS
11959
#ifdef __APPLE__
11960
        ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
11961
#else
11962
        ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
11963
#endif
11964
        Py_END_ALLOW_THREADS
11965
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11966
    _Py_END_SUPPRESS_IPH
11967
11968
    int saved_errno = errno;
11969
    if (sf.headers != NULL)
11970
        iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
11971
    if (sf.trailers != NULL)
11972
        iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
11973
11974
    if (ret < 0) {
11975
        if ((saved_errno == EAGAIN) || (saved_errno == EBUSY)) {
11976
            if (sbytes != 0) {
11977
                // some data has been sent
11978
                goto done;
11979
            }
11980
            // no data has been sent; upper application is supposed
11981
            // to retry on EAGAIN or EBUSY
11982
        }
11983
        if (!async_err) {
11984
            errno = saved_errno;
11985
            posix_error();
11986
        }
11987
        return NULL;
11988
    }
11989
    goto done;
11990
11991
done:
11992
    #if !defined(HAVE_LARGEFILE_SUPPORT)
11993
        return PyLong_FromLong(sbytes);
11994
    #else
11995
        return PyLong_FromLongLong(sbytes);
11996
    #endif
11997
11998
#else
11999
0
#ifdef __linux__
12000
0
    if (offobj == Py_None) {
12001
0
        do {
12002
0
            Py_BEGIN_ALLOW_THREADS
12003
0
            ret = sendfile(out_fd, in_fd, NULL, count);
12004
0
            Py_END_ALLOW_THREADS
12005
0
        } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12006
0
        if (ret < 0)
12007
0
            return (!async_err) ? posix_error() : NULL;
12008
0
        return PyLong_FromSsize_t(ret);
12009
0
    }
12010
0
#endif
12011
0
    off_t offset;
12012
0
    if (!Py_off_t_converter(offobj, &offset))
12013
0
        return NULL;
12014
12015
#if defined(__sun) && defined(__SVR4)
12016
    // On Solaris, sendfile raises EINVAL rather than returning 0
12017
    // when the offset is equal or bigger than the in_fd size.
12018
    struct stat st;
12019
12020
    do {
12021
        Py_BEGIN_ALLOW_THREADS
12022
        ret = fstat(in_fd, &st);
12023
        Py_END_ALLOW_THREADS
12024
    } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12025
    if (ret < 0)
12026
        return (!async_err) ? posix_error() : NULL;
12027
12028
    if (offset >= st.st_size) {
12029
        return PyLong_FromLong(0);
12030
    }
12031
12032
    // On illumos specifically sendfile() may perform a partial write but
12033
    // return -1/an error (in one confirmed case the destination socket
12034
    // had a 5 second timeout set and errno was EAGAIN) and it's on the client
12035
    // code to check if the offset parameter was modified by sendfile().
12036
    //
12037
    // We need this variable to track said change.
12038
    off_t original_offset = offset;
12039
#endif
12040
12041
0
    do {
12042
0
        Py_BEGIN_ALLOW_THREADS
12043
0
        ret = sendfile(out_fd, in_fd, &offset, count);
12044
#if defined(__sun) && defined(__SVR4)
12045
        // This handles illumos-specific sendfile() partial write behavior,
12046
        // see a comment above for more details.
12047
        if (ret < 0 && offset != original_offset) {
12048
            ret = offset - original_offset;
12049
        }
12050
#endif
12051
0
        Py_END_ALLOW_THREADS
12052
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12053
0
    if (ret < 0)
12054
0
        return (!async_err) ? posix_error() : NULL;
12055
0
    return PyLong_FromSsize_t(ret);
12056
0
#endif
12057
0
}
12058
#endif /* HAVE_SENDFILE */
12059
12060
12061
#if defined(__APPLE__)
12062
/*[clinic input]
12063
os._fcopyfile
12064
12065
    in_fd: int
12066
    out_fd: int
12067
    flags: int
12068
    /
12069
12070
Efficiently copy content or metadata of 2 regular file descriptors (macOS).
12071
[clinic start generated code]*/
12072
12073
static PyObject *
12074
os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
12075
/*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
12076
{
12077
    int ret;
12078
12079
    Py_BEGIN_ALLOW_THREADS
12080
    ret = fcopyfile(in_fd, out_fd, NULL, flags);
12081
    Py_END_ALLOW_THREADS
12082
    if (ret < 0)
12083
        return posix_error();
12084
    Py_RETURN_NONE;
12085
}
12086
#endif
12087
12088
12089
/*[clinic input]
12090
os.fstat
12091
12092
    fd : int
12093
12094
Perform a stat system call on the given file descriptor.
12095
12096
Like stat(), but for an open file descriptor.
12097
Equivalent to os.stat(fd).
12098
[clinic start generated code]*/
12099
12100
static PyObject *
12101
os_fstat_impl(PyObject *module, int fd)
12102
/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
12103
0
{
12104
0
    STRUCT_STAT st;
12105
0
    int res;
12106
0
    int async_err = 0;
12107
12108
0
    do {
12109
0
        Py_BEGIN_ALLOW_THREADS
12110
0
        res = FSTAT(fd, &st);
12111
0
        Py_END_ALLOW_THREADS
12112
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12113
0
    if (res != 0) {
12114
#ifdef MS_WINDOWS
12115
        return PyErr_SetFromWindowsErr(0);
12116
#else
12117
0
        return (!async_err) ? posix_error() : NULL;
12118
0
#endif
12119
0
    }
12120
12121
0
    return _pystat_fromstructstat(module, &st);
12122
0
}
12123
12124
12125
/*[clinic input]
12126
os.isatty -> bool
12127
    fd: int
12128
    /
12129
12130
Return True if the fd is connected to a terminal.
12131
12132
Return True if the file descriptor is an open file descriptor
12133
connected to the slave end of a terminal.
12134
[clinic start generated code]*/
12135
12136
static int
12137
os_isatty_impl(PyObject *module, int fd)
12138
/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
12139
0
{
12140
0
    int return_value;
12141
0
    Py_BEGIN_ALLOW_THREADS
12142
0
    _Py_BEGIN_SUPPRESS_IPH
12143
0
    return_value = isatty(fd);
12144
0
    _Py_END_SUPPRESS_IPH
12145
0
    Py_END_ALLOW_THREADS
12146
0
    return return_value;
12147
0
}
12148
12149
12150
#ifdef HAVE_PIPE
12151
/*[clinic input]
12152
os.pipe
12153
12154
Create a pipe.
12155
12156
Returns a tuple of two file descriptors:
12157
  (read_fd, write_fd)
12158
[clinic start generated code]*/
12159
12160
static PyObject *
12161
os_pipe_impl(PyObject *module)
12162
/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
12163
0
{
12164
0
    int fds[2];
12165
#ifdef MS_WINDOWS
12166
    HANDLE read, write;
12167
    SECURITY_ATTRIBUTES attr;
12168
    BOOL ok;
12169
#else
12170
0
    int res;
12171
0
#endif
12172
12173
#ifdef MS_WINDOWS
12174
    attr.nLength = sizeof(attr);
12175
    attr.lpSecurityDescriptor = NULL;
12176
    attr.bInheritHandle = FALSE;
12177
12178
    Py_BEGIN_ALLOW_THREADS
12179
    ok = CreatePipe(&read, &write, &attr, 0);
12180
    if (ok) {
12181
        fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY | _O_NOINHERIT);
12182
        fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY | _O_NOINHERIT);
12183
        if (fds[0] == -1 || fds[1] == -1) {
12184
            CloseHandle(read);
12185
            CloseHandle(write);
12186
            ok = 0;
12187
        }
12188
    }
12189
    Py_END_ALLOW_THREADS
12190
12191
    if (!ok)
12192
        return PyErr_SetFromWindowsErr(0);
12193
#else
12194
12195
0
#ifdef HAVE_PIPE2
12196
0
    Py_BEGIN_ALLOW_THREADS
12197
0
    res = pipe2(fds, O_CLOEXEC);
12198
0
    Py_END_ALLOW_THREADS
12199
12200
0
    if (res != 0 && errno == ENOSYS)
12201
0
    {
12202
0
#endif
12203
0
        Py_BEGIN_ALLOW_THREADS
12204
0
        res = pipe(fds);
12205
0
        Py_END_ALLOW_THREADS
12206
12207
0
        if (res == 0) {
12208
0
            if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
12209
0
                close(fds[0]);
12210
0
                close(fds[1]);
12211
0
                return NULL;
12212
0
            }
12213
0
            if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
12214
0
                close(fds[0]);
12215
0
                close(fds[1]);
12216
0
                return NULL;
12217
0
            }
12218
0
        }
12219
0
#ifdef HAVE_PIPE2
12220
0
    }
12221
0
#endif
12222
12223
0
    if (res != 0)
12224
0
        return PyErr_SetFromErrno(PyExc_OSError);
12225
0
#endif /* !MS_WINDOWS */
12226
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12227
0
}
12228
#endif  /* HAVE_PIPE */
12229
12230
12231
#ifdef HAVE_PIPE2
12232
/*[clinic input]
12233
os.pipe2
12234
12235
    flags: int
12236
    /
12237
12238
Create a pipe with flags set atomically.
12239
12240
Returns a tuple of two file descriptors:
12241
  (read_fd, write_fd)
12242
12243
flags can be constructed by ORing together one or more of these values:
12244
O_NONBLOCK, O_CLOEXEC.
12245
[clinic start generated code]*/
12246
12247
static PyObject *
12248
os_pipe2_impl(PyObject *module, int flags)
12249
/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
12250
0
{
12251
0
    int fds[2];
12252
0
    int res;
12253
12254
0
    res = pipe2(fds, flags);
12255
0
    if (res != 0)
12256
0
        return posix_error();
12257
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12258
0
}
12259
#endif /* HAVE_PIPE2 */
12260
12261
12262
#ifdef HAVE_WRITEV
12263
/*[clinic input]
12264
os.writev -> Py_ssize_t
12265
    fd: int
12266
    buffers: object
12267
    /
12268
12269
Iterate over buffers, and write the contents of each to a file descriptor.
12270
12271
Returns the total number of bytes written.
12272
buffers must be a sequence of bytes-like objects.
12273
[clinic start generated code]*/
12274
12275
static Py_ssize_t
12276
os_writev_impl(PyObject *module, int fd, PyObject *buffers)
12277
/*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
12278
0
{
12279
0
    Py_ssize_t cnt;
12280
0
    Py_ssize_t result;
12281
0
    int async_err = 0;
12282
0
    struct iovec *iov;
12283
0
    Py_buffer *buf;
12284
12285
0
    if (!PySequence_Check(buffers)) {
12286
0
        PyErr_SetString(PyExc_TypeError,
12287
0
            "writev() arg 2 must be a sequence");
12288
0
        return -1;
12289
0
    }
12290
0
    cnt = PySequence_Size(buffers);
12291
0
    if (cnt < 0)
12292
0
        return -1;
12293
12294
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12295
0
        return -1;
12296
0
    }
12297
12298
0
    do {
12299
0
        Py_BEGIN_ALLOW_THREADS
12300
0
        result = writev(fd, iov, cnt);
12301
0
        Py_END_ALLOW_THREADS
12302
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12303
12304
0
    if (result < 0 && !async_err)
12305
0
        posix_error();
12306
12307
0
    iov_cleanup(iov, buf, cnt);
12308
0
    return result;
12309
0
}
12310
#endif /* HAVE_WRITEV */
12311
12312
12313
#ifdef HAVE_PWRITE
12314
/*[clinic input]
12315
os.pwrite -> Py_ssize_t
12316
12317
    fd: int
12318
    buffer: Py_buffer
12319
    offset: Py_off_t
12320
    /
12321
12322
Write bytes to a file descriptor starting at a particular offset.
12323
12324
Write buffer to fd, starting at offset bytes from the beginning of
12325
the file.  Returns the number of bytes written.  Does not change the
12326
current file offset.
12327
[clinic start generated code]*/
12328
12329
static Py_ssize_t
12330
os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
12331
/*[clinic end generated code: output=c74da630758ee925 input=614acbc7e5a0339a]*/
12332
0
{
12333
0
    Py_ssize_t size;
12334
0
    int async_err = 0;
12335
12336
0
    do {
12337
0
        Py_BEGIN_ALLOW_THREADS
12338
0
        _Py_BEGIN_SUPPRESS_IPH
12339
0
        size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
12340
0
        _Py_END_SUPPRESS_IPH
12341
0
        Py_END_ALLOW_THREADS
12342
0
    } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12343
12344
0
    if (size < 0 && !async_err)
12345
0
        posix_error();
12346
0
    return size;
12347
0
}
12348
#endif /* HAVE_PWRITE */
12349
12350
#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12351
/*[clinic input]
12352
os.pwritev -> Py_ssize_t
12353
12354
    fd: int
12355
    buffers: object
12356
    offset: Py_off_t
12357
    flags: int = 0
12358
    /
12359
12360
Writes the contents of bytes-like objects to a file descriptor at a given offset.
12361
12362
Combines the functionality of writev() and pwrite(). All buffers must be a sequence
12363
of bytes-like objects. Buffers are processed in array order. Entire contents of first
12364
buffer is written before proceeding to second, and so on. The operating system may
12365
set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
12366
This function writes the contents of each object to the file descriptor and returns
12367
the total number of bytes written.
12368
12369
The flags argument contains a bitwise OR of zero or more of the following flags:
12370
12371
- RWF_DSYNC
12372
- RWF_SYNC
12373
- RWF_APPEND
12374
12375
Using non-zero flags requires Linux 4.7 or newer.
12376
[clinic start generated code]*/
12377
12378
static Py_ssize_t
12379
os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12380
                int flags)
12381
/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/
12382
0
{
12383
0
    Py_ssize_t cnt;
12384
0
    Py_ssize_t result;
12385
0
    int async_err = 0;
12386
0
    struct iovec *iov;
12387
0
    Py_buffer *buf;
12388
12389
0
    if (!PySequence_Check(buffers)) {
12390
0
        PyErr_SetString(PyExc_TypeError,
12391
0
            "pwritev() arg 2 must be a sequence");
12392
0
        return -1;
12393
0
    }
12394
12395
0
    cnt = PySequence_Size(buffers);
12396
0
    if (cnt < 0) {
12397
0
        return -1;
12398
0
    }
12399
12400
#ifndef HAVE_PWRITEV2
12401
    if(flags != 0) {
12402
        argument_unavailable_error("pwritev2", "flags");
12403
        return -1;
12404
    }
12405
#endif
12406
12407
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12408
0
        return -1;
12409
0
    }
12410
0
#ifdef HAVE_PWRITEV2
12411
0
    do {
12412
0
        Py_BEGIN_ALLOW_THREADS
12413
0
        _Py_BEGIN_SUPPRESS_IPH
12414
0
        result = pwritev2(fd, iov, cnt, offset, flags);
12415
0
        _Py_END_SUPPRESS_IPH
12416
0
        Py_END_ALLOW_THREADS
12417
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12418
#else
12419
12420
#if defined(__APPLE__) && defined(__clang__)
12421
/* This entire function will be removed from the module dict when the API
12422
 * is not available.
12423
 */
12424
#pragma clang diagnostic push
12425
#pragma clang diagnostic ignored "-Wunguarded-availability"
12426
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12427
#endif
12428
    do {
12429
        Py_BEGIN_ALLOW_THREADS
12430
        _Py_BEGIN_SUPPRESS_IPH
12431
        result = pwritev(fd, iov, cnt, offset);
12432
        _Py_END_SUPPRESS_IPH
12433
        Py_END_ALLOW_THREADS
12434
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12435
12436
#if defined(__APPLE__) && defined(__clang__)
12437
#pragma clang diagnostic pop
12438
#endif
12439
12440
#endif
12441
12442
0
    if (result < 0) {
12443
0
        if (!async_err) {
12444
0
            posix_error();
12445
0
        }
12446
0
        result = -1;
12447
0
    }
12448
0
    iov_cleanup(iov, buf, cnt);
12449
12450
0
    return result;
12451
0
}
12452
#endif /* HAVE_PWRITEV */
12453
12454
#ifdef HAVE_COPY_FILE_RANGE
12455
/*[clinic input]
12456
12457
os.copy_file_range
12458
    src: int
12459
        Source file descriptor.
12460
    dst: int
12461
        Destination file descriptor.
12462
    count: Py_ssize_t
12463
        Number of bytes to copy.
12464
    offset_src: object = None
12465
        Starting offset in src.
12466
    offset_dst: object = None
12467
        Starting offset in dst.
12468
12469
Copy count bytes from one file descriptor to another.
12470
12471
If offset_src is None, then src is read from the current position;
12472
respectively for offset_dst.
12473
[clinic start generated code]*/
12474
12475
static PyObject *
12476
os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
12477
                        PyObject *offset_src, PyObject *offset_dst)
12478
/*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
12479
0
{
12480
0
    off_t offset_src_val, offset_dst_val;
12481
0
    off_t *p_offset_src = NULL;
12482
0
    off_t *p_offset_dst = NULL;
12483
0
    Py_ssize_t ret;
12484
0
    int async_err = 0;
12485
    /* The flags argument is provided to allow
12486
     * for future extensions and currently must be to 0. */
12487
0
    int flags = 0;
12488
12489
12490
0
    if (count < 0) {
12491
0
        PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
12492
0
        return NULL;
12493
0
    }
12494
12495
0
    if (offset_src != Py_None) {
12496
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
12497
0
            return NULL;
12498
0
        }
12499
0
        p_offset_src = &offset_src_val;
12500
0
    }
12501
12502
0
    if (offset_dst != Py_None) {
12503
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
12504
0
            return NULL;
12505
0
        }
12506
0
        p_offset_dst = &offset_dst_val;
12507
0
    }
12508
12509
0
    do {
12510
0
        Py_BEGIN_ALLOW_THREADS
12511
0
        ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
12512
0
        Py_END_ALLOW_THREADS
12513
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12514
12515
0
    if (ret < 0) {
12516
0
        return (!async_err) ? posix_error() : NULL;
12517
0
    }
12518
12519
0
    return PyLong_FromSsize_t(ret);
12520
0
}
12521
#endif /* HAVE_COPY_FILE_RANGE*/
12522
12523
#if (defined(HAVE_SPLICE) && !defined(_AIX))
12524
/*[clinic input]
12525
12526
os.splice
12527
    src: int
12528
        Source file descriptor.
12529
    dst: int
12530
        Destination file descriptor.
12531
    count: Py_ssize_t
12532
        Number of bytes to copy.
12533
    offset_src: object = None
12534
        Starting offset in src.
12535
    offset_dst: object = None
12536
        Starting offset in dst.
12537
    flags: unsigned_int = 0
12538
        Flags to modify the semantics of the call.
12539
12540
Transfer count bytes from one pipe to a descriptor or vice versa.
12541
12542
If offset_src is None, then src is read from the current position;
12543
respectively for offset_dst. The offset associated to the file
12544
descriptor that refers to a pipe must be None.
12545
[clinic start generated code]*/
12546
12547
static PyObject *
12548
os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
12549
               PyObject *offset_src, PyObject *offset_dst,
12550
               unsigned int flags)
12551
/*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/
12552
0
{
12553
0
    off_t offset_src_val, offset_dst_val;
12554
0
    off_t *p_offset_src = NULL;
12555
0
    off_t *p_offset_dst = NULL;
12556
0
    Py_ssize_t ret;
12557
0
    int async_err = 0;
12558
12559
0
    if (count < 0) {
12560
0
        PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
12561
0
        return NULL;
12562
0
    }
12563
12564
0
    if (offset_src != Py_None) {
12565
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
12566
0
            return NULL;
12567
0
        }
12568
0
        p_offset_src = &offset_src_val;
12569
0
    }
12570
12571
0
    if (offset_dst != Py_None) {
12572
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
12573
0
            return NULL;
12574
0
        }
12575
0
        p_offset_dst = &offset_dst_val;
12576
0
    }
12577
12578
0
    do {
12579
0
        Py_BEGIN_ALLOW_THREADS
12580
0
        ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
12581
0
        Py_END_ALLOW_THREADS
12582
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12583
12584
0
    if (ret < 0) {
12585
0
        return (!async_err) ? posix_error() : NULL;
12586
0
    }
12587
12588
0
    return PyLong_FromSsize_t(ret);
12589
0
}
12590
#endif /* HAVE_SPLICE*/
12591
12592
#ifdef HAVE_MKFIFO
12593
/*[clinic input]
12594
os.mkfifo
12595
12596
    path: path_t
12597
    mode: int=0o666
12598
    *
12599
    dir_fd: dir_fd(requires='mkfifoat')=None
12600
12601
Create a "fifo" (a POSIX named pipe).
12602
12603
If dir_fd is not None, it should be a file descriptor open to a directory,
12604
  and path should be relative; path will then be relative to that directory.
12605
dir_fd may not be implemented on your platform.
12606
  If it is unavailable, using it will raise a NotImplementedError.
12607
[clinic start generated code]*/
12608
12609
static PyObject *
12610
os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
12611
/*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
12612
0
{
12613
0
    int result;
12614
0
    int async_err = 0;
12615
0
#ifdef HAVE_MKFIFOAT
12616
0
    int mkfifoat_unavailable = 0;
12617
0
#endif
12618
12619
0
    do {
12620
0
        Py_BEGIN_ALLOW_THREADS
12621
0
#ifdef HAVE_MKFIFOAT
12622
0
        if (dir_fd != DEFAULT_DIR_FD) {
12623
0
            if (HAVE_MKFIFOAT_RUNTIME) {
12624
0
                result = mkfifoat(dir_fd, path->narrow, mode);
12625
12626
0
            } else {
12627
0
                mkfifoat_unavailable = 1;
12628
0
                result = 0;
12629
0
            }
12630
0
        } else
12631
0
#endif
12632
0
            result = mkfifo(path->narrow, mode);
12633
0
        Py_END_ALLOW_THREADS
12634
0
    } while (result != 0 && errno == EINTR &&
12635
0
             !(async_err = PyErr_CheckSignals()));
12636
12637
0
#ifdef HAVE_MKFIFOAT
12638
0
    if (mkfifoat_unavailable) {
12639
0
        argument_unavailable_error(NULL, "dir_fd");
12640
0
        return NULL;
12641
0
    }
12642
0
#endif
12643
12644
0
    if (result != 0)
12645
0
        return (!async_err) ? posix_error() : NULL;
12646
12647
0
    Py_RETURN_NONE;
12648
0
}
12649
#endif /* HAVE_MKFIFO */
12650
12651
12652
#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
12653
/*[clinic input]
12654
os.mknod
12655
12656
    path: path_t
12657
    mode: int=0o600
12658
    device: dev_t=0
12659
    *
12660
    dir_fd: dir_fd(requires='mknodat')=None
12661
12662
Create a node in the file system.
12663
12664
Create a node in the file system (file, device special file or named pipe)
12665
at path.  mode specifies both the permissions to use and the
12666
type of node to be created, being combined (bitwise OR) with one of
12667
S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
12668
device defines the newly created device special file (probably using
12669
os.makedev()).  Otherwise device is ignored.
12670
12671
If dir_fd is not None, it should be a file descriptor open to a directory,
12672
  and path should be relative; path will then be relative to that directory.
12673
dir_fd may not be implemented on your platform.
12674
  If it is unavailable, using it will raise a NotImplementedError.
12675
[clinic start generated code]*/
12676
12677
static PyObject *
12678
os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
12679
              int dir_fd)
12680
/*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
12681
0
{
12682
0
    int result;
12683
0
    int async_err = 0;
12684
0
#ifdef HAVE_MKNODAT
12685
0
    int mknodat_unavailable = 0;
12686
0
#endif
12687
12688
0
    do {
12689
0
        Py_BEGIN_ALLOW_THREADS
12690
0
#ifdef HAVE_MKNODAT
12691
0
        if (dir_fd != DEFAULT_DIR_FD) {
12692
0
            if (HAVE_MKNODAT_RUNTIME) {
12693
0
                result = mknodat(dir_fd, path->narrow, mode, device);
12694
12695
0
            } else {
12696
0
                mknodat_unavailable = 1;
12697
0
                result = 0;
12698
0
            }
12699
0
        } else
12700
0
#endif
12701
0
            result = mknod(path->narrow, mode, device);
12702
0
        Py_END_ALLOW_THREADS
12703
0
    } while (result != 0 && errno == EINTR &&
12704
0
             !(async_err = PyErr_CheckSignals()));
12705
0
#ifdef HAVE_MKNODAT
12706
0
    if (mknodat_unavailable) {
12707
0
        argument_unavailable_error(NULL, "dir_fd");
12708
0
        return NULL;
12709
0
    }
12710
0
#endif
12711
0
    if (result != 0)
12712
0
        return (!async_err) ? posix_error() : NULL;
12713
12714
0
    Py_RETURN_NONE;
12715
0
}
12716
#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
12717
12718
12719
#ifdef HAVE_DEVICE_MACROS
12720
static PyObject *
12721
major_minor_conv(unsigned int value)
12722
0
{
12723
0
#ifdef NODEV
12724
0
    if (value == (unsigned int)NODEV) {
12725
0
        return PyLong_FromLong((int)NODEV);
12726
0
    }
12727
0
#endif
12728
0
    return PyLong_FromUnsignedLong(value);
12729
0
}
12730
12731
static int
12732
major_minor_check(dev_t value)
12733
0
{
12734
0
#ifdef NODEV
12735
0
    if (value == NODEV) {
12736
0
        return 1;
12737
0
    }
12738
0
#endif
12739
0
    return (dev_t)(unsigned int)value == value;
12740
0
}
12741
12742
/*[clinic input]
12743
os.major
12744
12745
    device: dev_t
12746
    /
12747
12748
Extracts a device major number from a raw device number.
12749
[clinic start generated code]*/
12750
12751
static PyObject *
12752
os_major_impl(PyObject *module, dev_t device)
12753
/*[clinic end generated code: output=4071ffee17647891 input=b1a0a14ec9448229]*/
12754
0
{
12755
0
    return major_minor_conv(major(device));
12756
0
}
12757
12758
12759
/*[clinic input]
12760
os.minor
12761
12762
    device: dev_t
12763
    /
12764
12765
Extracts a device minor number from a raw device number.
12766
[clinic start generated code]*/
12767
12768
static PyObject *
12769
os_minor_impl(PyObject *module, dev_t device)
12770
/*[clinic end generated code: output=306cb78e3bc5004f input=2f686e463682a9da]*/
12771
0
{
12772
0
    return major_minor_conv(minor(device));
12773
0
}
12774
12775
12776
/*[clinic input]
12777
os.makedev -> dev_t
12778
12779
    major: dev_t
12780
    minor: dev_t
12781
    /
12782
12783
Composes a raw device number from the major and minor device numbers.
12784
[clinic start generated code]*/
12785
12786
static dev_t
12787
os_makedev_impl(PyObject *module, dev_t major, dev_t minor)
12788
/*[clinic end generated code: output=cad6125c51f5af80 input=2146126ec02e55c1]*/
12789
0
{
12790
0
    if (!major_minor_check(major) || !major_minor_check(minor)) {
12791
0
        PyErr_SetString(PyExc_OverflowError,
12792
0
                        "Python int too large to convert to C unsigned int");
12793
0
        return (dev_t)-1;
12794
0
    }
12795
0
    return makedev(major, minor);
12796
0
}
12797
#endif /* HAVE_DEVICE_MACROS */
12798
12799
12800
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
12801
/*[clinic input]
12802
os.ftruncate
12803
12804
    fd: int
12805
    length: Py_off_t
12806
    /
12807
12808
Truncate a file, specified by file descriptor, to a specific length.
12809
[clinic start generated code]*/
12810
12811
static PyObject *
12812
os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
12813
/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
12814
0
{
12815
0
    int result;
12816
0
    int async_err = 0;
12817
12818
0
    if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
12819
0
        return NULL;
12820
0
    }
12821
12822
0
    do {
12823
0
        Py_BEGIN_ALLOW_THREADS
12824
0
        _Py_BEGIN_SUPPRESS_IPH
12825
#ifdef MS_WINDOWS
12826
        result = _chsize_s(fd, length);
12827
#else
12828
0
        result = ftruncate(fd, length);
12829
0
#endif
12830
0
        _Py_END_SUPPRESS_IPH
12831
0
        Py_END_ALLOW_THREADS
12832
0
    } while (result != 0 && errno == EINTR &&
12833
0
             !(async_err = PyErr_CheckSignals()));
12834
0
    if (result != 0)
12835
0
        return (!async_err) ? posix_error() : NULL;
12836
0
    Py_RETURN_NONE;
12837
0
}
12838
#endif /* HAVE_FTRUNCATE || MS_WINDOWS */
12839
12840
12841
#if defined HAVE_TRUNCATE || defined MS_WINDOWS
12842
/*[clinic input]
12843
os.truncate
12844
    path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
12845
    length: Py_off_t
12846
12847
Truncate a file, specified by path, to a specific length.
12848
12849
On some platforms, path may also be specified as an open file descriptor.
12850
  If this functionality is unavailable, using it raises an exception.
12851
[clinic start generated code]*/
12852
12853
static PyObject *
12854
os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
12855
/*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
12856
0
{
12857
0
    int result;
12858
#ifdef MS_WINDOWS
12859
    int fd;
12860
#endif
12861
12862
0
    if (path->fd != -1)
12863
0
        return os_ftruncate_impl(module, path->fd, length);
12864
12865
0
    if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
12866
0
        return NULL;
12867
0
    }
12868
12869
0
    Py_BEGIN_ALLOW_THREADS
12870
0
    _Py_BEGIN_SUPPRESS_IPH
12871
#ifdef MS_WINDOWS
12872
    fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
12873
    if (fd < 0)
12874
        result = -1;
12875
    else {
12876
        result = _chsize_s(fd, length);
12877
        close(fd);
12878
        if (result < 0)
12879
            errno = result;
12880
    }
12881
#else
12882
0
    result = truncate(path->narrow, length);
12883
0
#endif
12884
0
    _Py_END_SUPPRESS_IPH
12885
0
    Py_END_ALLOW_THREADS
12886
0
    if (result < 0)
12887
0
        return posix_path_error(path);
12888
12889
0
    Py_RETURN_NONE;
12890
0
}
12891
#endif /* HAVE_TRUNCATE || MS_WINDOWS */
12892
12893
12894
/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
12895
   and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
12896
   defined, which is the case in Python on AIX. AIX bug report:
12897
   http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
12898
#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
12899
#  define POSIX_FADVISE_AIX_BUG
12900
#endif
12901
12902
12903
/* GH-111804: Due to posix_fallocate() not having consistent semantics across
12904
   OSs, support was dropped in WASI preview2. */
12905
#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) && \
12906
    !defined(__wasi__)
12907
/*[clinic input]
12908
os.posix_fallocate
12909
12910
    fd: int
12911
    offset: Py_off_t
12912
    length: Py_off_t
12913
    /
12914
12915
Ensure a file has allocated at least a particular number of bytes on disk.
12916
12917
Ensure that the file specified by fd encompasses a range of bytes
12918
starting at offset bytes from the beginning and continuing for length bytes.
12919
[clinic start generated code]*/
12920
12921
static PyObject *
12922
os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
12923
                        Py_off_t length)
12924
/*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
12925
0
{
12926
0
    int result;
12927
0
    int async_err = 0;
12928
12929
0
    do {
12930
0
        Py_BEGIN_ALLOW_THREADS
12931
0
        result = posix_fallocate(fd, offset, length);
12932
0
        Py_END_ALLOW_THREADS
12933
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
12934
12935
0
    if (result == 0)
12936
0
        Py_RETURN_NONE;
12937
12938
0
    if (async_err)
12939
0
        return NULL;
12940
12941
0
    errno = result;
12942
0
    return posix_error();
12943
0
}
12944
#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG && !defined(__wasi__) */
12945
12946
12947
#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
12948
/*[clinic input]
12949
os.posix_fadvise
12950
12951
    fd: int
12952
    offset: Py_off_t
12953
    length: Py_off_t
12954
    advice: int
12955
    /
12956
12957
Announce an intention to access data in a specific pattern.
12958
12959
Announce an intention to access data in a specific pattern, thus allowing
12960
the kernel to make optimizations.
12961
The advice applies to the region of the file specified by fd starting at
12962
offset and continuing for length bytes.
12963
advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
12964
POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
12965
POSIX_FADV_DONTNEED.
12966
[clinic start generated code]*/
12967
12968
static PyObject *
12969
os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
12970
                      Py_off_t length, int advice)
12971
/*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
12972
0
{
12973
0
    int result;
12974
0
    int async_err = 0;
12975
12976
0
    do {
12977
0
        Py_BEGIN_ALLOW_THREADS
12978
0
        result = posix_fadvise(fd, offset, length, advice);
12979
0
        Py_END_ALLOW_THREADS
12980
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
12981
12982
0
    if (result == 0)
12983
0
        Py_RETURN_NONE;
12984
12985
0
    if (async_err)
12986
0
        return NULL;
12987
12988
0
    errno = result;
12989
0
    return posix_error();
12990
0
}
12991
#endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
12992
12993
12994
#ifdef MS_WINDOWS
12995
static PyObject*
12996
win32_putenv(PyObject *name, PyObject *value)
12997
{
12998
    /* Search from index 1 because on Windows starting '=' is allowed for
12999
       defining hidden environment variables. */
13000
    if (PyUnicode_GET_LENGTH(name) == 0 ||
13001
        PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
13002
    {
13003
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13004
        return NULL;
13005
    }
13006
    PyObject *unicode;
13007
    if (value != NULL) {
13008
        unicode = PyUnicode_FromFormat("%U=%U", name, value);
13009
    }
13010
    else {
13011
        unicode = PyUnicode_FromFormat("%U=", name);
13012
    }
13013
    if (unicode == NULL) {
13014
        return NULL;
13015
    }
13016
13017
    Py_ssize_t size;
13018
    wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
13019
    Py_DECREF(unicode);
13020
13021
    if (env == NULL) {
13022
        return NULL;
13023
    }
13024
    if (size > _MAX_ENV) {
13025
        PyErr_Format(PyExc_ValueError,
13026
                     "the environment variable is longer than %u characters",
13027
                     _MAX_ENV);
13028
        PyMem_Free(env);
13029
        return NULL;
13030
    }
13031
    if (wcslen(env) != (size_t)size) {
13032
        PyErr_SetString(PyExc_ValueError,
13033
                        "embedded null character");
13034
        PyMem_Free(env);
13035
        return NULL;
13036
    }
13037
13038
    /* _wputenv() and SetEnvironmentVariableW() update the environment in the
13039
       Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
13040
       and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
13041
13042
       Prefer _wputenv() to be compatible with C libraries using CRT
13043
       variables and CRT functions using these variables (ex: getenv()). */
13044
    int err = _wputenv(env);
13045
13046
    if (err) {
13047
        posix_error();
13048
        PyMem_Free(env);
13049
        return NULL;
13050
    }
13051
    PyMem_Free(env);
13052
13053
    Py_RETURN_NONE;
13054
}
13055
#endif
13056
13057
13058
#ifdef MS_WINDOWS
13059
/*[clinic input]
13060
os.putenv
13061
13062
    name: unicode
13063
    value: unicode
13064
    /
13065
13066
Change or add an environment variable.
13067
[clinic start generated code]*/
13068
13069
static PyObject *
13070
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13071
/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
13072
{
13073
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13074
        return NULL;
13075
    }
13076
    return win32_putenv(name, value);
13077
}
13078
#else
13079
/*[clinic input]
13080
os.putenv
13081
13082
    name: FSConverter
13083
    value: FSConverter
13084
    /
13085
13086
Change or add an environment variable.
13087
[clinic start generated code]*/
13088
13089
static PyObject *
13090
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13091
/*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
13092
0
{
13093
0
    const char *name_string = PyBytes_AS_STRING(name);
13094
0
    const char *value_string = PyBytes_AS_STRING(value);
13095
13096
0
    if (strchr(name_string, '=') != NULL) {
13097
0
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13098
0
        return NULL;
13099
0
    }
13100
13101
0
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13102
0
        return NULL;
13103
0
    }
13104
13105
0
    if (setenv(name_string, value_string, 1)) {
13106
0
        return posix_error();
13107
0
    }
13108
0
    Py_RETURN_NONE;
13109
0
}
13110
#endif  /* !defined(MS_WINDOWS) */
13111
13112
13113
#ifdef MS_WINDOWS
13114
/*[clinic input]
13115
os.unsetenv
13116
    name: unicode
13117
    /
13118
13119
Delete an environment variable.
13120
[clinic start generated code]*/
13121
13122
static PyObject *
13123
os_unsetenv_impl(PyObject *module, PyObject *name)
13124
/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
13125
{
13126
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13127
        return NULL;
13128
    }
13129
    return win32_putenv(name, NULL);
13130
}
13131
#else
13132
/*[clinic input]
13133
os.unsetenv
13134
    name: FSConverter
13135
    /
13136
13137
Delete an environment variable.
13138
[clinic start generated code]*/
13139
13140
static PyObject *
13141
os_unsetenv_impl(PyObject *module, PyObject *name)
13142
/*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
13143
0
{
13144
0
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13145
0
        return NULL;
13146
0
    }
13147
#ifdef HAVE_BROKEN_UNSETENV
13148
    unsetenv(PyBytes_AS_STRING(name));
13149
#else
13150
0
    int err = unsetenv(PyBytes_AS_STRING(name));
13151
0
    if (err) {
13152
0
        return posix_error();
13153
0
    }
13154
0
#endif
13155
13156
0
    Py_RETURN_NONE;
13157
0
}
13158
#endif /* !MS_WINDOWS */
13159
13160
13161
/*[clinic input]
13162
os.strerror
13163
13164
    code: int
13165
    /
13166
13167
Translate an error code to a message string.
13168
[clinic start generated code]*/
13169
13170
static PyObject *
13171
os_strerror_impl(PyObject *module, int code)
13172
/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
13173
0
{
13174
0
    char *message = strerror(code);
13175
0
    if (message == NULL) {
13176
0
        PyErr_SetString(PyExc_ValueError,
13177
0
                        "strerror() argument out of range");
13178
0
        return NULL;
13179
0
    }
13180
0
    return PyUnicode_DecodeLocale(message, "surrogateescape");
13181
0
}
13182
13183
13184
#ifdef HAVE_SYS_WAIT_H
13185
#ifdef WCOREDUMP
13186
/*[clinic input]
13187
os.WCOREDUMP -> bool
13188
13189
    status: int
13190
    /
13191
13192
Return True if the process returning status was dumped to a core file.
13193
[clinic start generated code]*/
13194
13195
static int
13196
os_WCOREDUMP_impl(PyObject *module, int status)
13197
/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
13198
0
{
13199
0
    WAIT_TYPE wait_status;
13200
0
    WAIT_STATUS_INT(wait_status) = status;
13201
0
    return WCOREDUMP(wait_status);
13202
0
}
13203
#endif /* WCOREDUMP */
13204
13205
13206
#ifdef WIFCONTINUED
13207
/*[clinic input]
13208
os.WIFCONTINUED -> bool
13209
13210
    status: int
13211
13212
Return True if a particular process was continued from a job control stop.
13213
13214
Return True if the process returning status was continued from a
13215
job control stop.
13216
[clinic start generated code]*/
13217
13218
static int
13219
os_WIFCONTINUED_impl(PyObject *module, int status)
13220
/*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
13221
0
{
13222
0
    WAIT_TYPE wait_status;
13223
0
    WAIT_STATUS_INT(wait_status) = status;
13224
0
    return WIFCONTINUED(wait_status);
13225
0
}
13226
#endif /* WIFCONTINUED */
13227
13228
13229
#ifdef WIFSTOPPED
13230
/*[clinic input]
13231
os.WIFSTOPPED -> bool
13232
13233
    status: int
13234
13235
Return True if the process returning status was stopped.
13236
[clinic start generated code]*/
13237
13238
static int
13239
os_WIFSTOPPED_impl(PyObject *module, int status)
13240
/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
13241
0
{
13242
0
    WAIT_TYPE wait_status;
13243
0
    WAIT_STATUS_INT(wait_status) = status;
13244
0
    return WIFSTOPPED(wait_status);
13245
0
}
13246
#endif /* WIFSTOPPED */
13247
13248
13249
#ifdef WIFSIGNALED
13250
/*[clinic input]
13251
os.WIFSIGNALED -> bool
13252
13253
    status: int
13254
13255
Return True if the process returning status was terminated by a signal.
13256
[clinic start generated code]*/
13257
13258
static int
13259
os_WIFSIGNALED_impl(PyObject *module, int status)
13260
/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
13261
0
{
13262
0
    WAIT_TYPE wait_status;
13263
0
    WAIT_STATUS_INT(wait_status) = status;
13264
0
    return WIFSIGNALED(wait_status);
13265
0
}
13266
#endif /* WIFSIGNALED */
13267
13268
13269
#ifdef WIFEXITED
13270
/*[clinic input]
13271
os.WIFEXITED -> bool
13272
13273
    status: int
13274
13275
Return True if the process returning status exited via the exit() system call.
13276
[clinic start generated code]*/
13277
13278
static int
13279
os_WIFEXITED_impl(PyObject *module, int status)
13280
/*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
13281
0
{
13282
0
    WAIT_TYPE wait_status;
13283
0
    WAIT_STATUS_INT(wait_status) = status;
13284
0
    return WIFEXITED(wait_status);
13285
0
}
13286
#endif /* WIFEXITED */
13287
13288
13289
#ifdef WEXITSTATUS
13290
/*[clinic input]
13291
os.WEXITSTATUS -> int
13292
13293
    status: int
13294
13295
Return the process return code from status.
13296
[clinic start generated code]*/
13297
13298
static int
13299
os_WEXITSTATUS_impl(PyObject *module, int status)
13300
/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
13301
0
{
13302
0
    WAIT_TYPE wait_status;
13303
0
    WAIT_STATUS_INT(wait_status) = status;
13304
0
    return WEXITSTATUS(wait_status);
13305
0
}
13306
#endif /* WEXITSTATUS */
13307
13308
13309
#ifdef WTERMSIG
13310
/*[clinic input]
13311
os.WTERMSIG -> int
13312
13313
    status: int
13314
13315
Return the signal that terminated the process that provided the status value.
13316
[clinic start generated code]*/
13317
13318
static int
13319
os_WTERMSIG_impl(PyObject *module, int status)
13320
/*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
13321
0
{
13322
0
    WAIT_TYPE wait_status;
13323
0
    WAIT_STATUS_INT(wait_status) = status;
13324
0
    return WTERMSIG(wait_status);
13325
0
}
13326
#endif /* WTERMSIG */
13327
13328
13329
#ifdef WSTOPSIG
13330
/*[clinic input]
13331
os.WSTOPSIG -> int
13332
13333
    status: int
13334
13335
Return the signal that stopped the process that provided the status value.
13336
[clinic start generated code]*/
13337
13338
static int
13339
os_WSTOPSIG_impl(PyObject *module, int status)
13340
/*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
13341
0
{
13342
0
    WAIT_TYPE wait_status;
13343
0
    WAIT_STATUS_INT(wait_status) = status;
13344
0
    return WSTOPSIG(wait_status);
13345
0
}
13346
#endif /* WSTOPSIG */
13347
#endif /* HAVE_SYS_WAIT_H */
13348
13349
13350
#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
13351
#ifdef _SCO_DS
13352
/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
13353
   needed definitions in sys/statvfs.h */
13354
#define _SVID3
13355
#endif
13356
#include <sys/statvfs.h>
13357
13358
#ifdef __APPLE__
13359
/* On macOS struct statvfs uses 32-bit integers for block counts,
13360
 * resulting in overflow when filesystems are larger than 4TB. Therefore
13361
 * os.statvfs is implemented in terms of statfs(2).
13362
 */
13363
13364
static PyObject*
13365
_pystatvfs_fromstructstatfs(PyObject *module, struct statfs st) {
13366
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13367
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13368
    if (v == NULL) {
13369
        return NULL;
13370
    }
13371
13372
    long flags = 0;
13373
    if (st.f_flags & MNT_RDONLY) {
13374
        flags |= ST_RDONLY;
13375
    }
13376
    if (st.f_flags & MNT_NOSUID) {
13377
        flags |= ST_NOSUID;
13378
    }
13379
13380
    _Static_assert(sizeof(st.f_blocks) == sizeof(long long), "assuming large file");
13381
13382
#define SET_ITEM(SEQ, INDEX, EXPR)                       \
13383
    do {                                                 \
13384
        PyObject *obj = (EXPR);                          \
13385
        if (obj == NULL) {                               \
13386
            Py_DECREF((SEQ));                            \
13387
            return NULL;                                 \
13388
        }                                                \
13389
        PyStructSequence_SET_ITEM((SEQ), (INDEX), obj);  \
13390
    } while (0)
13391
13392
    SET_ITEM(v, 0, PyLong_FromLong((long) st.f_iosize));
13393
    SET_ITEM(v, 1, PyLong_FromLong((long) st.f_bsize));
13394
    SET_ITEM(v, 2, PyLong_FromLongLong((long long) st.f_blocks));
13395
    SET_ITEM(v, 3, PyLong_FromLongLong((long long) st.f_bfree));
13396
    SET_ITEM(v, 4, PyLong_FromLongLong((long long) st.f_bavail));
13397
    SET_ITEM(v, 5, PyLong_FromLongLong((long long) st.f_files));
13398
    SET_ITEM(v, 6, PyLong_FromLongLong((long long) st.f_ffree));
13399
    SET_ITEM(v, 7, PyLong_FromLongLong((long long) st.f_ffree));
13400
    SET_ITEM(v, 8, PyLong_FromLong((long) flags));
13401
13402
    SET_ITEM(v, 9, PyLong_FromLong((long) NAME_MAX));
13403
    SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13404
13405
#undef SET_ITEM
13406
13407
    return v;
13408
}
13409
13410
#else
13411
13412
13413
13414
static PyObject*
13415
0
_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
13416
0
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13417
0
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13418
0
    if (v == NULL)
13419
0
        return NULL;
13420
13421
0
    int pos = 0;
13422
13423
0
#define SET_RESULT(CALL)                                     \
13424
0
    do {                                                     \
13425
0
        PyObject *item = (CALL);                             \
13426
0
        if (item == NULL) {                                  \
13427
0
            Py_DECREF(v);                                    \
13428
0
            return NULL;                                     \
13429
0
        }                                                    \
13430
0
        PyStructSequence_SET_ITEM(v, pos++, item);           \
13431
0
    } while(0)
13432
13433
0
#if !defined(HAVE_LARGEFILE_SUPPORT)
13434
0
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13435
0
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13436
0
    SET_RESULT(PyLong_FromLong((long) st.f_blocks));
13437
0
    SET_RESULT(PyLong_FromLong((long) st.f_bfree));
13438
0
    SET_RESULT(PyLong_FromLong((long) st.f_bavail));
13439
0
    SET_RESULT(PyLong_FromLong((long) st.f_files));
13440
0
    SET_RESULT(PyLong_FromLong((long) st.f_ffree));
13441
0
    SET_RESULT(PyLong_FromLong((long) st.f_favail));
13442
0
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13443
0
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13444
#else
13445
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13446
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13447
    SET_RESULT(PyLong_FromLongLong((long long) st.f_blocks));
13448
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bfree));
13449
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bavail));
13450
    SET_RESULT(PyLong_FromLongLong((long long) st.f_files));
13451
    SET_RESULT(PyLong_FromLongLong((long long) st.f_ffree));
13452
    SET_RESULT(PyLong_FromLongLong((long long) st.f_favail));
13453
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13454
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13455
#endif
13456
/* The _ALL_SOURCE feature test macro defines f_fsid as a structure
13457
 * (issue #32390). */
13458
#if defined(_AIX) && defined(_ALL_SOURCE)
13459
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13460
#else
13461
0
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid));
13462
0
#endif
13463
13464
0
#undef SET_RESULT
13465
13466
0
    return v;
13467
0
}
13468
13469
#endif
13470
13471
13472
/*[clinic input]
13473
os.fstatvfs
13474
    fd: int
13475
    /
13476
13477
Perform an fstatvfs system call on the given fd.
13478
13479
Equivalent to statvfs(fd).
13480
[clinic start generated code]*/
13481
13482
static PyObject *
13483
os_fstatvfs_impl(PyObject *module, int fd)
13484
/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
13485
0
{
13486
0
    int result;
13487
0
    int async_err = 0;
13488
#ifdef __APPLE__
13489
    struct statfs st;
13490
    /* On macOS os.fstatvfs is implemented using fstatfs(2) because
13491
     * the former uses 32-bit values for block counts.
13492
     */
13493
    do {
13494
        Py_BEGIN_ALLOW_THREADS
13495
        result = fstatfs(fd, &st);
13496
        Py_END_ALLOW_THREADS
13497
    } while (result != 0 && errno == EINTR &&
13498
             !(async_err = PyErr_CheckSignals()));
13499
    if (result != 0)
13500
        return (!async_err) ? posix_error() : NULL;
13501
13502
    return _pystatvfs_fromstructstatfs(module, st);
13503
#else
13504
0
    struct statvfs st;
13505
13506
0
    do {
13507
0
        Py_BEGIN_ALLOW_THREADS
13508
0
        result = fstatvfs(fd, &st);
13509
0
        Py_END_ALLOW_THREADS
13510
0
    } while (result != 0 && errno == EINTR &&
13511
0
             !(async_err = PyErr_CheckSignals()));
13512
0
    if (result != 0)
13513
0
        return (!async_err) ? posix_error() : NULL;
13514
13515
0
    return _pystatvfs_fromstructstatvfs(module, st);
13516
0
#endif
13517
0
}
13518
#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
13519
13520
13521
#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
13522
#include <sys/statvfs.h>
13523
/*[clinic input]
13524
os.statvfs
13525
13526
    path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
13527
13528
Perform a statvfs system call on the given path.
13529
13530
path may always be specified as a string.
13531
On some platforms, path may also be specified as an open file descriptor.
13532
  If this functionality is unavailable, using it raises an exception.
13533
[clinic start generated code]*/
13534
13535
static PyObject *
13536
os_statvfs_impl(PyObject *module, path_t *path)
13537
/*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
13538
0
{
13539
0
    int result;
13540
13541
#ifdef __APPLE__
13542
    /* On macOS os.statvfs is implemented using statfs(2)/fstatfs(2) because
13543
     * the former uses 32-bit values for block counts.
13544
     */
13545
    struct statfs st;
13546
13547
    Py_BEGIN_ALLOW_THREADS
13548
    if (path->fd != -1) {
13549
        result = fstatfs(path->fd, &st);
13550
    }
13551
    else
13552
        result = statfs(path->narrow, &st);
13553
    Py_END_ALLOW_THREADS
13554
13555
    if (result) {
13556
        return path_error(path);
13557
    }
13558
13559
    return _pystatvfs_fromstructstatfs(module, st);
13560
13561
#else
13562
0
    struct statvfs st;
13563
13564
0
    Py_BEGIN_ALLOW_THREADS
13565
0
#ifdef HAVE_FSTATVFS
13566
0
    if (path->fd != -1) {
13567
0
        result = fstatvfs(path->fd, &st);
13568
0
    }
13569
0
    else
13570
0
#endif
13571
0
        result = statvfs(path->narrow, &st);
13572
0
    Py_END_ALLOW_THREADS
13573
13574
0
    if (result) {
13575
0
        return path_error(path);
13576
0
    }
13577
13578
0
    return _pystatvfs_fromstructstatvfs(module, st);
13579
0
#endif
13580
0
}
13581
#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
13582
13583
13584
#ifdef MS_WINDOWS
13585
/*[clinic input]
13586
os._getdiskusage
13587
13588
    path: path_t
13589
13590
Return disk usage statistics about the given path as a (total, free) tuple.
13591
[clinic start generated code]*/
13592
13593
static PyObject *
13594
os__getdiskusage_impl(PyObject *module, path_t *path)
13595
/*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
13596
{
13597
    BOOL retval;
13598
    ULARGE_INTEGER _, total, free;
13599
    DWORD err = 0;
13600
13601
    Py_BEGIN_ALLOW_THREADS
13602
    retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
13603
    Py_END_ALLOW_THREADS
13604
    if (retval == 0) {
13605
        if (GetLastError() == ERROR_DIRECTORY) {
13606
            wchar_t *dir_path = NULL;
13607
13608
            dir_path = PyMem_New(wchar_t, path->length + 1);
13609
            if (dir_path == NULL) {
13610
                return PyErr_NoMemory();
13611
            }
13612
13613
            wcscpy_s(dir_path, path->length + 1, path->wide);
13614
13615
            if (_dirnameW(dir_path) != -1) {
13616
                Py_BEGIN_ALLOW_THREADS
13617
                retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
13618
                Py_END_ALLOW_THREADS
13619
            }
13620
            /* Record the last error in case it's modified by PyMem_Free. */
13621
            err = GetLastError();
13622
            PyMem_Free(dir_path);
13623
            if (retval) {
13624
                goto success;
13625
            }
13626
        }
13627
        return PyErr_SetFromWindowsErr(err);
13628
    }
13629
13630
success:
13631
    return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
13632
}
13633
#endif /* MS_WINDOWS */
13634
13635
13636
/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
13637
 * It maps strings representing configuration variable names to
13638
 * integer values, allowing those functions to be called with the
13639
 * magic names instead of polluting the module's namespace with tons of
13640
 * rarely-used constants.  There are three separate tables that use
13641
 * these definitions.
13642
 *
13643
 * This code is always included, even if none of the interfaces that
13644
 * need it are included.  The #if hackery needed to avoid it would be
13645
 * sufficiently pervasive that it's not worth the loss of readability.
13646
 */
13647
struct constdef {
13648
    const char *name;
13649
    int value;
13650
};
13651
13652
static int
13653
conv_confname(PyObject *module, PyObject *arg, int *valuep, const char *tablename)
13654
0
{
13655
0
    if (PyUnicode_Check(arg)) {
13656
0
        PyObject *table = PyObject_GetAttrString(module, tablename);
13657
0
        if (table == NULL) {
13658
0
            return 0;
13659
0
        }
13660
13661
0
        arg = PyObject_GetItem(table, arg);
13662
0
        Py_DECREF(table);
13663
0
        if (arg == NULL) {
13664
0
            PyErr_SetString(
13665
0
                PyExc_ValueError, "unrecognized configuration name");
13666
0
            return 0;
13667
0
        }
13668
0
    } else {
13669
0
        Py_INCREF(arg);  // Match the Py_DECREF below.
13670
0
    }
13671
13672
0
    int success = 0;
13673
0
    if (!PyIndex_Check(arg)) {
13674
0
        PyErr_SetString(PyExc_TypeError,
13675
0
            "configuration names must be strings or integers");
13676
0
    } else {
13677
0
        int value = PyLong_AsInt(arg);
13678
0
        if (!(value == -1 && PyErr_Occurred())) {
13679
0
            *valuep = value;
13680
0
            success = 1;
13681
0
        }
13682
0
    }
13683
0
    Py_DECREF(arg);
13684
0
    return success;
13685
0
}
13686
13687
13688
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
13689
static struct constdef  posix_constants_pathconf[] = {
13690
#ifdef _PC_ABI_AIO_XFER_MAX
13691
    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
13692
#endif
13693
#ifdef _PC_ABI_ASYNC_IO
13694
    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
13695
#endif
13696
#ifdef _PC_ASYNC_IO
13697
    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
13698
#endif
13699
#ifdef _PC_CHOWN_RESTRICTED
13700
    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
13701
#endif
13702
#ifdef _PC_FILESIZEBITS
13703
    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
13704
#endif
13705
#ifdef _PC_LAST
13706
    {"PC_LAST", _PC_LAST},
13707
#endif
13708
#ifdef _PC_LINK_MAX
13709
    {"PC_LINK_MAX",     _PC_LINK_MAX},
13710
#endif
13711
#ifdef _PC_MAX_CANON
13712
    {"PC_MAX_CANON",    _PC_MAX_CANON},
13713
#endif
13714
#ifdef _PC_MAX_INPUT
13715
    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
13716
#endif
13717
#ifdef _PC_NAME_MAX
13718
    {"PC_NAME_MAX",     _PC_NAME_MAX},
13719
#endif
13720
#ifdef _PC_NO_TRUNC
13721
    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
13722
#endif
13723
#ifdef _PC_PATH_MAX
13724
    {"PC_PATH_MAX",     _PC_PATH_MAX},
13725
#endif
13726
#ifdef _PC_PIPE_BUF
13727
    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
13728
#endif
13729
#ifdef _PC_PRIO_IO
13730
    {"PC_PRIO_IO",      _PC_PRIO_IO},
13731
#endif
13732
#ifdef _PC_SOCK_MAXBUF
13733
    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
13734
#endif
13735
#ifdef _PC_SYNC_IO
13736
    {"PC_SYNC_IO",      _PC_SYNC_IO},
13737
#endif
13738
#ifdef _PC_VDISABLE
13739
    {"PC_VDISABLE",     _PC_VDISABLE},
13740
#endif
13741
#ifdef _PC_ACL_ENABLED
13742
    {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
13743
#endif
13744
#ifdef _PC_MIN_HOLE_SIZE
13745
    {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
13746
#endif
13747
#ifdef _PC_ALLOC_SIZE_MIN
13748
    {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
13749
#endif
13750
#ifdef _PC_REC_INCR_XFER_SIZE
13751
    {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
13752
#endif
13753
#ifdef _PC_REC_MAX_XFER_SIZE
13754
    {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
13755
#endif
13756
#ifdef _PC_REC_MIN_XFER_SIZE
13757
    {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
13758
#endif
13759
#ifdef _PC_REC_XFER_ALIGN
13760
    {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
13761
#endif
13762
#ifdef _PC_SYMLINK_MAX
13763
    {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
13764
#endif
13765
#ifdef _PC_XATTR_ENABLED
13766
    {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
13767
#endif
13768
#ifdef _PC_XATTR_EXISTS
13769
    {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
13770
#endif
13771
#ifdef _PC_TIMESTAMP_RESOLUTION
13772
    {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
13773
#endif
13774
};
13775
#endif
13776
13777
13778
#ifdef HAVE_FPATHCONF
13779
/*[clinic input]
13780
os.fpathconf -> long
13781
13782
    fd: fildes
13783
    name: confname(table="pathconf_names")
13784
    /
13785
13786
Return the configuration limit name for the file descriptor fd.
13787
13788
If there is no limit, return -1.
13789
[clinic start generated code]*/
13790
13791
static long
13792
os_fpathconf_impl(PyObject *module, int fd, int name)
13793
/*[clinic end generated code: output=d5b7042425fc3e21 input=023d44589c9ed6aa]*/
13794
0
{
13795
0
    long limit;
13796
13797
0
    errno = 0;
13798
0
    limit = fpathconf(fd, name);
13799
0
    if (limit == -1 && errno != 0)
13800
0
        posix_error();
13801
13802
0
    return limit;
13803
0
}
13804
#endif /* HAVE_FPATHCONF */
13805
13806
13807
#ifdef HAVE_PATHCONF
13808
/*[clinic input]
13809
os.pathconf -> long
13810
    path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
13811
    name: confname(table="pathconf_names")
13812
13813
Return the configuration limit name for the file or directory path.
13814
13815
If there is no limit, return -1.
13816
On some platforms, path may also be specified as an open file descriptor.
13817
  If this functionality is unavailable, using it raises an exception.
13818
[clinic start generated code]*/
13819
13820
static long
13821
os_pathconf_impl(PyObject *module, path_t *path, int name)
13822
/*[clinic end generated code: output=5bedee35b293a089 input=6f6072f57b10c787]*/
13823
0
{
13824
0
    long limit;
13825
13826
0
    errno = 0;
13827
0
#ifdef HAVE_FPATHCONF
13828
0
    if (path->fd != -1)
13829
0
        limit = fpathconf(path->fd, name);
13830
0
    else
13831
0
#endif
13832
0
        limit = pathconf(path->narrow, name);
13833
0
    if (limit == -1 && errno != 0) {
13834
0
        if (errno == EINVAL)
13835
            /* could be a path or name problem */
13836
0
            posix_error();
13837
0
        else
13838
0
            path_error(path);
13839
0
    }
13840
13841
0
    return limit;
13842
0
}
13843
#endif /* HAVE_PATHCONF */
13844
13845
#ifdef HAVE_CONFSTR
13846
static struct constdef posix_constants_confstr[] = {
13847
#ifdef _CS_ARCHITECTURE
13848
    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
13849
#endif
13850
#ifdef _CS_GNU_LIBC_VERSION
13851
    {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
13852
#endif
13853
#ifdef _CS_GNU_LIBPTHREAD_VERSION
13854
    {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
13855
#endif
13856
#ifdef _CS_HOSTNAME
13857
    {"CS_HOSTNAME",     _CS_HOSTNAME},
13858
#endif
13859
#ifdef _CS_HW_PROVIDER
13860
    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
13861
#endif
13862
#ifdef _CS_HW_SERIAL
13863
    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
13864
#endif
13865
#ifdef _CS_INITTAB_NAME
13866
    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
13867
#endif
13868
#ifdef _CS_LFS64_CFLAGS
13869
    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
13870
#endif
13871
#ifdef _CS_LFS64_LDFLAGS
13872
    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
13873
#endif
13874
#ifdef _CS_LFS64_LIBS
13875
    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
13876
#endif
13877
#ifdef _CS_LFS64_LINTFLAGS
13878
    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
13879
#endif
13880
#ifdef _CS_LFS_CFLAGS
13881
    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
13882
#endif
13883
#ifdef _CS_LFS_LDFLAGS
13884
    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
13885
#endif
13886
#ifdef _CS_LFS_LIBS
13887
    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
13888
#endif
13889
#ifdef _CS_LFS_LINTFLAGS
13890
    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
13891
#endif
13892
#ifdef _CS_MACHINE
13893
    {"CS_MACHINE",      _CS_MACHINE},
13894
#endif
13895
#ifdef _CS_PATH
13896
    {"CS_PATH", _CS_PATH},
13897
#endif
13898
#ifdef _CS_RELEASE
13899
    {"CS_RELEASE",      _CS_RELEASE},
13900
#endif
13901
#ifdef _CS_SRPC_DOMAIN
13902
    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
13903
#endif
13904
#ifdef _CS_SYSNAME
13905
    {"CS_SYSNAME",      _CS_SYSNAME},
13906
#endif
13907
#ifdef _CS_VERSION
13908
    {"CS_VERSION",      _CS_VERSION},
13909
#endif
13910
#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
13911
    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
13912
#endif
13913
#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
13914
    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
13915
#endif
13916
#ifdef _CS_XBS5_ILP32_OFF32_LIBS
13917
    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
13918
#endif
13919
#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
13920
    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
13921
#endif
13922
#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
13923
    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
13924
#endif
13925
#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
13926
    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
13927
#endif
13928
#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
13929
    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
13930
#endif
13931
#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
13932
    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
13933
#endif
13934
#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
13935
    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
13936
#endif
13937
#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
13938
    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
13939
#endif
13940
#ifdef _CS_XBS5_LP64_OFF64_LIBS
13941
    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
13942
#endif
13943
#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
13944
    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
13945
#endif
13946
#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
13947
    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
13948
#endif
13949
#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
13950
    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
13951
#endif
13952
#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
13953
    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
13954
#endif
13955
#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
13956
    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
13957
#endif
13958
#ifdef _MIPS_CS_AVAIL_PROCESSORS
13959
    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
13960
#endif
13961
#ifdef _MIPS_CS_BASE
13962
    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
13963
#endif
13964
#ifdef _MIPS_CS_HOSTID
13965
    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
13966
#endif
13967
#ifdef _MIPS_CS_HW_NAME
13968
    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
13969
#endif
13970
#ifdef _MIPS_CS_NUM_PROCESSORS
13971
    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
13972
#endif
13973
#ifdef _MIPS_CS_OSREL_MAJ
13974
    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
13975
#endif
13976
#ifdef _MIPS_CS_OSREL_MIN
13977
    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
13978
#endif
13979
#ifdef _MIPS_CS_OSREL_PATCH
13980
    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
13981
#endif
13982
#ifdef _MIPS_CS_OS_NAME
13983
    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
13984
#endif
13985
#ifdef _MIPS_CS_OS_PROVIDER
13986
    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
13987
#endif
13988
#ifdef _MIPS_CS_PROCESSORS
13989
    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
13990
#endif
13991
#ifdef _MIPS_CS_SERIAL
13992
    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
13993
#endif
13994
#ifdef _MIPS_CS_VENDOR
13995
    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
13996
#endif
13997
};
13998
13999
14000
/*[clinic input]
14001
os.confstr
14002
14003
    name: confname(table="confstr_names")
14004
    /
14005
14006
Return a string-valued system configuration variable.
14007
[clinic start generated code]*/
14008
14009
static PyObject *
14010
os_confstr_impl(PyObject *module, int name)
14011
/*[clinic end generated code: output=bfb0b1b1e49b9383 input=4c6ffca2837ec959]*/
14012
0
{
14013
0
    PyObject *result = NULL;
14014
0
    char buffer[255];
14015
0
    size_t len;
14016
14017
0
    errno = 0;
14018
0
    len = confstr(name, buffer, sizeof(buffer));
14019
0
    if (len == 0) {
14020
0
        if (errno) {
14021
0
            posix_error();
14022
0
            return NULL;
14023
0
        }
14024
0
        else {
14025
0
            Py_RETURN_NONE;
14026
0
        }
14027
0
    }
14028
14029
0
    if (len >= sizeof(buffer)) {
14030
0
        size_t len2;
14031
0
        char *buf = PyMem_Malloc(len);
14032
0
        if (buf == NULL)
14033
0
            return PyErr_NoMemory();
14034
0
        len2 = confstr(name, buf, len);
14035
0
        assert(len == len2);
14036
0
        result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
14037
0
        PyMem_Free(buf);
14038
0
    }
14039
0
    else
14040
0
        result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
14041
0
    return result;
14042
0
}
14043
#endif /* HAVE_CONFSTR */
14044
14045
14046
#ifdef HAVE_SYSCONF
14047
static struct constdef posix_constants_sysconf[] = {
14048
#ifdef _SC_2_CHAR_TERM
14049
    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
14050
#endif
14051
#ifdef _SC_2_C_BIND
14052
    {"SC_2_C_BIND",     _SC_2_C_BIND},
14053
#endif
14054
#ifdef _SC_2_C_DEV
14055
    {"SC_2_C_DEV",      _SC_2_C_DEV},
14056
#endif
14057
#ifdef _SC_2_C_VERSION
14058
    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
14059
#endif
14060
#ifdef _SC_2_FORT_DEV
14061
    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
14062
#endif
14063
#ifdef _SC_2_FORT_RUN
14064
    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
14065
#endif
14066
#ifdef _SC_2_LOCALEDEF
14067
    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
14068
#endif
14069
#ifdef _SC_2_SW_DEV
14070
    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
14071
#endif
14072
#ifdef _SC_2_UPE
14073
    {"SC_2_UPE",        _SC_2_UPE},
14074
#endif
14075
#ifdef _SC_2_VERSION
14076
    {"SC_2_VERSION",    _SC_2_VERSION},
14077
#endif
14078
#ifdef _SC_ABI_ASYNCHRONOUS_IO
14079
    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
14080
#endif
14081
#ifdef _SC_ACL
14082
    {"SC_ACL",  _SC_ACL},
14083
#endif
14084
#ifdef _SC_AIO_LISTIO_MAX
14085
    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
14086
#endif
14087
#ifdef _SC_AIO_MAX
14088
    {"SC_AIO_MAX",      _SC_AIO_MAX},
14089
#endif
14090
#ifdef _SC_AIO_PRIO_DELTA_MAX
14091
    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
14092
#endif
14093
#ifdef _SC_ARG_MAX
14094
    {"SC_ARG_MAX",      _SC_ARG_MAX},
14095
#endif
14096
#ifdef _SC_ASYNCHRONOUS_IO
14097
    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
14098
#endif
14099
#ifdef _SC_ATEXIT_MAX
14100
    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
14101
#endif
14102
#ifdef _SC_AUDIT
14103
    {"SC_AUDIT",        _SC_AUDIT},
14104
#endif
14105
#ifdef _SC_AVPHYS_PAGES
14106
    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
14107
#endif
14108
#ifdef _SC_BC_BASE_MAX
14109
    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
14110
#endif
14111
#ifdef _SC_BC_DIM_MAX
14112
    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
14113
#endif
14114
#ifdef _SC_BC_SCALE_MAX
14115
    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
14116
#endif
14117
#ifdef _SC_BC_STRING_MAX
14118
    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
14119
#endif
14120
#ifdef _SC_CAP
14121
    {"SC_CAP",  _SC_CAP},
14122
#endif
14123
#ifdef _SC_CHARCLASS_NAME_MAX
14124
    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
14125
#endif
14126
#ifdef _SC_CHAR_BIT
14127
    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
14128
#endif
14129
#ifdef _SC_CHAR_MAX
14130
    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
14131
#endif
14132
#ifdef _SC_CHAR_MIN
14133
    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
14134
#endif
14135
#ifdef _SC_CHILD_MAX
14136
    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
14137
#endif
14138
#ifdef _SC_CLK_TCK
14139
    {"SC_CLK_TCK",      _SC_CLK_TCK},
14140
#endif
14141
#ifdef _SC_COHER_BLKSZ
14142
    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
14143
#endif
14144
#ifdef _SC_COLL_WEIGHTS_MAX
14145
    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
14146
#endif
14147
#ifdef _SC_DCACHE_ASSOC
14148
    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
14149
#endif
14150
#ifdef _SC_DCACHE_BLKSZ
14151
    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
14152
#endif
14153
#ifdef _SC_DCACHE_LINESZ
14154
    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
14155
#endif
14156
#ifdef _SC_DCACHE_SZ
14157
    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
14158
#endif
14159
#ifdef _SC_DCACHE_TBLKSZ
14160
    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
14161
#endif
14162
#ifdef _SC_DELAYTIMER_MAX
14163
    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
14164
#endif
14165
#ifdef _SC_EQUIV_CLASS_MAX
14166
    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
14167
#endif
14168
#ifdef _SC_EXPR_NEST_MAX
14169
    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
14170
#endif
14171
#ifdef _SC_FSYNC
14172
    {"SC_FSYNC",        _SC_FSYNC},
14173
#endif
14174
#ifdef _SC_GETGR_R_SIZE_MAX
14175
    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
14176
#endif
14177
#ifdef _SC_GETPW_R_SIZE_MAX
14178
    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
14179
#endif
14180
#ifdef _SC_ICACHE_ASSOC
14181
    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
14182
#endif
14183
#ifdef _SC_ICACHE_BLKSZ
14184
    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
14185
#endif
14186
#ifdef _SC_ICACHE_LINESZ
14187
    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
14188
#endif
14189
#ifdef _SC_ICACHE_SZ
14190
    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
14191
#endif
14192
#ifdef _SC_INF
14193
    {"SC_INF",  _SC_INF},
14194
#endif
14195
#ifdef _SC_INT_MAX
14196
    {"SC_INT_MAX",      _SC_INT_MAX},
14197
#endif
14198
#ifdef _SC_INT_MIN
14199
    {"SC_INT_MIN",      _SC_INT_MIN},
14200
#endif
14201
#ifdef _SC_IOV_MAX
14202
    {"SC_IOV_MAX",      _SC_IOV_MAX},
14203
#endif
14204
#ifdef _SC_IP_SECOPTS
14205
    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
14206
#endif
14207
#ifdef _SC_JOB_CONTROL
14208
    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
14209
#endif
14210
#ifdef _SC_KERN_POINTERS
14211
    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
14212
#endif
14213
#ifdef _SC_KERN_SIM
14214
    {"SC_KERN_SIM",     _SC_KERN_SIM},
14215
#endif
14216
#ifdef _SC_LINE_MAX
14217
    {"SC_LINE_MAX",     _SC_LINE_MAX},
14218
#endif
14219
#ifdef _SC_LOGIN_NAME_MAX
14220
    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
14221
#endif
14222
#ifdef _SC_LOGNAME_MAX
14223
    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
14224
#endif
14225
#ifdef _SC_LONG_BIT
14226
    {"SC_LONG_BIT",     _SC_LONG_BIT},
14227
#endif
14228
#ifdef _SC_MAC
14229
    {"SC_MAC",  _SC_MAC},
14230
#endif
14231
#ifdef _SC_MAPPED_FILES
14232
    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
14233
#endif
14234
#ifdef _SC_MAXPID
14235
    {"SC_MAXPID",       _SC_MAXPID},
14236
#endif
14237
#ifdef _SC_MB_LEN_MAX
14238
    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
14239
#endif
14240
#ifdef _SC_MEMLOCK
14241
    {"SC_MEMLOCK",      _SC_MEMLOCK},
14242
#endif
14243
#ifdef _SC_MEMLOCK_RANGE
14244
    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
14245
#endif
14246
#ifdef _SC_MEMORY_PROTECTION
14247
    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
14248
#endif
14249
#ifdef _SC_MESSAGE_PASSING
14250
    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
14251
#endif
14252
#ifdef _SC_MMAP_FIXED_ALIGNMENT
14253
    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
14254
#endif
14255
#ifdef _SC_MQ_OPEN_MAX
14256
    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
14257
#endif
14258
#ifdef _SC_MQ_PRIO_MAX
14259
    {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
14260
#endif
14261
#ifdef _SC_NACLS_MAX
14262
    {"SC_NACLS_MAX",    _SC_NACLS_MAX},
14263
#endif
14264
#ifdef _SC_NGROUPS_MAX
14265
    {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
14266
#endif
14267
#ifdef _SC_NL_ARGMAX
14268
    {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
14269
#endif
14270
#ifdef _SC_NL_LANGMAX
14271
    {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
14272
#endif
14273
#ifdef _SC_NL_MSGMAX
14274
    {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
14275
#endif
14276
#ifdef _SC_NL_NMAX
14277
    {"SC_NL_NMAX",      _SC_NL_NMAX},
14278
#endif
14279
#ifdef _SC_NL_SETMAX
14280
    {"SC_NL_SETMAX",    _SC_NL_SETMAX},
14281
#endif
14282
#ifdef _SC_NL_TEXTMAX
14283
    {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
14284
#endif
14285
#ifdef _SC_NPROCESSORS_CONF
14286
    {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
14287
#endif
14288
#ifdef _SC_NPROCESSORS_ONLN
14289
    {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
14290
#endif
14291
#ifdef _SC_NPROC_CONF
14292
    {"SC_NPROC_CONF",   _SC_NPROC_CONF},
14293
#endif
14294
#ifdef _SC_NPROC_ONLN
14295
    {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
14296
#endif
14297
#ifdef _SC_NZERO
14298
    {"SC_NZERO",        _SC_NZERO},
14299
#endif
14300
#ifdef _SC_OPEN_MAX
14301
    {"SC_OPEN_MAX",     _SC_OPEN_MAX},
14302
#endif
14303
#ifdef _SC_PAGESIZE
14304
    {"SC_PAGESIZE",     _SC_PAGESIZE},
14305
#endif
14306
#ifdef _SC_PAGE_SIZE
14307
    {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
14308
#endif
14309
#ifdef _SC_AIX_REALMEM
14310
    {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
14311
#endif
14312
#ifdef _SC_PASS_MAX
14313
    {"SC_PASS_MAX",     _SC_PASS_MAX},
14314
#endif
14315
#ifdef _SC_PHYS_PAGES
14316
    {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
14317
#endif
14318
#ifdef _SC_PII
14319
    {"SC_PII",  _SC_PII},
14320
#endif
14321
#ifdef _SC_PII_INTERNET
14322
    {"SC_PII_INTERNET", _SC_PII_INTERNET},
14323
#endif
14324
#ifdef _SC_PII_INTERNET_DGRAM
14325
    {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
14326
#endif
14327
#ifdef _SC_PII_INTERNET_STREAM
14328
    {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
14329
#endif
14330
#ifdef _SC_PII_OSI
14331
    {"SC_PII_OSI",      _SC_PII_OSI},
14332
#endif
14333
#ifdef _SC_PII_OSI_CLTS
14334
    {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
14335
#endif
14336
#ifdef _SC_PII_OSI_COTS
14337
    {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
14338
#endif
14339
#ifdef _SC_PII_OSI_M
14340
    {"SC_PII_OSI_M",    _SC_PII_OSI_M},
14341
#endif
14342
#ifdef _SC_PII_SOCKET
14343
    {"SC_PII_SOCKET",   _SC_PII_SOCKET},
14344
#endif
14345
#ifdef _SC_PII_XTI
14346
    {"SC_PII_XTI",      _SC_PII_XTI},
14347
#endif
14348
#ifdef _SC_POLL
14349
    {"SC_POLL", _SC_POLL},
14350
#endif
14351
#ifdef _SC_PRIORITIZED_IO
14352
    {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
14353
#endif
14354
#ifdef _SC_PRIORITY_SCHEDULING
14355
    {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
14356
#endif
14357
#ifdef _SC_REALTIME_SIGNALS
14358
    {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
14359
#endif
14360
#ifdef _SC_RE_DUP_MAX
14361
    {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
14362
#endif
14363
#ifdef _SC_RTSIG_MAX
14364
    {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
14365
#endif
14366
#ifdef _SC_SAVED_IDS
14367
    {"SC_SAVED_IDS",    _SC_SAVED_IDS},
14368
#endif
14369
#ifdef _SC_SCHAR_MAX
14370
    {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
14371
#endif
14372
#ifdef _SC_SCHAR_MIN
14373
    {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
14374
#endif
14375
#ifdef _SC_SELECT
14376
    {"SC_SELECT",       _SC_SELECT},
14377
#endif
14378
#ifdef _SC_SEMAPHORES
14379
    {"SC_SEMAPHORES",   _SC_SEMAPHORES},
14380
#endif
14381
#ifdef _SC_SEM_NSEMS_MAX
14382
    {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
14383
#endif
14384
#ifdef _SC_SEM_VALUE_MAX
14385
    {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
14386
#endif
14387
#ifdef _SC_SHARED_MEMORY_OBJECTS
14388
    {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
14389
#endif
14390
#ifdef _SC_SHRT_MAX
14391
    {"SC_SHRT_MAX",     _SC_SHRT_MAX},
14392
#endif
14393
#ifdef _SC_SHRT_MIN
14394
    {"SC_SHRT_MIN",     _SC_SHRT_MIN},
14395
#endif
14396
#ifdef _SC_SIGQUEUE_MAX
14397
    {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
14398
#endif
14399
#ifdef _SC_SIGRT_MAX
14400
    {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
14401
#endif
14402
#ifdef _SC_SIGRT_MIN
14403
    {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
14404
#endif
14405
#ifdef _SC_SOFTPOWER
14406
    {"SC_SOFTPOWER",    _SC_SOFTPOWER},
14407
#endif
14408
#ifdef _SC_SPLIT_CACHE
14409
    {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
14410
#endif
14411
#ifdef _SC_SSIZE_MAX
14412
    {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
14413
#endif
14414
#ifdef _SC_STACK_PROT
14415
    {"SC_STACK_PROT",   _SC_STACK_PROT},
14416
#endif
14417
#ifdef _SC_STREAM_MAX
14418
    {"SC_STREAM_MAX",   _SC_STREAM_MAX},
14419
#endif
14420
#ifdef _SC_SYNCHRONIZED_IO
14421
    {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
14422
#endif
14423
#ifdef _SC_THREADS
14424
    {"SC_THREADS",      _SC_THREADS},
14425
#endif
14426
#ifdef _SC_THREAD_ATTR_STACKADDR
14427
    {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
14428
#endif
14429
#ifdef _SC_THREAD_ATTR_STACKSIZE
14430
    {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
14431
#endif
14432
#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
14433
    {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
14434
#endif
14435
#ifdef _SC_THREAD_KEYS_MAX
14436
    {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
14437
#endif
14438
#ifdef _SC_THREAD_PRIORITY_SCHEDULING
14439
    {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
14440
#endif
14441
#ifdef _SC_THREAD_PRIO_INHERIT
14442
    {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
14443
#endif
14444
#ifdef _SC_THREAD_PRIO_PROTECT
14445
    {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
14446
#endif
14447
#ifdef _SC_THREAD_PROCESS_SHARED
14448
    {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
14449
#endif
14450
#ifdef _SC_THREAD_SAFE_FUNCTIONS
14451
    {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
14452
#endif
14453
#ifdef _SC_THREAD_STACK_MIN
14454
    {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
14455
#endif
14456
#ifdef _SC_THREAD_THREADS_MAX
14457
    {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
14458
#endif
14459
#ifdef _SC_TIMERS
14460
    {"SC_TIMERS",       _SC_TIMERS},
14461
#endif
14462
#ifdef _SC_TIMER_MAX
14463
    {"SC_TIMER_MAX",    _SC_TIMER_MAX},
14464
#endif
14465
#ifdef _SC_TTY_NAME_MAX
14466
    {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
14467
#endif
14468
#ifdef _SC_TZNAME_MAX
14469
    {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
14470
#endif
14471
#ifdef _SC_T_IOV_MAX
14472
    {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
14473
#endif
14474
#ifdef _SC_UCHAR_MAX
14475
    {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
14476
#endif
14477
#ifdef _SC_UINT_MAX
14478
    {"SC_UINT_MAX",     _SC_UINT_MAX},
14479
#endif
14480
#ifdef _SC_UIO_MAXIOV
14481
    {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
14482
#endif
14483
#ifdef _SC_ULONG_MAX
14484
    {"SC_ULONG_MAX",    _SC_ULONG_MAX},
14485
#endif
14486
#ifdef _SC_USHRT_MAX
14487
    {"SC_USHRT_MAX",    _SC_USHRT_MAX},
14488
#endif
14489
#ifdef _SC_VERSION
14490
    {"SC_VERSION",      _SC_VERSION},
14491
#endif
14492
#ifdef _SC_WORD_BIT
14493
    {"SC_WORD_BIT",     _SC_WORD_BIT},
14494
#endif
14495
#ifdef _SC_XBS5_ILP32_OFF32
14496
    {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
14497
#endif
14498
#ifdef _SC_XBS5_ILP32_OFFBIG
14499
    {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
14500
#endif
14501
#ifdef _SC_XBS5_LP64_OFF64
14502
    {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
14503
#endif
14504
#ifdef _SC_XBS5_LPBIG_OFFBIG
14505
    {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
14506
#endif
14507
#ifdef _SC_XOPEN_CRYPT
14508
    {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
14509
#endif
14510
#ifdef _SC_XOPEN_ENH_I18N
14511
    {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
14512
#endif
14513
#ifdef _SC_XOPEN_LEGACY
14514
    {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
14515
#endif
14516
#ifdef _SC_XOPEN_REALTIME
14517
    {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
14518
#endif
14519
#ifdef _SC_XOPEN_REALTIME_THREADS
14520
    {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
14521
#endif
14522
#ifdef _SC_XOPEN_SHM
14523
    {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
14524
#endif
14525
#ifdef _SC_XOPEN_UNIX
14526
    {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
14527
#endif
14528
#ifdef _SC_XOPEN_VERSION
14529
    {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
14530
#endif
14531
#ifdef _SC_XOPEN_XCU_VERSION
14532
    {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
14533
#endif
14534
#ifdef _SC_XOPEN_XPG2
14535
    {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
14536
#endif
14537
#ifdef _SC_XOPEN_XPG3
14538
    {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
14539
#endif
14540
#ifdef _SC_XOPEN_XPG4
14541
    {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
14542
#endif
14543
#ifdef _SC_MINSIGSTKSZ
14544
    {"SC_MINSIGSTKSZ",   _SC_MINSIGSTKSZ},
14545
#endif
14546
};
14547
14548
14549
/*[clinic input]
14550
os.sysconf -> long
14551
    name: confname(table="sysconf_names")
14552
    /
14553
14554
Return an integer-valued system configuration variable.
14555
[clinic start generated code]*/
14556
14557
static long
14558
os_sysconf_impl(PyObject *module, int name)
14559
/*[clinic end generated code: output=3662f945fc0cc756 input=930b8f23b5d15086]*/
14560
0
{
14561
0
    long value;
14562
14563
0
    errno = 0;
14564
0
    value = sysconf(name);
14565
0
    if (value == -1 && errno != 0)
14566
0
        posix_error();
14567
0
    return value;
14568
0
}
14569
#endif /* HAVE_SYSCONF */
14570
14571
14572
static int
14573
setup_confname_table(struct constdef *table, size_t tablesize,
14574
                     const char *tablename, PyObject *module)
14575
48
{
14576
48
    PyObject *d = PyDict_New();
14577
48
    if (d == NULL)
14578
0
        return -1;
14579
14580
2.94k
    for (size_t i=0; i < tablesize; ++i) {
14581
2.89k
        PyObject *o = PyLong_FromLong(table[i].value);
14582
2.89k
        if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
14583
0
            Py_XDECREF(o);
14584
0
            Py_DECREF(d);
14585
0
            return -1;
14586
0
        }
14587
2.89k
        Py_DECREF(o);
14588
2.89k
    }
14589
48
    return PyModule_Add(module, tablename, d);
14590
48
}
14591
14592
/* Return -1 on failure, 0 on success. */
14593
static int
14594
setup_confname_tables(PyObject *module)
14595
16
{
14596
16
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
14597
16
    if (setup_confname_table(posix_constants_pathconf,
14598
16
                             sizeof(posix_constants_pathconf)
14599
16
                               / sizeof(struct constdef),
14600
16
                             "pathconf_names", module))
14601
0
        return -1;
14602
16
#endif
14603
16
#ifdef HAVE_CONFSTR
14604
16
    if (setup_confname_table(posix_constants_confstr,
14605
16
                             sizeof(posix_constants_confstr)
14606
16
                               / sizeof(struct constdef),
14607
16
                             "confstr_names", module))
14608
0
        return -1;
14609
16
#endif
14610
16
#ifdef HAVE_SYSCONF
14611
16
    if (setup_confname_table(posix_constants_sysconf,
14612
16
                             sizeof(posix_constants_sysconf)
14613
16
                               / sizeof(struct constdef),
14614
16
                             "sysconf_names", module))
14615
0
        return -1;
14616
16
#endif
14617
16
    return 0;
14618
16
}
14619
14620
14621
/*[clinic input]
14622
os.abort
14623
14624
Abort the interpreter immediately.
14625
14626
This function 'dumps core' or otherwise fails in the hardest way possible
14627
on the hosting operating system.  This function never returns.
14628
[clinic start generated code]*/
14629
14630
static PyObject *
14631
os_abort_impl(PyObject *module)
14632
/*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
14633
0
{
14634
0
    abort();
14635
    /*NOTREACHED*/
14636
#ifndef __clang__
14637
    /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
14638
       GCC emits a warning without "return NULL;" (compiler bug?), but Clang
14639
       is smarter and emits a warning on the return. */
14640
    Py_FatalError("abort() called from Python code didn't abort!");
14641
    return NULL;
14642
#endif
14643
0
}
14644
14645
#ifdef MS_WINDOWS
14646
/* Grab ShellExecute dynamically from shell32 */
14647
static int has_ShellExecute = -1;
14648
static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
14649
                                              LPCWSTR, INT);
14650
static int
14651
check_ShellExecute(void)
14652
{
14653
    HINSTANCE hShell32;
14654
14655
    /* only recheck */
14656
    if (-1 == has_ShellExecute) {
14657
        Py_BEGIN_ALLOW_THREADS
14658
        /* Security note: this call is not vulnerable to "DLL hijacking".
14659
           SHELL32 is part of "KnownDLLs" and so Windows always load
14660
           the system SHELL32.DLL, even if there is another SHELL32.DLL
14661
           in the DLL search path. */
14662
        hShell32 = LoadLibraryW(L"SHELL32");
14663
        if (hShell32) {
14664
            *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
14665
                                            "ShellExecuteW");
14666
            has_ShellExecute = Py_ShellExecuteW != NULL;
14667
        } else {
14668
            has_ShellExecute = 0;
14669
        }
14670
        Py_END_ALLOW_THREADS
14671
    }
14672
    return has_ShellExecute;
14673
}
14674
14675
14676
/*[clinic input]
14677
os.startfile
14678
    filepath: path_t
14679
    operation: Py_UNICODE = NULL
14680
    arguments: Py_UNICODE = NULL
14681
    cwd: path_t(nullable=True) = None
14682
    show_cmd: int = 1
14683
14684
Start a file with its associated application.
14685
14686
When "operation" is not specified or "open", this acts like
14687
double-clicking the file in Explorer, or giving the file name as an
14688
argument to the DOS "start" command: the file is opened with whatever
14689
application (if any) its extension is associated.
14690
When another "operation" is given, it specifies what should be done with
14691
the file.  A typical operation is "print".
14692
14693
"arguments" is passed to the application, but should be omitted if the
14694
file is a document.
14695
14696
"cwd" is the working directory for the operation. If "filepath" is
14697
relative, it will be resolved against this directory. This argument
14698
should usually be an absolute path.
14699
14700
"show_cmd" can be used to override the recommended visibility option.
14701
See the Windows ShellExecute documentation for values.
14702
14703
startfile returns as soon as the associated application is launched.
14704
There is no option to wait for the application to close, and no way
14705
to retrieve the application's exit status.
14706
14707
The filepath is relative to the current directory.  If you want to use
14708
an absolute path, make sure the first character is not a slash ("/");
14709
the underlying Win32 ShellExecute function doesn't work if it is.
14710
[clinic start generated code]*/
14711
14712
static PyObject *
14713
os_startfile_impl(PyObject *module, path_t *filepath,
14714
                  const wchar_t *operation, const wchar_t *arguments,
14715
                  path_t *cwd, int show_cmd)
14716
/*[clinic end generated code: output=1c6f2f3340e31ffa input=8248997b80669622]*/
14717
{
14718
    HINSTANCE rc;
14719
14720
    if(!check_ShellExecute()) {
14721
        /* If the OS doesn't have ShellExecute, return a
14722
           NotImplementedError. */
14723
        return PyErr_Format(PyExc_NotImplementedError,
14724
            "startfile not available on this platform");
14725
    }
14726
14727
    if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
14728
        return NULL;
14729
    }
14730
    if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
14731
                    arguments, cwd->object ? cwd->object : Py_None,
14732
                    show_cmd) < 0) {
14733
        return NULL;
14734
    }
14735
14736
    Py_BEGIN_ALLOW_THREADS
14737
    rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
14738
                          arguments, cwd->wide, show_cmd);
14739
    Py_END_ALLOW_THREADS
14740
14741
    if (rc <= (HINSTANCE)32) {
14742
        win32_error_object("startfile", filepath->object);
14743
        return NULL;
14744
    }
14745
    Py_RETURN_NONE;
14746
}
14747
#endif /* MS_WINDOWS */
14748
14749
14750
#ifdef HAVE_GETLOADAVG
14751
/*[clinic input]
14752
os.getloadavg
14753
14754
Return average recent system load information.
14755
14756
Return the number of processes in the system run queue averaged over
14757
the last 1, 5, and 15 minutes as a tuple of three floats.
14758
Raises OSError if the load average was unobtainable.
14759
[clinic start generated code]*/
14760
14761
static PyObject *
14762
os_getloadavg_impl(PyObject *module)
14763
/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
14764
0
{
14765
0
    double loadavg[3];
14766
0
    if (getloadavg(loadavg, 3)!=3) {
14767
0
        PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
14768
0
        return NULL;
14769
0
    } else
14770
0
        return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
14771
0
}
14772
#endif /* HAVE_GETLOADAVG */
14773
14774
14775
/*[clinic input]
14776
os.device_encoding
14777
    fd: int
14778
14779
Return a string describing the encoding of a terminal's file descriptor.
14780
14781
The file descriptor must be attached to a terminal.
14782
If the device is not a terminal, return None.
14783
[clinic start generated code]*/
14784
14785
static PyObject *
14786
os_device_encoding_impl(PyObject *module, int fd)
14787
/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
14788
0
{
14789
0
    return _Py_device_encoding(fd);
14790
0
}
14791
14792
14793
#ifdef HAVE_SETRESUID
14794
/*[clinic input]
14795
os.setresuid
14796
14797
    ruid: uid_t
14798
    euid: uid_t
14799
    suid: uid_t
14800
    /
14801
14802
Set the current process's real, effective, and saved user ids.
14803
[clinic start generated code]*/
14804
14805
static PyObject *
14806
os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
14807
/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
14808
0
{
14809
0
    if (setresuid(ruid, euid, suid) < 0)
14810
0
        return posix_error();
14811
0
    Py_RETURN_NONE;
14812
0
}
14813
#endif /* HAVE_SETRESUID */
14814
14815
14816
#ifdef HAVE_SETRESGID
14817
/*[clinic input]
14818
os.setresgid
14819
14820
    rgid: gid_t
14821
    egid: gid_t
14822
    sgid: gid_t
14823
    /
14824
14825
Set the current process's real, effective, and saved group ids.
14826
[clinic start generated code]*/
14827
14828
static PyObject *
14829
os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
14830
/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
14831
0
{
14832
0
    if (setresgid(rgid, egid, sgid) < 0)
14833
0
        return posix_error();
14834
0
    Py_RETURN_NONE;
14835
0
}
14836
#endif /* HAVE_SETRESGID */
14837
14838
14839
#ifdef HAVE_GETRESUID
14840
/*[clinic input]
14841
os.getresuid
14842
14843
Return a tuple of the current process's real, effective, and saved user ids.
14844
[clinic start generated code]*/
14845
14846
static PyObject *
14847
os_getresuid_impl(PyObject *module)
14848
/*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
14849
0
{
14850
0
    uid_t ruid, euid, suid;
14851
0
    if (getresuid(&ruid, &euid, &suid) < 0)
14852
0
        return posix_error();
14853
0
    return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
14854
0
                                  _PyLong_FromUid(euid),
14855
0
                                  _PyLong_FromUid(suid));
14856
0
}
14857
#endif /* HAVE_GETRESUID */
14858
14859
14860
#ifdef HAVE_GETRESGID
14861
/*[clinic input]
14862
os.getresgid
14863
14864
Return a tuple of the current process's real, effective, and saved group ids.
14865
[clinic start generated code]*/
14866
14867
static PyObject *
14868
os_getresgid_impl(PyObject *module)
14869
/*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
14870
0
{
14871
0
    gid_t rgid, egid, sgid;
14872
0
    if (getresgid(&rgid, &egid, &sgid) < 0)
14873
0
        return posix_error();
14874
0
    return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
14875
0
                                  _PyLong_FromGid(egid),
14876
0
                                  _PyLong_FromGid(sgid));
14877
0
}
14878
#endif /* HAVE_GETRESGID */
14879
14880
14881
#ifdef USE_XATTRS
14882
/*[clinic input]
14883
os.getxattr
14884
14885
    path: path_t(allow_fd=True)
14886
    attribute: path_t
14887
    *
14888
    follow_symlinks: bool = True
14889
14890
Return the value of extended attribute attribute on path.
14891
14892
path may be either a string, a path-like object, or an open file descriptor.
14893
If follow_symlinks is False, and the last element of the path is a symbolic
14894
  link, getxattr will examine the symbolic link itself instead of the file
14895
  the link points to.
14896
14897
[clinic start generated code]*/
14898
14899
static PyObject *
14900
os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
14901
                 int follow_symlinks)
14902
/*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
14903
0
{
14904
0
    Py_ssize_t i;
14905
0
    PyObject *buffer = NULL;
14906
14907
0
    if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
14908
0
        return NULL;
14909
14910
0
    if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
14911
0
        return NULL;
14912
0
    }
14913
14914
0
    for (i = 0; ; i++) {
14915
0
        void *ptr;
14916
0
        ssize_t result;
14917
0
        static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
14918
0
        Py_ssize_t buffer_size = buffer_sizes[i];
14919
0
        if (!buffer_size) {
14920
0
            path_error(path);
14921
0
            return NULL;
14922
0
        }
14923
0
        buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
14924
0
        if (!buffer)
14925
0
            return NULL;
14926
0
        ptr = PyBytes_AS_STRING(buffer);
14927
14928
0
        Py_BEGIN_ALLOW_THREADS;
14929
0
        if (path->fd >= 0)
14930
0
            result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
14931
0
        else if (follow_symlinks)
14932
0
            result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
14933
0
        else
14934
0
            result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
14935
0
        Py_END_ALLOW_THREADS;
14936
14937
0
        if (result < 0) {
14938
0
            if (errno == ERANGE) {
14939
0
                Py_DECREF(buffer);
14940
0
                continue;
14941
0
            }
14942
0
            path_error(path);
14943
0
            Py_DECREF(buffer);
14944
0
            return NULL;
14945
0
        }
14946
14947
0
        if (result != buffer_size) {
14948
            /* Can only shrink. */
14949
0
            _PyBytes_Resize(&buffer, result);
14950
0
        }
14951
0
        break;
14952
0
    }
14953
14954
0
    return buffer;
14955
0
}
14956
14957
14958
/*[clinic input]
14959
os.setxattr
14960
14961
    path: path_t(allow_fd=True)
14962
    attribute: path_t
14963
    value: Py_buffer
14964
    flags: int = 0
14965
    *
14966
    follow_symlinks: bool = True
14967
14968
Set extended attribute attribute on path to value.
14969
14970
path may be either a string, a path-like object,  or an open file descriptor.
14971
If follow_symlinks is False, and the last element of the path is a symbolic
14972
  link, setxattr will modify the symbolic link itself instead of the file
14973
  the link points to.
14974
14975
[clinic start generated code]*/
14976
14977
static PyObject *
14978
os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
14979
                 Py_buffer *value, int flags, int follow_symlinks)
14980
/*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
14981
0
{
14982
0
    ssize_t result;
14983
14984
0
    if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
14985
0
        return NULL;
14986
14987
0
    if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
14988
0
                    value->buf, value->len, flags) < 0) {
14989
0
        return NULL;
14990
0
    }
14991
14992
0
    Py_BEGIN_ALLOW_THREADS;
14993
0
    if (path->fd > -1)
14994
0
        result = fsetxattr(path->fd, attribute->narrow,
14995
0
                           value->buf, value->len, flags);
14996
0
    else if (follow_symlinks)
14997
0
        result = setxattr(path->narrow, attribute->narrow,
14998
0
                           value->buf, value->len, flags);
14999
0
    else
15000
0
        result = lsetxattr(path->narrow, attribute->narrow,
15001
0
                           value->buf, value->len, flags);
15002
0
    Py_END_ALLOW_THREADS;
15003
15004
0
    if (result) {
15005
0
        path_error(path);
15006
0
        return NULL;
15007
0
    }
15008
15009
0
    Py_RETURN_NONE;
15010
0
}
15011
15012
15013
/*[clinic input]
15014
os.removexattr
15015
15016
    path: path_t(allow_fd=True)
15017
    attribute: path_t
15018
    *
15019
    follow_symlinks: bool = True
15020
15021
Remove extended attribute attribute on path.
15022
15023
path may be either a string, a path-like object, or an open file descriptor.
15024
If follow_symlinks is False, and the last element of the path is a symbolic
15025
  link, removexattr will modify the symbolic link itself instead of the file
15026
  the link points to.
15027
15028
[clinic start generated code]*/
15029
15030
static PyObject *
15031
os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
15032
                    int follow_symlinks)
15033
/*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
15034
0
{
15035
0
    ssize_t result;
15036
15037
0
    if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
15038
0
        return NULL;
15039
15040
0
    if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
15041
0
        return NULL;
15042
0
    }
15043
15044
0
    Py_BEGIN_ALLOW_THREADS;
15045
0
    if (path->fd > -1)
15046
0
        result = fremovexattr(path->fd, attribute->narrow);
15047
0
    else if (follow_symlinks)
15048
0
        result = removexattr(path->narrow, attribute->narrow);
15049
0
    else
15050
0
        result = lremovexattr(path->narrow, attribute->narrow);
15051
0
    Py_END_ALLOW_THREADS;
15052
15053
0
    if (result) {
15054
0
        return path_error(path);
15055
0
    }
15056
15057
0
    Py_RETURN_NONE;
15058
0
}
15059
15060
15061
/*[clinic input]
15062
os.listxattr
15063
15064
    path: path_t(allow_fd=True, nullable=True) = None
15065
    *
15066
    follow_symlinks: bool = True
15067
15068
Return a list of extended attributes on path.
15069
15070
path may be either None, a string, a path-like object, or an open file descriptor.
15071
if path is None, listxattr will examine the current directory.
15072
If follow_symlinks is False, and the last element of the path is a symbolic
15073
  link, listxattr will examine the symbolic link itself instead of the file
15074
  the link points to.
15075
[clinic start generated code]*/
15076
15077
static PyObject *
15078
os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
15079
/*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
15080
0
{
15081
0
    Py_ssize_t i;
15082
0
    PyObject *result = NULL;
15083
0
    const char *name;
15084
0
    char *buffer = NULL;
15085
15086
0
    if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
15087
0
        goto exit;
15088
15089
0
    if (PySys_Audit("os.listxattr", "(O)",
15090
0
                    path->object ? path->object : Py_None) < 0) {
15091
0
        return NULL;
15092
0
    }
15093
15094
0
    name = path->narrow ? path->narrow : ".";
15095
15096
0
    for (i = 0; ; i++) {
15097
0
        const char *start, *trace, *end;
15098
0
        ssize_t length;
15099
0
        static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
15100
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15101
0
        if (!buffer_size) {
15102
            /* ERANGE */
15103
0
            path_error(path);
15104
0
            break;
15105
0
        }
15106
0
        buffer = PyMem_Malloc(buffer_size);
15107
0
        if (!buffer) {
15108
0
            PyErr_NoMemory();
15109
0
            break;
15110
0
        }
15111
15112
0
        Py_BEGIN_ALLOW_THREADS;
15113
0
        if (path->fd > -1)
15114
0
            length = flistxattr(path->fd, buffer, buffer_size);
15115
0
        else if (follow_symlinks)
15116
0
            length = listxattr(name, buffer, buffer_size);
15117
0
        else
15118
0
            length = llistxattr(name, buffer, buffer_size);
15119
0
        Py_END_ALLOW_THREADS;
15120
15121
0
        if (length < 0) {
15122
0
            if (errno == ERANGE) {
15123
0
                PyMem_Free(buffer);
15124
0
                buffer = NULL;
15125
0
                continue;
15126
0
            }
15127
0
            path_error(path);
15128
0
            break;
15129
0
        }
15130
15131
0
        result = PyList_New(0);
15132
0
        if (!result) {
15133
0
            goto exit;
15134
0
        }
15135
15136
0
        end = buffer + length;
15137
0
        for (trace = start = buffer; trace != end; trace++) {
15138
0
            if (!*trace) {
15139
0
                int error;
15140
0
                PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
15141
0
                                                                 trace - start);
15142
0
                if (!attribute) {
15143
0
                    Py_SETREF(result, NULL);
15144
0
                    goto exit;
15145
0
                }
15146
0
                error = PyList_Append(result, attribute);
15147
0
                Py_DECREF(attribute);
15148
0
                if (error) {
15149
0
                    Py_SETREF(result, NULL);
15150
0
                    goto exit;
15151
0
                }
15152
0
                start = trace + 1;
15153
0
            }
15154
0
        }
15155
0
    break;
15156
0
    }
15157
0
exit:
15158
0
    if (buffer)
15159
0
        PyMem_Free(buffer);
15160
0
    return result;
15161
0
}
15162
#endif /* USE_XATTRS */
15163
15164
15165
/*[clinic input]
15166
os.urandom
15167
15168
    size: Py_ssize_t
15169
    /
15170
15171
Return a bytes object containing random bytes suitable for cryptographic use.
15172
[clinic start generated code]*/
15173
15174
static PyObject *
15175
os_urandom_impl(PyObject *module, Py_ssize_t size)
15176
/*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
15177
0
{
15178
0
    PyObject *bytes;
15179
0
    int result;
15180
15181
0
    if (size < 0)
15182
0
        return PyErr_Format(PyExc_ValueError,
15183
0
                            "negative argument not allowed");
15184
0
    bytes = PyBytes_FromStringAndSize(NULL, size);
15185
0
    if (bytes == NULL)
15186
0
        return NULL;
15187
15188
0
    result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
15189
0
    if (result == -1) {
15190
0
        Py_DECREF(bytes);
15191
0
        return NULL;
15192
0
    }
15193
0
    return bytes;
15194
0
}
15195
15196
#ifdef HAVE_MEMFD_CREATE
15197
/*[clinic input]
15198
os.memfd_create
15199
15200
    name: FSConverter
15201
    flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
15202
15203
[clinic start generated code]*/
15204
15205
static PyObject *
15206
os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
15207
/*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
15208
0
{
15209
0
    int fd;
15210
0
    const char *bytes = PyBytes_AS_STRING(name);
15211
0
    Py_BEGIN_ALLOW_THREADS
15212
0
    fd = memfd_create(bytes, flags);
15213
0
    Py_END_ALLOW_THREADS
15214
0
    if (fd == -1) {
15215
0
        return PyErr_SetFromErrno(PyExc_OSError);
15216
0
    }
15217
0
    return PyLong_FromLong(fd);
15218
0
}
15219
#endif
15220
15221
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
15222
/*[clinic input]
15223
os.eventfd
15224
15225
    initval: unsigned_int
15226
    flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
15227
15228
Creates and returns an event notification file descriptor.
15229
[clinic start generated code]*/
15230
15231
static PyObject *
15232
os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
15233
/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
15234
15235
0
{
15236
    /* initval is limited to uint32_t, internal counter is uint64_t */
15237
0
    int fd;
15238
0
    Py_BEGIN_ALLOW_THREADS
15239
0
    fd = eventfd(initval, flags);
15240
0
    Py_END_ALLOW_THREADS
15241
0
    if (fd == -1) {
15242
0
        return PyErr_SetFromErrno(PyExc_OSError);
15243
0
    }
15244
0
    return PyLong_FromLong(fd);
15245
0
}
15246
15247
/*[clinic input]
15248
os.eventfd_read
15249
15250
    fd: fildes
15251
15252
Read eventfd value
15253
[clinic start generated code]*/
15254
15255
static PyObject *
15256
os_eventfd_read_impl(PyObject *module, int fd)
15257
/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
15258
0
{
15259
0
    eventfd_t value;
15260
0
    int result;
15261
0
    Py_BEGIN_ALLOW_THREADS
15262
0
    result = eventfd_read(fd, &value);
15263
0
    Py_END_ALLOW_THREADS
15264
0
    if (result == -1) {
15265
0
        return PyErr_SetFromErrno(PyExc_OSError);
15266
0
    }
15267
0
    return PyLong_FromUnsignedLongLong(value);
15268
0
}
15269
15270
/*[clinic input]
15271
os.eventfd_write
15272
15273
    fd: fildes
15274
    value: unsigned_long_long
15275
15276
Write eventfd value.
15277
[clinic start generated code]*/
15278
15279
static PyObject *
15280
os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
15281
/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
15282
0
{
15283
0
    int result;
15284
0
    Py_BEGIN_ALLOW_THREADS
15285
0
    result = eventfd_write(fd, value);
15286
0
    Py_END_ALLOW_THREADS
15287
0
    if (result == -1) {
15288
0
        return PyErr_SetFromErrno(PyExc_OSError);
15289
0
    }
15290
0
    Py_RETURN_NONE;
15291
0
}
15292
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
15293
15294
/* Terminal size querying */
15295
15296
PyDoc_STRVAR(TerminalSize_docstring,
15297
    "A tuple of (columns, lines) for holding terminal window size");
15298
15299
static PyStructSequence_Field TerminalSize_fields[] = {
15300
    {"columns", "width of the terminal window in characters"},
15301
    {"lines", "height of the terminal window in characters"},
15302
    {NULL, NULL}
15303
};
15304
15305
static PyStructSequence_Desc TerminalSize_desc = {
15306
    "os.terminal_size",
15307
    TerminalSize_docstring,
15308
    TerminalSize_fields,
15309
    2,
15310
};
15311
15312
#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
15313
/*[clinic input]
15314
os.get_terminal_size
15315
15316
    fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
15317
    /
15318
15319
Return the size of the terminal window as (columns, lines).
15320
15321
The optional argument fd (default standard output) specifies
15322
which file descriptor should be queried.
15323
15324
If the file descriptor is not connected to a terminal, an OSError
15325
is thrown.
15326
15327
This function will only be defined if an implementation is
15328
available for this system.
15329
15330
shutil.get_terminal_size is the high-level function which should
15331
normally be used, os.get_terminal_size is the low-level implementation.
15332
[clinic start generated code]*/
15333
15334
static PyObject *
15335
os_get_terminal_size_impl(PyObject *module, int fd)
15336
/*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
15337
0
{
15338
0
    int columns, lines;
15339
0
    PyObject *termsize;
15340
15341
    /* Under some conditions stdout may not be connected and
15342
     * fileno(stdout) may point to an invalid file descriptor. For example
15343
     * GUI apps don't have valid standard streams by default.
15344
     *
15345
     * If this happens, and the optional fd argument is not present,
15346
     * the ioctl below will fail returning EBADF. This is what we want.
15347
     */
15348
15349
0
#ifdef TERMSIZE_USE_IOCTL
15350
0
    {
15351
0
        struct winsize w;
15352
0
        if (ioctl(fd, TIOCGWINSZ, &w))
15353
0
            return PyErr_SetFromErrno(PyExc_OSError);
15354
0
        columns = w.ws_col;
15355
0
        lines = w.ws_row;
15356
0
    }
15357
0
#endif /* TERMSIZE_USE_IOCTL */
15358
15359
#ifdef TERMSIZE_USE_CONIO
15360
    {
15361
        HANDLE handle;
15362
        CONSOLE_SCREEN_BUFFER_INFO csbi;
15363
        handle = _Py_get_osfhandle(fd);
15364
        if (handle == INVALID_HANDLE_VALUE)
15365
            return NULL;
15366
15367
        if (!GetConsoleScreenBufferInfo(handle, &csbi))
15368
            return PyErr_SetFromWindowsErr(0);
15369
15370
        columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
15371
        lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
15372
    }
15373
#endif /* TERMSIZE_USE_CONIO */
15374
15375
0
    PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
15376
0
    termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
15377
0
    if (termsize == NULL)
15378
0
        return NULL;
15379
15380
0
    int pos = 0;
15381
15382
0
#define SET_TERMSIZE(CALL)                                   \
15383
0
    do {                                                     \
15384
0
        PyObject *item = (CALL);                             \
15385
0
        if (item == NULL) {                                  \
15386
0
            Py_DECREF(termsize);                             \
15387
0
            return NULL;                                     \
15388
0
        }                                                    \
15389
0
        PyStructSequence_SET_ITEM(termsize, pos++, item);    \
15390
0
    } while(0)
15391
15392
0
    SET_TERMSIZE(PyLong_FromLong(columns));
15393
0
    SET_TERMSIZE(PyLong_FromLong(lines));
15394
0
#undef SET_TERMSIZE
15395
15396
0
    return termsize;
15397
0
}
15398
#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
15399
15400
/*[clinic input]
15401
os.cpu_count
15402
15403
Return the number of logical CPUs in the system.
15404
15405
Return None if indeterminable.
15406
[clinic start generated code]*/
15407
15408
static PyObject *
15409
os_cpu_count_impl(PyObject *module)
15410
/*[clinic end generated code: output=5fc29463c3936a9c input=ba2f6f8980a0e2eb]*/
15411
0
{
15412
0
    const PyConfig *config = _Py_GetConfig();
15413
0
    if (config->cpu_count > 0) {
15414
0
        return PyLong_FromLong(config->cpu_count);
15415
0
    }
15416
15417
0
    int ncpu = 0;
15418
#ifdef MS_WINDOWS
15419
# ifdef MS_WINDOWS_DESKTOP
15420
    ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
15421
# else
15422
    ncpu = 0;
15423
# endif
15424
15425
#elif defined(__hpux)
15426
    ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
15427
15428
#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
15429
    ncpu = sysconf(_SC_NPROCESSORS_ONLN);
15430
15431
#elif defined(__VXWORKS__)
15432
    ncpu = _Py_popcount32(vxCpuEnabledGet());
15433
15434
#elif defined(__DragonFly__) || \
15435
      defined(__OpenBSD__)   || \
15436
      defined(__FreeBSD__)   || \
15437
      defined(__NetBSD__)    || \
15438
      defined(__APPLE__)
15439
    ncpu = 0;
15440
    size_t len = sizeof(ncpu);
15441
    int mib[2] = {CTL_HW, HW_NCPU};
15442
    if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) {
15443
        ncpu = 0;
15444
    }
15445
#endif
15446
15447
0
    if (ncpu < 1) {
15448
0
        Py_RETURN_NONE;
15449
0
    }
15450
0
    return PyLong_FromLong(ncpu);
15451
0
}
15452
15453
15454
/*[clinic input]
15455
os.get_inheritable -> bool
15456
15457
    fd: int
15458
    /
15459
15460
Get the close-on-exe flag of the specified file descriptor.
15461
[clinic start generated code]*/
15462
15463
static int
15464
os_get_inheritable_impl(PyObject *module, int fd)
15465
/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
15466
0
{
15467
0
    int return_value;
15468
0
    _Py_BEGIN_SUPPRESS_IPH
15469
0
    return_value = _Py_get_inheritable(fd);
15470
0
    _Py_END_SUPPRESS_IPH
15471
0
    return return_value;
15472
0
}
15473
15474
15475
/*[clinic input]
15476
os.set_inheritable
15477
    fd: int
15478
    inheritable: int
15479
    /
15480
15481
Set the inheritable flag of the specified file descriptor.
15482
[clinic start generated code]*/
15483
15484
static PyObject *
15485
os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
15486
/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
15487
0
{
15488
0
    int result;
15489
15490
0
    _Py_BEGIN_SUPPRESS_IPH
15491
0
    result = _Py_set_inheritable(fd, inheritable, NULL);
15492
0
    _Py_END_SUPPRESS_IPH
15493
0
    if (result < 0)
15494
0
        return NULL;
15495
0
    Py_RETURN_NONE;
15496
0
}
15497
15498
15499
#ifdef MS_WINDOWS
15500
#ifndef HANDLE_FLAG_INHERIT
15501
#define HANDLE_FLAG_INHERIT 0x00000001
15502
#endif
15503
15504
/*[clinic input]
15505
os.get_handle_inheritable -> bool
15506
    handle: intptr_t
15507
    /
15508
15509
Get the close-on-exe flag of the specified file descriptor.
15510
[clinic start generated code]*/
15511
15512
static int
15513
os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
15514
/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
15515
{
15516
    DWORD flags;
15517
15518
    if (!GetHandleInformation((HANDLE)handle, &flags)) {
15519
        PyErr_SetFromWindowsErr(0);
15520
        return -1;
15521
    }
15522
15523
    return flags & HANDLE_FLAG_INHERIT;
15524
}
15525
15526
15527
/*[clinic input]
15528
os.set_handle_inheritable
15529
    handle: intptr_t
15530
    inheritable: bool
15531
    /
15532
15533
Set the inheritable flag of the specified handle.
15534
[clinic start generated code]*/
15535
15536
static PyObject *
15537
os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
15538
                               int inheritable)
15539
/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
15540
{
15541
    DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
15542
    if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
15543
        PyErr_SetFromWindowsErr(0);
15544
        return NULL;
15545
    }
15546
    Py_RETURN_NONE;
15547
}
15548
#endif /* MS_WINDOWS */
15549
15550
/*[clinic input]
15551
os.get_blocking -> bool
15552
    fd: int
15553
    /
15554
15555
Get the blocking mode of the file descriptor.
15556
15557
Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
15558
[clinic start generated code]*/
15559
15560
static int
15561
os_get_blocking_impl(PyObject *module, int fd)
15562
/*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
15563
0
{
15564
0
    int blocking;
15565
15566
0
    _Py_BEGIN_SUPPRESS_IPH
15567
0
    blocking = _Py_get_blocking(fd);
15568
0
    _Py_END_SUPPRESS_IPH
15569
0
    return blocking;
15570
0
}
15571
15572
/*[clinic input]
15573
os.set_blocking
15574
    fd: int
15575
    blocking: bool
15576
    /
15577
15578
Set the blocking mode of the specified file descriptor.
15579
15580
Set the O_NONBLOCK flag if blocking is False,
15581
clear the O_NONBLOCK flag otherwise.
15582
[clinic start generated code]*/
15583
15584
static PyObject *
15585
os_set_blocking_impl(PyObject *module, int fd, int blocking)
15586
/*[clinic end generated code: output=384eb43aa0762a9d input=7e9dfc9b14804dd4]*/
15587
0
{
15588
0
    int result;
15589
15590
0
    _Py_BEGIN_SUPPRESS_IPH
15591
0
    result = _Py_set_blocking(fd, blocking);
15592
0
    _Py_END_SUPPRESS_IPH
15593
0
    if (result < 0)
15594
0
        return NULL;
15595
0
    Py_RETURN_NONE;
15596
0
}
15597
15598
15599
/*[clinic input]
15600
class os.DirEntry "DirEntry *" "DirEntryType"
15601
[clinic start generated code]*/
15602
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
15603
15604
typedef struct {
15605
    PyObject_HEAD
15606
    PyObject *name;
15607
    PyObject *path;
15608
    PyObject *stat;
15609
    PyObject *lstat;
15610
#ifdef MS_WINDOWS
15611
    struct _Py_stat_struct win32_lstat;
15612
    uint64_t win32_file_index;
15613
    uint64_t win32_file_index_high;
15614
    int got_file_index;
15615
#else /* POSIX */
15616
#ifdef HAVE_DIRENT_D_TYPE
15617
    unsigned char d_type;
15618
#endif
15619
    ino_t d_ino;
15620
    int dir_fd;
15621
#endif
15622
} DirEntry;
15623
15624
0
#define DirEntry_CAST(op)   ((DirEntry *)(op))
15625
15626
static void
15627
DirEntry_dealloc(PyObject *op)
15628
0
{
15629
0
    DirEntry *entry = DirEntry_CAST(op);
15630
0
    PyTypeObject *tp = Py_TYPE(entry);
15631
0
    Py_XDECREF(entry->name);
15632
0
    Py_XDECREF(entry->path);
15633
0
    Py_XDECREF(entry->stat);
15634
0
    Py_XDECREF(entry->lstat);
15635
0
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
15636
0
    free_func(entry);
15637
0
    Py_DECREF(tp);
15638
0
}
15639
15640
/* Forward reference */
15641
static int
15642
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
15643
                   int follow_symlinks, unsigned short mode_bits);
15644
15645
/*[clinic input]
15646
os.DirEntry.is_symlink -> bool
15647
    defining_class: defining_class
15648
    /
15649
15650
Return True if the entry is a symbolic link; cached per entry.
15651
[clinic start generated code]*/
15652
15653
static int
15654
os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
15655
/*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
15656
0
{
15657
#ifdef MS_WINDOWS
15658
    return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
15659
#elif defined(HAVE_DIRENT_D_TYPE)
15660
    /* POSIX */
15661
0
    if (self->d_type != DT_UNKNOWN)
15662
0
        return self->d_type == DT_LNK;
15663
0
    else
15664
0
        return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
15665
#else
15666
    /* POSIX without d_type */
15667
    return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
15668
#endif
15669
0
}
15670
15671
/*[clinic input]
15672
os.DirEntry.is_junction -> bool
15673
15674
Return True if the entry is a junction; cached per entry.
15675
[clinic start generated code]*/
15676
15677
static int
15678
os_DirEntry_is_junction_impl(DirEntry *self)
15679
/*[clinic end generated code: output=97f64d5d99eeccb5 input=4fc8e701eea118a1]*/
15680
0
{
15681
#ifdef MS_WINDOWS
15682
    return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
15683
#else
15684
0
    return 0;
15685
0
#endif
15686
0
}
15687
15688
static PyObject *
15689
DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
15690
0
{
15691
0
    int result;
15692
0
    STRUCT_STAT st;
15693
0
    PyObject *ub;
15694
15695
#ifdef MS_WINDOWS
15696
    if (!PyUnicode_FSDecoder(self->path, &ub))
15697
        return NULL;
15698
    wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
15699
    Py_DECREF(ub);
15700
#else /* POSIX */
15701
0
    if (!PyUnicode_FSConverter(self->path, &ub))
15702
0
        return NULL;
15703
0
    const char *path = PyBytes_AS_STRING(ub);
15704
0
    if (self->dir_fd != DEFAULT_DIR_FD) {
15705
0
#ifdef HAVE_FSTATAT
15706
0
      if (HAVE_FSTATAT_RUNTIME) {
15707
0
        Py_BEGIN_ALLOW_THREADS
15708
0
        result = fstatat(self->dir_fd, path, &st,
15709
0
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
15710
0
        Py_END_ALLOW_THREADS
15711
0
      } else
15712
15713
0
#endif /* HAVE_FSTATAT */
15714
0
      {
15715
0
        Py_DECREF(ub);
15716
0
        PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
15717
0
        return NULL;
15718
0
      }
15719
0
    }
15720
0
    else
15721
0
#endif
15722
0
    {
15723
0
        Py_BEGIN_ALLOW_THREADS
15724
0
        if (follow_symlinks) {
15725
0
            result = STAT(path, &st);
15726
0
        }
15727
0
        else {
15728
0
            result = LSTAT(path, &st);
15729
0
        }
15730
0
        Py_END_ALLOW_THREADS
15731
0
    }
15732
15733
0
    int saved_errno = errno;
15734
#if defined(MS_WINDOWS)
15735
    PyMem_Free(path);
15736
#else
15737
0
    Py_DECREF(ub);
15738
0
#endif
15739
15740
0
    if (result != 0) {
15741
0
        errno = saved_errno;
15742
0
        path_object_error(self->path);
15743
0
        return NULL;
15744
0
    }
15745
15746
0
    return _pystat_fromstructstat(module, &st);
15747
0
}
15748
15749
static PyObject *
15750
DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
15751
0
{
15752
0
    if (!self->lstat) {
15753
0
        PyObject *module = PyType_GetModule(defining_class);
15754
#ifdef MS_WINDOWS
15755
        self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
15756
#else /* POSIX */
15757
0
        self->lstat = DirEntry_fetch_stat(module, self, 0);
15758
0
#endif
15759
0
    }
15760
0
    return Py_XNewRef(self->lstat);
15761
0
}
15762
15763
/*[clinic input]
15764
os.DirEntry.stat
15765
    defining_class: defining_class
15766
    /
15767
    *
15768
    follow_symlinks: bool = True
15769
15770
Return stat_result object for the entry; cached per entry.
15771
[clinic start generated code]*/
15772
15773
static PyObject *
15774
os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
15775
                      int follow_symlinks)
15776
/*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
15777
0
{
15778
0
    if (!follow_symlinks) {
15779
0
        return DirEntry_get_lstat(defining_class, self);
15780
0
    }
15781
15782
0
    if (!self->stat) {
15783
0
        int result = os_DirEntry_is_symlink_impl(self, defining_class);
15784
0
        if (result == -1) {
15785
0
            return NULL;
15786
0
        }
15787
0
        if (result) {
15788
0
            PyObject *module = PyType_GetModule(defining_class);
15789
0
            self->stat = DirEntry_fetch_stat(module, self, 1);
15790
0
        }
15791
0
        else {
15792
0
            self->stat = DirEntry_get_lstat(defining_class, self);
15793
0
        }
15794
0
    }
15795
15796
0
    return Py_XNewRef(self->stat);
15797
0
}
15798
15799
/* Set exception and return -1 on error, 0 for False, 1 for True */
15800
static int
15801
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
15802
                   int follow_symlinks, unsigned short mode_bits)
15803
0
{
15804
0
    PyObject *stat = NULL;
15805
0
    PyObject *st_mode = NULL;
15806
0
    long mode;
15807
0
    int result;
15808
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
15809
0
    int is_symlink;
15810
0
    int need_stat;
15811
0
#endif
15812
#ifdef MS_WINDOWS
15813
    unsigned long dir_bits;
15814
#endif
15815
15816
#ifdef MS_WINDOWS
15817
    is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
15818
    need_stat = follow_symlinks && is_symlink;
15819
#elif defined(HAVE_DIRENT_D_TYPE)
15820
    is_symlink = self->d_type == DT_LNK;
15821
0
    need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
15822
0
#endif
15823
15824
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
15825
0
    if (need_stat) {
15826
0
#endif
15827
0
        stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
15828
0
        if (!stat) {
15829
0
            if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
15830
                /* If file doesn't exist (anymore), then return False
15831
                   (i.e., say it's not a file/directory) */
15832
0
                PyErr_Clear();
15833
0
                return 0;
15834
0
            }
15835
0
            goto error;
15836
0
        }
15837
0
        _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
15838
0
        st_mode = PyObject_GetAttr(stat, state->st_mode);
15839
0
        if (!st_mode)
15840
0
            goto error;
15841
15842
0
        mode = PyLong_AsLong(st_mode);
15843
0
        if (mode == -1 && PyErr_Occurred())
15844
0
            goto error;
15845
0
        Py_CLEAR(st_mode);
15846
0
        Py_CLEAR(stat);
15847
0
        result = (mode & S_IFMT) == mode_bits;
15848
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
15849
0
    }
15850
0
    else if (is_symlink) {
15851
0
        assert(mode_bits != S_IFLNK);
15852
0
        result = 0;
15853
0
    }
15854
0
    else {
15855
0
        assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
15856
#ifdef MS_WINDOWS
15857
        dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
15858
        if (mode_bits == S_IFDIR)
15859
            result = dir_bits != 0;
15860
        else
15861
            result = dir_bits == 0;
15862
#else /* POSIX */
15863
0
        if (mode_bits == S_IFDIR)
15864
0
            result = self->d_type == DT_DIR;
15865
0
        else
15866
0
            result = self->d_type == DT_REG;
15867
0
#endif
15868
0
    }
15869
0
#endif
15870
15871
0
    return result;
15872
15873
0
error:
15874
0
    Py_XDECREF(st_mode);
15875
0
    Py_XDECREF(stat);
15876
0
    return -1;
15877
0
}
15878
15879
/*[clinic input]
15880
os.DirEntry.is_dir -> bool
15881
    defining_class: defining_class
15882
    /
15883
    *
15884
    follow_symlinks: bool = True
15885
15886
Return True if the entry is a directory; cached per entry.
15887
[clinic start generated code]*/
15888
15889
static int
15890
os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
15891
                        int follow_symlinks)
15892
/*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
15893
0
{
15894
0
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
15895
0
}
15896
15897
/*[clinic input]
15898
os.DirEntry.is_file -> bool
15899
    defining_class: defining_class
15900
    /
15901
    *
15902
    follow_symlinks: bool = True
15903
15904
Return True if the entry is a file; cached per entry.
15905
[clinic start generated code]*/
15906
15907
static int
15908
os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
15909
                         int follow_symlinks)
15910
/*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
15911
0
{
15912
0
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
15913
0
}
15914
15915
/*[clinic input]
15916
os.DirEntry.inode
15917
15918
Return inode of the entry; cached per entry.
15919
[clinic start generated code]*/
15920
15921
static PyObject *
15922
os_DirEntry_inode_impl(DirEntry *self)
15923
/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
15924
0
{
15925
#ifdef MS_WINDOWS
15926
    if (!self->got_file_index) {
15927
        PyObject *unicode;
15928
        STRUCT_STAT stat;
15929
        int result;
15930
15931
        if (!PyUnicode_FSDecoder(self->path, &unicode))
15932
            return NULL;
15933
        wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
15934
        Py_DECREF(unicode);
15935
        result = LSTAT(path, &stat);
15936
15937
        int saved_errno = errno;
15938
        PyMem_Free(path);
15939
15940
        if (result != 0) {
15941
            errno = saved_errno;
15942
            return path_object_error(self->path);
15943
        }
15944
15945
        self->win32_file_index = stat.st_ino;
15946
        self->win32_file_index_high = stat.st_ino_high;
15947
        self->got_file_index = 1;
15948
    }
15949
    return _pystat_l128_from_l64_l64(self->win32_file_index, self->win32_file_index_high);
15950
#else /* POSIX */
15951
0
    static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
15952
0
                  "DirEntry.d_ino is larger than unsigned long long");
15953
0
    return PyLong_FromUnsignedLongLong(self->d_ino);
15954
0
#endif
15955
0
}
15956
15957
static PyObject *
15958
DirEntry_repr(PyObject *op)
15959
0
{
15960
0
    DirEntry *self = DirEntry_CAST(op);
15961
0
    return PyUnicode_FromFormat("<DirEntry %R>", self->name);
15962
0
}
15963
15964
/*[clinic input]
15965
os.DirEntry.__fspath__
15966
15967
Returns the path for the entry.
15968
[clinic start generated code]*/
15969
15970
static PyObject *
15971
os_DirEntry___fspath___impl(DirEntry *self)
15972
/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
15973
0
{
15974
0
    return Py_NewRef(self->path);
15975
0
}
15976
15977
static PyMemberDef DirEntry_members[] = {
15978
    {"name", Py_T_OBJECT_EX, offsetof(DirEntry, name), Py_READONLY,
15979
     "the entry's base filename, relative to scandir() \"path\" argument"},
15980
    {"path", Py_T_OBJECT_EX, offsetof(DirEntry, path), Py_READONLY,
15981
     "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
15982
    {NULL}
15983
};
15984
15985
#include "clinic/posixmodule.c.h"
15986
15987
static PyMethodDef DirEntry_methods[] = {
15988
    OS_DIRENTRY_IS_DIR_METHODDEF
15989
    OS_DIRENTRY_IS_FILE_METHODDEF
15990
    OS_DIRENTRY_IS_SYMLINK_METHODDEF
15991
    OS_DIRENTRY_IS_JUNCTION_METHODDEF
15992
    OS_DIRENTRY_STAT_METHODDEF
15993
    OS_DIRENTRY_INODE_METHODDEF
15994
    OS_DIRENTRY___FSPATH___METHODDEF
15995
    {"__class_getitem__",       Py_GenericAlias,
15996
    METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
15997
    {NULL}
15998
};
15999
16000
static PyType_Slot DirEntryType_slots[] = {
16001
    {Py_tp_dealloc, DirEntry_dealloc},
16002
    {Py_tp_repr, DirEntry_repr},
16003
    {Py_tp_methods, DirEntry_methods},
16004
    {Py_tp_members, DirEntry_members},
16005
    {0, 0},
16006
};
16007
16008
static PyType_Spec DirEntryType_spec = {
16009
    MODNAME ".DirEntry",
16010
    sizeof(DirEntry),
16011
    0,
16012
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
16013
    DirEntryType_slots
16014
};
16015
16016
16017
#ifdef MS_WINDOWS
16018
16019
static wchar_t *
16020
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
16021
{
16022
    Py_ssize_t path_len;
16023
    Py_ssize_t size;
16024
    wchar_t *result;
16025
    wchar_t ch;
16026
16027
    if (!path_wide) { /* Default arg: "." */
16028
        path_wide = L".";
16029
        path_len = 1;
16030
    }
16031
    else {
16032
        path_len = wcslen(path_wide);
16033
    }
16034
16035
    /* The +1's are for the path separator and the NUL */
16036
    size = path_len + 1 + wcslen(filename) + 1;
16037
    result = PyMem_New(wchar_t, size);
16038
    if (!result) {
16039
        PyErr_NoMemory();
16040
        return NULL;
16041
    }
16042
    wcscpy(result, path_wide);
16043
    if (path_len > 0) {
16044
        ch = result[path_len - 1];
16045
        if (ch != SEP && ch != ALTSEP && ch != L':')
16046
            result[path_len++] = SEP;
16047
        wcscpy(result + path_len, filename);
16048
    }
16049
    return result;
16050
}
16051
16052
static PyObject *
16053
DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
16054
{
16055
    DirEntry *entry;
16056
    BY_HANDLE_FILE_INFORMATION file_info;
16057
    ULONG reparse_tag;
16058
    wchar_t *joined_path;
16059
16060
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16061
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16062
    if (!entry)
16063
        return NULL;
16064
    entry->name = NULL;
16065
    entry->path = NULL;
16066
    entry->stat = NULL;
16067
    entry->lstat = NULL;
16068
    entry->got_file_index = 0;
16069
16070
    entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
16071
    if (!entry->name)
16072
        goto error;
16073
    int return_bytes = path->wide && PyBytes_Check(path->object);
16074
    if (return_bytes) {
16075
        Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
16076
        if (!entry->name)
16077
            goto error;
16078
    }
16079
16080
    joined_path = join_path_filenameW(path->wide, dataW->cFileName);
16081
    if (!joined_path)
16082
        goto error;
16083
16084
    entry->path = PyUnicode_FromWideChar(joined_path, -1);
16085
    PyMem_Free(joined_path);
16086
    if (!entry->path)
16087
        goto error;
16088
    if (return_bytes) {
16089
        Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
16090
        if (!entry->path)
16091
            goto error;
16092
    }
16093
16094
    find_data_to_file_info(dataW, &file_info, &reparse_tag);
16095
    _Py_attribute_data_to_stat(&file_info, reparse_tag, NULL, NULL, &entry->win32_lstat);
16096
16097
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
16098
    entry->win32_lstat.st_ctime = entry->win32_lstat.st_birthtime;
16099
    entry->win32_lstat.st_ctime_nsec = entry->win32_lstat.st_birthtime_nsec;
16100
16101
    return (PyObject *)entry;
16102
16103
error:
16104
    Py_DECREF(entry);
16105
    return NULL;
16106
}
16107
16108
#else /* POSIX */
16109
16110
static char *
16111
join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
16112
0
{
16113
0
    Py_ssize_t path_len;
16114
0
    Py_ssize_t size;
16115
0
    char *result;
16116
16117
0
    if (!path_narrow) { /* Default arg: "." */
16118
0
        path_narrow = ".";
16119
0
        path_len = 1;
16120
0
    }
16121
0
    else {
16122
0
        path_len = strlen(path_narrow);
16123
0
    }
16124
16125
0
    if (filename_len == -1)
16126
0
        filename_len = strlen(filename);
16127
16128
    /* The +1's are for the path separator and the NUL */
16129
0
    size = path_len + 1 + filename_len + 1;
16130
0
    result = PyMem_New(char, size);
16131
0
    if (!result) {
16132
0
        PyErr_NoMemory();
16133
0
        return NULL;
16134
0
    }
16135
0
    strcpy(result, path_narrow);
16136
0
    if (path_len > 0 && result[path_len - 1] != '/')
16137
0
        result[path_len++] = '/';
16138
0
    strcpy(result + path_len, filename);
16139
0
    return result;
16140
0
}
16141
16142
static PyObject *
16143
DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
16144
                         Py_ssize_t name_len, ino_t d_ino
16145
#ifdef HAVE_DIRENT_D_TYPE
16146
                         , unsigned char d_type
16147
#endif
16148
                         )
16149
0
{
16150
0
    DirEntry *entry;
16151
0
    char *joined_path;
16152
16153
0
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16154
0
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16155
0
    if (!entry)
16156
0
        return NULL;
16157
0
    entry->name = NULL;
16158
0
    entry->path = NULL;
16159
0
    entry->stat = NULL;
16160
0
    entry->lstat = NULL;
16161
16162
0
    if (path->fd != -1) {
16163
0
        entry->dir_fd = path->fd;
16164
0
        joined_path = NULL;
16165
0
    }
16166
0
    else {
16167
0
        entry->dir_fd = DEFAULT_DIR_FD;
16168
0
        joined_path = join_path_filename(path->narrow, name, name_len);
16169
0
        if (!joined_path)
16170
0
            goto error;
16171
0
    }
16172
16173
0
    if (!path->narrow || !PyBytes_Check(path->object)) {
16174
0
        entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
16175
0
        if (joined_path)
16176
0
            entry->path = PyUnicode_DecodeFSDefault(joined_path);
16177
0
    }
16178
0
    else {
16179
0
        entry->name = PyBytes_FromStringAndSize(name, name_len);
16180
0
        if (joined_path)
16181
0
            entry->path = PyBytes_FromString(joined_path);
16182
0
    }
16183
0
    PyMem_Free(joined_path);
16184
0
    if (!entry->name)
16185
0
        goto error;
16186
16187
0
    if (path->fd != -1) {
16188
0
        entry->path = Py_NewRef(entry->name);
16189
0
    }
16190
0
    else if (!entry->path)
16191
0
        goto error;
16192
16193
0
#ifdef HAVE_DIRENT_D_TYPE
16194
0
    entry->d_type = d_type;
16195
0
#endif
16196
0
    entry->d_ino = d_ino;
16197
16198
0
    return (PyObject *)entry;
16199
16200
0
error:
16201
0
    Py_XDECREF(entry);
16202
0
    return NULL;
16203
0
}
16204
16205
#endif
16206
16207
16208
typedef struct {
16209
    PyObject_HEAD
16210
    path_t path;
16211
#ifdef MS_WINDOWS
16212
    HANDLE handle;
16213
    WIN32_FIND_DATAW file_data;
16214
    int first_time;
16215
#else /* POSIX */
16216
    DIR *dirp;
16217
#endif
16218
#ifdef HAVE_FDOPENDIR
16219
    int fd;
16220
#endif
16221
} ScandirIterator;
16222
16223
0
#define ScandirIterator_CAST(op)    ((ScandirIterator *)(op))
16224
16225
#ifdef MS_WINDOWS
16226
16227
static int
16228
ScandirIterator_is_closed(ScandirIterator *iterator)
16229
{
16230
    return iterator->handle == INVALID_HANDLE_VALUE;
16231
}
16232
16233
static void
16234
ScandirIterator_closedir(ScandirIterator *iterator)
16235
{
16236
    HANDLE handle = iterator->handle;
16237
16238
    if (handle == INVALID_HANDLE_VALUE)
16239
        return;
16240
16241
    iterator->handle = INVALID_HANDLE_VALUE;
16242
    Py_BEGIN_ALLOW_THREADS
16243
    FindClose(handle);
16244
    Py_END_ALLOW_THREADS
16245
}
16246
16247
static PyObject *
16248
ScandirIterator_iternext(PyObject *op)
16249
{
16250
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16251
    WIN32_FIND_DATAW *file_data = &iterator->file_data;
16252
    BOOL success;
16253
    PyObject *entry;
16254
16255
    /* Happens if the iterator is iterated twice, or closed explicitly */
16256
    if (iterator->handle == INVALID_HANDLE_VALUE)
16257
        return NULL;
16258
16259
    while (1) {
16260
        if (!iterator->first_time) {
16261
            Py_BEGIN_ALLOW_THREADS
16262
            success = FindNextFileW(iterator->handle, file_data);
16263
            Py_END_ALLOW_THREADS
16264
            if (!success) {
16265
                /* Error or no more files */
16266
                if (GetLastError() != ERROR_NO_MORE_FILES)
16267
                    path_error(&iterator->path);
16268
                break;
16269
            }
16270
        }
16271
        iterator->first_time = 0;
16272
16273
        /* Skip over . and .. */
16274
        if (wcscmp(file_data->cFileName, L".") != 0 &&
16275
            wcscmp(file_data->cFileName, L"..") != 0)
16276
        {
16277
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16278
            entry = DirEntry_from_find_data(module, &iterator->path, file_data);
16279
            if (!entry)
16280
                break;
16281
            return entry;
16282
        }
16283
16284
        /* Loop till we get a non-dot directory or finish iterating */
16285
    }
16286
16287
    /* Error or no more files */
16288
    ScandirIterator_closedir(iterator);
16289
    return NULL;
16290
}
16291
16292
#else /* POSIX */
16293
16294
static int
16295
ScandirIterator_is_closed(ScandirIterator *iterator)
16296
0
{
16297
0
    return !iterator->dirp;
16298
0
}
16299
16300
static void
16301
ScandirIterator_closedir(ScandirIterator *iterator)
16302
0
{
16303
0
    DIR *dirp = iterator->dirp;
16304
16305
0
    if (!dirp)
16306
0
        return;
16307
16308
0
    iterator->dirp = NULL;
16309
0
    Py_BEGIN_ALLOW_THREADS
16310
0
#ifdef HAVE_FDOPENDIR
16311
0
    if (iterator->path.fd != -1)
16312
0
        rewinddir(dirp);
16313
0
#endif
16314
0
    closedir(dirp);
16315
0
    Py_END_ALLOW_THREADS
16316
0
    return;
16317
0
}
16318
16319
static PyObject *
16320
ScandirIterator_iternext(PyObject *op)
16321
0
{
16322
0
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16323
0
    struct dirent *direntp;
16324
0
    Py_ssize_t name_len;
16325
0
    int is_dot;
16326
0
    PyObject *entry;
16327
16328
    /* Happens if the iterator is iterated twice, or closed explicitly */
16329
0
    if (!iterator->dirp)
16330
0
        return NULL;
16331
16332
0
    while (1) {
16333
0
        errno = 0;
16334
0
        Py_BEGIN_ALLOW_THREADS
16335
0
        direntp = readdir(iterator->dirp);
16336
0
        Py_END_ALLOW_THREADS
16337
16338
0
        if (!direntp) {
16339
            /* Error or no more files */
16340
0
            if (errno != 0)
16341
0
                path_error(&iterator->path);
16342
0
            break;
16343
0
        }
16344
16345
        /* Skip over . and .. */
16346
0
        name_len = NAMLEN(direntp);
16347
0
        is_dot = direntp->d_name[0] == '.' &&
16348
0
                 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
16349
0
        if (!is_dot) {
16350
0
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16351
0
            entry = DirEntry_from_posix_info(module,
16352
0
                                             &iterator->path, direntp->d_name,
16353
0
                                             name_len, direntp->d_ino
16354
0
#ifdef HAVE_DIRENT_D_TYPE
16355
0
                                             , direntp->d_type
16356
0
#endif
16357
0
                                            );
16358
0
            if (!entry)
16359
0
                break;
16360
0
            return entry;
16361
0
        }
16362
16363
        /* Loop till we get a non-dot directory or finish iterating */
16364
0
    }
16365
16366
    /* Error or no more files */
16367
0
    ScandirIterator_closedir(iterator);
16368
0
    return NULL;
16369
0
}
16370
16371
#endif
16372
16373
static PyObject *
16374
ScandirIterator_close(PyObject *op, PyObject *Py_UNUSED(dummy))
16375
0
{
16376
0
    ScandirIterator *self = ScandirIterator_CAST(op);
16377
0
    ScandirIterator_closedir(self);
16378
0
    Py_RETURN_NONE;
16379
0
}
16380
16381
static PyObject *
16382
ScandirIterator_enter(PyObject *self, PyObject *Py_UNUSED(dummy))
16383
0
{
16384
0
    return Py_NewRef(self);
16385
0
}
16386
16387
static PyObject *
16388
ScandirIterator_exit(PyObject *op, PyObject *Py_UNUSED(args))
16389
0
{
16390
0
    ScandirIterator *self = ScandirIterator_CAST(op);
16391
0
    ScandirIterator_closedir(self);
16392
0
    Py_RETURN_NONE;
16393
0
}
16394
16395
static void
16396
ScandirIterator_finalize(PyObject *op)
16397
0
{
16398
0
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16399
    /* Save the current exception, if any. */
16400
0
    PyObject *exc = PyErr_GetRaisedException();
16401
16402
0
    if (!ScandirIterator_is_closed(iterator)) {
16403
0
        ScandirIterator_closedir(iterator);
16404
16405
0
        if (PyErr_ResourceWarning(op, 1,
16406
0
                                  "unclosed scandir iterator %R", iterator))
16407
0
        {
16408
            /* Spurious errors can appear at shutdown */
16409
0
            if (PyErr_ExceptionMatches(PyExc_Warning)) {
16410
0
                PyErr_FormatUnraisable("Exception ignored while finalizing "
16411
0
                                       "scandir iterator %R", iterator);
16412
0
            }
16413
0
        }
16414
0
    }
16415
16416
0
    path_cleanup(&iterator->path);
16417
16418
    /* Restore the saved exception. */
16419
0
    PyErr_SetRaisedException(exc);
16420
0
}
16421
16422
static void
16423
ScandirIterator_dealloc(PyObject *op)
16424
0
{
16425
0
    PyTypeObject *tp = Py_TYPE(op);
16426
0
    if (PyObject_CallFinalizerFromDealloc(op) < 0)
16427
0
        return;
16428
16429
0
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16430
0
    free_func(op);
16431
0
    Py_DECREF(tp);
16432
0
}
16433
16434
static PyMethodDef ScandirIterator_methods[] = {
16435
    {"__enter__", ScandirIterator_enter, METH_NOARGS},
16436
    {"__exit__", ScandirIterator_exit, METH_VARARGS},
16437
    {"close", ScandirIterator_close, METH_NOARGS},
16438
    {NULL}
16439
};
16440
16441
static PyType_Slot ScandirIteratorType_slots[] = {
16442
    {Py_tp_dealloc, ScandirIterator_dealloc},
16443
    {Py_tp_finalize, ScandirIterator_finalize},
16444
    {Py_tp_iter, PyObject_SelfIter},
16445
    {Py_tp_iternext, ScandirIterator_iternext},
16446
    {Py_tp_methods, ScandirIterator_methods},
16447
    {0, 0},
16448
};
16449
16450
static PyType_Spec ScandirIteratorType_spec = {
16451
    MODNAME ".ScandirIterator",
16452
    sizeof(ScandirIterator),
16453
    0,
16454
    // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
16455
    // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
16456
    (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE
16457
        | Py_TPFLAGS_DISALLOW_INSTANTIATION),
16458
    ScandirIteratorType_slots
16459
};
16460
16461
/*[clinic input]
16462
os.scandir
16463
16464
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
16465
16466
Return an iterator of DirEntry objects for given path.
16467
16468
path can be specified as either str, bytes, or a path-like object.  If path
16469
is bytes, the names of yielded DirEntry objects will also be bytes; in
16470
all other circumstances they will be str.
16471
16472
If path is None, uses the path='.'.
16473
[clinic start generated code]*/
16474
16475
static PyObject *
16476
os_scandir_impl(PyObject *module, path_t *path)
16477
/*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
16478
0
{
16479
0
    ScandirIterator *iterator;
16480
#ifdef MS_WINDOWS
16481
    wchar_t *path_strW;
16482
#else
16483
0
    const char *path_str;
16484
0
#ifdef HAVE_FDOPENDIR
16485
0
    int fd = -1;
16486
0
#endif
16487
0
#endif
16488
16489
0
    if (PySys_Audit("os.scandir", "O",
16490
0
                    path->object ? path->object : Py_None) < 0) {
16491
0
        return NULL;
16492
0
    }
16493
16494
0
    PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
16495
0
    iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
16496
0
    if (!iterator)
16497
0
        return NULL;
16498
16499
#ifdef MS_WINDOWS
16500
    iterator->handle = INVALID_HANDLE_VALUE;
16501
#else
16502
0
    iterator->dirp = NULL;
16503
0
#endif
16504
16505
    /* Move the ownership to iterator->path */
16506
0
    memcpy(&iterator->path, path, sizeof(path_t));
16507
0
    memset(path, 0, sizeof(path_t));
16508
16509
#ifdef MS_WINDOWS
16510
    iterator->first_time = 1;
16511
16512
    path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
16513
    if (!path_strW)
16514
        goto error;
16515
16516
    Py_BEGIN_ALLOW_THREADS
16517
    iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
16518
    Py_END_ALLOW_THREADS
16519
16520
    if (iterator->handle == INVALID_HANDLE_VALUE) {
16521
        path_error(&iterator->path);
16522
        PyMem_Free(path_strW);
16523
        goto error;
16524
    }
16525
    PyMem_Free(path_strW);
16526
#else /* POSIX */
16527
0
    errno = 0;
16528
0
#ifdef HAVE_FDOPENDIR
16529
0
    if (iterator->path.fd != -1) {
16530
0
      if (HAVE_FDOPENDIR_RUNTIME) {
16531
        /* closedir() closes the FD, so we duplicate it */
16532
0
        fd = _Py_dup(iterator->path.fd);
16533
0
        if (fd == -1)
16534
0
            goto error;
16535
16536
0
        Py_BEGIN_ALLOW_THREADS
16537
0
        iterator->dirp = fdopendir(fd);
16538
0
        Py_END_ALLOW_THREADS
16539
0
      } else {
16540
0
        PyErr_SetString(PyExc_TypeError,
16541
0
            "scandir: path should be string, bytes, os.PathLike or None, not int");
16542
0
        return NULL;
16543
0
      }
16544
0
    }
16545
0
    else
16546
0
#endif
16547
0
    {
16548
0
        if (iterator->path.narrow)
16549
0
            path_str = iterator->path.narrow;
16550
0
        else
16551
0
            path_str = ".";
16552
16553
0
        Py_BEGIN_ALLOW_THREADS
16554
0
        iterator->dirp = opendir(path_str);
16555
0
        Py_END_ALLOW_THREADS
16556
0
    }
16557
16558
0
    if (!iterator->dirp) {
16559
0
        path_error(&iterator->path);
16560
0
#ifdef HAVE_FDOPENDIR
16561
0
        if (fd != -1) {
16562
0
            Py_BEGIN_ALLOW_THREADS
16563
0
            close(fd);
16564
0
            Py_END_ALLOW_THREADS
16565
0
        }
16566
0
#endif
16567
0
        goto error;
16568
0
    }
16569
0
#endif
16570
16571
0
    return (PyObject *)iterator;
16572
16573
0
error:
16574
0
    Py_DECREF(iterator);
16575
0
    return NULL;
16576
0
}
16577
16578
/*
16579
    Return the file system path representation of the object.
16580
16581
    If the object is str or bytes, then allow it to pass through with
16582
    an incremented refcount. If the object defines __fspath__(), then
16583
    return the result of that method. All other types raise a TypeError.
16584
*/
16585
PyObject *
16586
PyOS_FSPath(PyObject *path)
16587
39.9k
{
16588
    /* For error message reasons, this function is manually inlined in
16589
       path_converter(). */
16590
39.9k
    PyObject *func = NULL;
16591
39.9k
    PyObject *path_repr = NULL;
16592
16593
39.9k
    if (PyUnicode_Check(path) || PyBytes_Check(path)) {
16594
39.9k
        return Py_NewRef(path);
16595
39.9k
    }
16596
16597
0
    func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
16598
0
    if ((NULL == func) || (func == Py_None)) {
16599
0
        return PyErr_Format(PyExc_TypeError,
16600
0
                            "expected str, bytes or os.PathLike object, "
16601
0
                            "not %.200s",
16602
0
                            _PyType_Name(Py_TYPE(path)));
16603
0
    }
16604
16605
0
    path_repr = _PyObject_CallNoArgs(func);
16606
0
    Py_DECREF(func);
16607
0
    if (NULL == path_repr) {
16608
0
        return NULL;
16609
0
    }
16610
16611
0
    if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
16612
0
        PyErr_Format(PyExc_TypeError,
16613
0
                     "expected %.200s.__fspath__() to return str or bytes, "
16614
0
                     "not %.200s", _PyType_Name(Py_TYPE(path)),
16615
0
                     _PyType_Name(Py_TYPE(path_repr)));
16616
0
        Py_DECREF(path_repr);
16617
0
        return NULL;
16618
0
    }
16619
16620
0
    return path_repr;
16621
0
}
16622
16623
/*[clinic input]
16624
os.fspath
16625
16626
    path: object
16627
16628
Return the file system path representation of the object.
16629
16630
If the object is str or bytes, then allow it to pass through as-is. If the
16631
object defines __fspath__(), then return the result of that method. All other
16632
types raise a TypeError.
16633
[clinic start generated code]*/
16634
16635
static PyObject *
16636
os_fspath_impl(PyObject *module, PyObject *path)
16637
/*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
16638
2.89k
{
16639
2.89k
    return PyOS_FSPath(path);
16640
2.89k
}
16641
16642
#ifdef HAVE_GETRANDOM_SYSCALL
16643
/*[clinic input]
16644
os.getrandom
16645
16646
    size: Py_ssize_t
16647
    flags: int=0
16648
16649
Obtain a series of random bytes.
16650
[clinic start generated code]*/
16651
16652
static PyObject *
16653
os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
16654
/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
16655
0
{
16656
0
    PyObject *bytes;
16657
0
    Py_ssize_t n;
16658
16659
0
    if (size < 0) {
16660
0
        errno = EINVAL;
16661
0
        return posix_error();
16662
0
    }
16663
16664
0
    bytes = PyBytes_FromStringAndSize(NULL, size);
16665
0
    if (bytes == NULL) {
16666
0
        PyErr_NoMemory();
16667
0
        return NULL;
16668
0
    }
16669
16670
0
    while (1) {
16671
0
        n = syscall(SYS_getrandom,
16672
0
                    PyBytes_AS_STRING(bytes),
16673
0
                    PyBytes_GET_SIZE(bytes),
16674
0
                    flags);
16675
0
        if (n < 0 && errno == EINTR) {
16676
0
            if (PyErr_CheckSignals() < 0) {
16677
0
                goto error;
16678
0
            }
16679
16680
            /* getrandom() was interrupted by a signal: retry */
16681
0
            continue;
16682
0
        }
16683
0
        break;
16684
0
    }
16685
16686
0
    if (n < 0) {
16687
0
        PyErr_SetFromErrno(PyExc_OSError);
16688
0
        goto error;
16689
0
    }
16690
16691
0
    if (n != size) {
16692
0
        _PyBytes_Resize(&bytes, n);
16693
0
    }
16694
16695
0
    return bytes;
16696
16697
0
error:
16698
0
    Py_DECREF(bytes);
16699
0
    return NULL;
16700
0
}
16701
#endif   /* HAVE_GETRANDOM_SYSCALL */
16702
16703
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
16704
16705
/* bpo-36085: Helper functions for managing DLL search directories
16706
 * on win32
16707
 */
16708
16709
/*[clinic input]
16710
os._add_dll_directory
16711
16712
    path: path_t
16713
16714
Add a path to the DLL search path.
16715
16716
This search path is used when resolving dependencies for imported
16717
extension modules (the module itself is resolved through sys.path),
16718
and also by ctypes.
16719
16720
Returns an opaque value that may be passed to os.remove_dll_directory
16721
to remove this directory from the search path.
16722
[clinic start generated code]*/
16723
16724
static PyObject *
16725
os__add_dll_directory_impl(PyObject *module, path_t *path)
16726
/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
16727
{
16728
    DLL_DIRECTORY_COOKIE cookie = 0;
16729
    DWORD err = 0;
16730
16731
    if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
16732
        return NULL;
16733
    }
16734
16735
    Py_BEGIN_ALLOW_THREADS
16736
    if (!(cookie = AddDllDirectory(path->wide))) {
16737
        err = GetLastError();
16738
    }
16739
    Py_END_ALLOW_THREADS
16740
16741
    if (err) {
16742
        return win32_error_object_err("add_dll_directory",
16743
                                      path->object, err);
16744
    }
16745
16746
    return PyCapsule_New(cookie, "DLL directory cookie", NULL);
16747
}
16748
16749
/*[clinic input]
16750
os._remove_dll_directory
16751
16752
    cookie: object
16753
16754
Removes a path from the DLL search path.
16755
16756
The parameter is an opaque value that was returned from
16757
os.add_dll_directory. You can only remove directories that you added
16758
yourself.
16759
[clinic start generated code]*/
16760
16761
static PyObject *
16762
os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
16763
/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
16764
{
16765
    DLL_DIRECTORY_COOKIE cookieValue;
16766
    DWORD err = 0;
16767
16768
    if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
16769
        PyErr_SetString(PyExc_TypeError,
16770
            "Provided cookie was not returned from os.add_dll_directory");
16771
        return NULL;
16772
    }
16773
16774
    cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
16775
        cookie, "DLL directory cookie");
16776
16777
    Py_BEGIN_ALLOW_THREADS
16778
    if (!RemoveDllDirectory(cookieValue)) {
16779
        err = GetLastError();
16780
    }
16781
    Py_END_ALLOW_THREADS
16782
16783
    if (err) {
16784
        return win32_error_object_err("remove_dll_directory",
16785
                                      NULL, err);
16786
    }
16787
16788
    if (PyCapsule_SetName(cookie, NULL)) {
16789
        return NULL;
16790
    }
16791
16792
    Py_RETURN_NONE;
16793
}
16794
16795
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
16796
16797
16798
/* Only check if WIFEXITED is available: expect that it comes
16799
   with WEXITSTATUS, WIFSIGNALED, etc.
16800
16801
   os.waitstatus_to_exitcode() is implemented in C and not in Python, so
16802
   subprocess can safely call it during late Python finalization without
16803
   risking that used os attributes were set to None by finalize_modules(). */
16804
#if defined(WIFEXITED) || defined(MS_WINDOWS)
16805
/*[clinic input]
16806
os.waitstatus_to_exitcode
16807
16808
    status as status_obj: object
16809
16810
Convert a wait status to an exit code.
16811
16812
On Unix:
16813
16814
* If WIFEXITED(status) is true, return WEXITSTATUS(status).
16815
* If WIFSIGNALED(status) is true, return -WTERMSIG(status).
16816
* Otherwise, raise a ValueError.
16817
16818
On Windows, return status shifted right by 8 bits.
16819
16820
On Unix, if the process is being traced or if waitpid() was called with
16821
WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
16822
This function must not be called if WIFSTOPPED(status) is true.
16823
[clinic start generated code]*/
16824
16825
static PyObject *
16826
os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
16827
/*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
16828
0
{
16829
0
#ifndef MS_WINDOWS
16830
0
    int status = PyLong_AsInt(status_obj);
16831
0
    if (status == -1 && PyErr_Occurred()) {
16832
0
        return NULL;
16833
0
    }
16834
16835
0
    WAIT_TYPE wait_status;
16836
0
    WAIT_STATUS_INT(wait_status) = status;
16837
0
    int exitcode;
16838
0
    if (WIFEXITED(wait_status)) {
16839
0
        exitcode = WEXITSTATUS(wait_status);
16840
        /* Sanity check to provide warranty on the function behavior.
16841
           It should not occur in practice */
16842
0
        if (exitcode < 0) {
16843
0
            PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
16844
0
            return NULL;
16845
0
        }
16846
0
    }
16847
0
    else if (WIFSIGNALED(wait_status)) {
16848
0
        int signum = WTERMSIG(wait_status);
16849
        /* Sanity check to provide warranty on the function behavior.
16850
           It should not occurs in practice */
16851
0
        if (signum <= 0) {
16852
0
            PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
16853
0
            return NULL;
16854
0
        }
16855
0
        exitcode = -signum;
16856
0
    } else if (WIFSTOPPED(wait_status)) {
16857
        /* Status only received if the process is being traced
16858
           or if waitpid() was called with WUNTRACED option. */
16859
0
        int signum = WSTOPSIG(wait_status);
16860
0
        PyErr_Format(PyExc_ValueError,
16861
0
                     "process stopped by delivery of signal %i",
16862
0
                     signum);
16863
0
        return NULL;
16864
0
    }
16865
0
    else {
16866
0
        PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
16867
0
        return NULL;
16868
0
    }
16869
0
    return PyLong_FromLong(exitcode);
16870
#else
16871
    /* Windows implementation: see os.waitpid() implementation
16872
       which uses _cwait(). */
16873
    unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
16874
    if (status == (unsigned long long)-1 && PyErr_Occurred()) {
16875
        return NULL;
16876
    }
16877
16878
    unsigned long long exitcode = (status >> 8);
16879
    /* ExitProcess() accepts an UINT type:
16880
       reject exit code which doesn't fit in an UINT */
16881
    if (exitcode > UINT_MAX) {
16882
        PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
16883
        return NULL;
16884
    }
16885
    return PyLong_FromUnsignedLong((unsigned long)exitcode);
16886
#endif
16887
0
}
16888
#endif
16889
16890
#if defined(MS_WINDOWS)
16891
/*[clinic input]
16892
os._supports_virtual_terminal
16893
16894
Checks if virtual terminal is supported in windows
16895
[clinic start generated code]*/
16896
16897
static PyObject *
16898
os__supports_virtual_terminal_impl(PyObject *module)
16899
/*[clinic end generated code: output=bd0556a6d9d99fe6 input=0752c98e5d321542]*/
16900
{
16901
#ifdef HAVE_WINDOWS_CONSOLE_IO
16902
    DWORD mode = 0;
16903
    HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
16904
    if (!GetConsoleMode(handle, &mode)) {
16905
        Py_RETURN_FALSE;
16906
    }
16907
    return PyBool_FromLong(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING);
16908
#else
16909
    Py_RETURN_FALSE;
16910
#endif /* HAVE_WINDOWS_CONSOLE_IO */
16911
}
16912
#endif
16913
16914
/*[clinic input]
16915
os._inputhook
16916
16917
Calls PyOS_CallInputHook droppong the GIL first
16918
[clinic start generated code]*/
16919
16920
static PyObject *
16921
os__inputhook_impl(PyObject *module)
16922
/*[clinic end generated code: output=525aca4ef3c6149f input=fc531701930d064f]*/
16923
0
{
16924
0
     int result = 0;
16925
0
     if (PyOS_InputHook) {
16926
0
         Py_BEGIN_ALLOW_THREADS;
16927
0
         result = PyOS_InputHook();
16928
0
         Py_END_ALLOW_THREADS;
16929
0
     }
16930
0
     return PyLong_FromLong(result);
16931
0
}
16932
16933
/*[clinic input]
16934
os._is_inputhook_installed
16935
16936
Checks if PyOS_CallInputHook is set
16937
[clinic start generated code]*/
16938
16939
static PyObject *
16940
os__is_inputhook_installed_impl(PyObject *module)
16941
/*[clinic end generated code: output=3b3eab4f672c689a input=ff177c9938dd76d8]*/
16942
0
{
16943
0
    return PyBool_FromLong(PyOS_InputHook != NULL);
16944
0
}
16945
16946
/*[clinic input]
16947
os._create_environ
16948
16949
Create the environment dictionary.
16950
[clinic start generated code]*/
16951
16952
static PyObject *
16953
os__create_environ_impl(PyObject *module)
16954
/*[clinic end generated code: output=19d9039ab14f8ad4 input=a4c05686b34635e8]*/
16955
0
{
16956
0
    return convertenviron();
16957
0
}
16958
16959
16960
#ifdef __EMSCRIPTEN__
16961
/*[clinic input]
16962
os._emscripten_debugger
16963
16964
Create a breakpoint for the JavaScript debugger. Emscripten only.
16965
[clinic start generated code]*/
16966
16967
static PyObject *
16968
os__emscripten_debugger_impl(PyObject *module)
16969
/*[clinic end generated code: output=ad47dc3bf0661343 input=d814b1877fb6083a]*/
16970
{
16971
    emscripten_debugger();
16972
    Py_RETURN_NONE;
16973
}
16974
#endif /* __EMSCRIPTEN__ */
16975
16976
16977
static PyMethodDef posix_methods[] = {
16978
    OS_STAT_METHODDEF
16979
    OS_ACCESS_METHODDEF
16980
    OS_TTYNAME_METHODDEF
16981
    OS_CHDIR_METHODDEF
16982
    OS_CHFLAGS_METHODDEF
16983
    OS_CHMOD_METHODDEF
16984
    OS_FCHMOD_METHODDEF
16985
    OS_LCHMOD_METHODDEF
16986
    OS_CHOWN_METHODDEF
16987
    OS_FCHOWN_METHODDEF
16988
    OS_LCHOWN_METHODDEF
16989
    OS_LCHFLAGS_METHODDEF
16990
    OS_CHROOT_METHODDEF
16991
    OS_CTERMID_METHODDEF
16992
    OS_GETCWD_METHODDEF
16993
    OS_GETCWDB_METHODDEF
16994
    OS_LINK_METHODDEF
16995
    OS_LISTDIR_METHODDEF
16996
    OS_LISTDRIVES_METHODDEF
16997
    OS_LISTMOUNTS_METHODDEF
16998
    OS_LISTVOLUMES_METHODDEF
16999
    OS_LSTAT_METHODDEF
17000
    OS_MKDIR_METHODDEF
17001
    OS_NICE_METHODDEF
17002
    OS_GETPRIORITY_METHODDEF
17003
    OS_SETPRIORITY_METHODDEF
17004
    OS_POSIX_SPAWN_METHODDEF
17005
    OS_POSIX_SPAWNP_METHODDEF
17006
    OS_READLINK_METHODDEF
17007
    OS_COPY_FILE_RANGE_METHODDEF
17008
    OS_SPLICE_METHODDEF
17009
    OS_RENAME_METHODDEF
17010
    OS_REPLACE_METHODDEF
17011
    OS_RMDIR_METHODDEF
17012
    OS_SYMLINK_METHODDEF
17013
    OS_SYSTEM_METHODDEF
17014
    OS_UMASK_METHODDEF
17015
    OS_UNAME_METHODDEF
17016
    OS_UNLINK_METHODDEF
17017
    OS_REMOVE_METHODDEF
17018
    OS_UTIME_METHODDEF
17019
    OS_TIMES_METHODDEF
17020
    OS__EXIT_METHODDEF
17021
    OS__FCOPYFILE_METHODDEF
17022
    OS_EXECV_METHODDEF
17023
    OS_EXECVE_METHODDEF
17024
    OS_SPAWNV_METHODDEF
17025
    OS_SPAWNVE_METHODDEF
17026
    OS_FORK1_METHODDEF
17027
    OS_FORK_METHODDEF
17028
    OS_REGISTER_AT_FORK_METHODDEF
17029
    OS_SCHED_GET_PRIORITY_MAX_METHODDEF
17030
    OS_SCHED_GET_PRIORITY_MIN_METHODDEF
17031
    OS_SCHED_GETPARAM_METHODDEF
17032
    OS_SCHED_GETSCHEDULER_METHODDEF
17033
    OS_SCHED_RR_GET_INTERVAL_METHODDEF
17034
    OS_SCHED_SETPARAM_METHODDEF
17035
    OS_SCHED_SETSCHEDULER_METHODDEF
17036
    OS_SCHED_YIELD_METHODDEF
17037
    OS_SCHED_SETAFFINITY_METHODDEF
17038
    OS_SCHED_GETAFFINITY_METHODDEF
17039
    OS_POSIX_OPENPT_METHODDEF
17040
    OS_GRANTPT_METHODDEF
17041
    OS_UNLOCKPT_METHODDEF
17042
    OS_PTSNAME_METHODDEF
17043
    OS_OPENPTY_METHODDEF
17044
    OS_LOGIN_TTY_METHODDEF
17045
    OS_FORKPTY_METHODDEF
17046
    OS_GETEGID_METHODDEF
17047
    OS_GETEUID_METHODDEF
17048
    OS_GETGID_METHODDEF
17049
    OS_GETGROUPLIST_METHODDEF
17050
    OS_GETGROUPS_METHODDEF
17051
    OS_GETPID_METHODDEF
17052
    OS_GETPGRP_METHODDEF
17053
    OS_GETPPID_METHODDEF
17054
    OS_GETUID_METHODDEF
17055
    OS_GETLOGIN_METHODDEF
17056
    OS_KILL_METHODDEF
17057
    OS_KILLPG_METHODDEF
17058
    OS_PLOCK_METHODDEF
17059
    OS_STARTFILE_METHODDEF
17060
    OS_SETUID_METHODDEF
17061
    OS_SETEUID_METHODDEF
17062
    OS_SETREUID_METHODDEF
17063
    OS_SETGID_METHODDEF
17064
    OS_SETEGID_METHODDEF
17065
    OS_SETREGID_METHODDEF
17066
    OS_SETGROUPS_METHODDEF
17067
    OS_INITGROUPS_METHODDEF
17068
    OS_GETPGID_METHODDEF
17069
    OS_SETPGRP_METHODDEF
17070
    OS_WAIT_METHODDEF
17071
    OS_WAIT3_METHODDEF
17072
    OS_WAIT4_METHODDEF
17073
    OS_WAITID_METHODDEF
17074
    OS_WAITPID_METHODDEF
17075
    OS_PIDFD_OPEN_METHODDEF
17076
    OS_GETSID_METHODDEF
17077
    OS_SETSID_METHODDEF
17078
    OS_SETPGID_METHODDEF
17079
    OS_TCGETPGRP_METHODDEF
17080
    OS_TCSETPGRP_METHODDEF
17081
    OS_OPEN_METHODDEF
17082
    OS_CLOSE_METHODDEF
17083
    OS_CLOSERANGE_METHODDEF
17084
    OS_DEVICE_ENCODING_METHODDEF
17085
    OS_DUP_METHODDEF
17086
    OS_DUP2_METHODDEF
17087
    OS_LOCKF_METHODDEF
17088
    OS_LSEEK_METHODDEF
17089
    OS_READ_METHODDEF
17090
    OS_READINTO_METHODDEF
17091
    OS_READV_METHODDEF
17092
    OS_PREAD_METHODDEF
17093
    OS_PREADV_METHODDEF
17094
    OS_WRITE_METHODDEF
17095
    OS_WRITEV_METHODDEF
17096
    OS_PWRITE_METHODDEF
17097
    OS_PWRITEV_METHODDEF
17098
    OS_SENDFILE_METHODDEF
17099
    OS_FSTAT_METHODDEF
17100
    OS_ISATTY_METHODDEF
17101
    OS_PIPE_METHODDEF
17102
    OS_PIPE2_METHODDEF
17103
    OS_MKFIFO_METHODDEF
17104
    OS_MKNOD_METHODDEF
17105
    OS_MAJOR_METHODDEF
17106
    OS_MINOR_METHODDEF
17107
    OS_MAKEDEV_METHODDEF
17108
    OS_FTRUNCATE_METHODDEF
17109
    OS_TRUNCATE_METHODDEF
17110
    OS_POSIX_FALLOCATE_METHODDEF
17111
    OS_POSIX_FADVISE_METHODDEF
17112
    OS_PUTENV_METHODDEF
17113
    OS_UNSETENV_METHODDEF
17114
    OS_STRERROR_METHODDEF
17115
    OS_FCHDIR_METHODDEF
17116
    OS_FSYNC_METHODDEF
17117
    OS_SYNC_METHODDEF
17118
    OS_FDATASYNC_METHODDEF
17119
    OS_WCOREDUMP_METHODDEF
17120
    OS_WIFCONTINUED_METHODDEF
17121
    OS_WIFSTOPPED_METHODDEF
17122
    OS_WIFSIGNALED_METHODDEF
17123
    OS_WIFEXITED_METHODDEF
17124
    OS_WEXITSTATUS_METHODDEF
17125
    OS_WTERMSIG_METHODDEF
17126
    OS_WSTOPSIG_METHODDEF
17127
    OS_FSTATVFS_METHODDEF
17128
    OS_STATVFS_METHODDEF
17129
    OS_CONFSTR_METHODDEF
17130
    OS_SYSCONF_METHODDEF
17131
    OS_FPATHCONF_METHODDEF
17132
    OS_PATHCONF_METHODDEF
17133
    OS_ABORT_METHODDEF
17134
    OS__GETFULLPATHNAME_METHODDEF
17135
    OS__GETDISKUSAGE_METHODDEF
17136
    OS__GETFINALPATHNAME_METHODDEF
17137
    OS__FINDFIRSTFILE_METHODDEF
17138
    OS__GETVOLUMEPATHNAME_METHODDEF
17139
    OS__PATH_SPLITROOT_METHODDEF
17140
    OS__PATH_SPLITROOT_EX_METHODDEF
17141
    OS__PATH_NORMPATH_METHODDEF
17142
    OS_GETLOADAVG_METHODDEF
17143
    OS_URANDOM_METHODDEF
17144
    OS_SETRESUID_METHODDEF
17145
    OS_SETRESGID_METHODDEF
17146
    OS_GETRESUID_METHODDEF
17147
    OS_GETRESGID_METHODDEF
17148
17149
    OS_GETXATTR_METHODDEF
17150
    OS_SETXATTR_METHODDEF
17151
    OS_REMOVEXATTR_METHODDEF
17152
    OS_LISTXATTR_METHODDEF
17153
17154
    OS_GET_TERMINAL_SIZE_METHODDEF
17155
    OS_CPU_COUNT_METHODDEF
17156
    OS_GET_INHERITABLE_METHODDEF
17157
    OS_SET_INHERITABLE_METHODDEF
17158
    OS_GET_HANDLE_INHERITABLE_METHODDEF
17159
    OS_SET_HANDLE_INHERITABLE_METHODDEF
17160
    OS_GET_BLOCKING_METHODDEF
17161
    OS_SET_BLOCKING_METHODDEF
17162
    OS_SCANDIR_METHODDEF
17163
    OS_FSPATH_METHODDEF
17164
    OS_GETRANDOM_METHODDEF
17165
    OS_MEMFD_CREATE_METHODDEF
17166
    OS_EVENTFD_METHODDEF
17167
    OS_EVENTFD_READ_METHODDEF
17168
    OS_EVENTFD_WRITE_METHODDEF
17169
    OS__ADD_DLL_DIRECTORY_METHODDEF
17170
    OS__REMOVE_DLL_DIRECTORY_METHODDEF
17171
    OS_WAITSTATUS_TO_EXITCODE_METHODDEF
17172
    OS_SETNS_METHODDEF
17173
    OS_UNSHARE_METHODDEF
17174
    OS_TIMERFD_CREATE_METHODDEF
17175
    OS_TIMERFD_SETTIME_METHODDEF
17176
    OS_TIMERFD_SETTIME_NS_METHODDEF
17177
    OS_TIMERFD_GETTIME_METHODDEF
17178
    OS_TIMERFD_GETTIME_NS_METHODDEF
17179
17180
    OS__PATH_ISDEVDRIVE_METHODDEF
17181
    OS__PATH_ISDIR_METHODDEF
17182
    OS__PATH_ISFILE_METHODDEF
17183
    OS__PATH_ISLINK_METHODDEF
17184
    OS__PATH_ISJUNCTION_METHODDEF
17185
    OS__PATH_EXISTS_METHODDEF
17186
    OS__PATH_LEXISTS_METHODDEF
17187
17188
    OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
17189
    OS__INPUTHOOK_METHODDEF
17190
    OS__IS_INPUTHOOK_INSTALLED_METHODDEF
17191
    OS__CREATE_ENVIRON_METHODDEF
17192
    OS__EMSCRIPTEN_DEBUGGER_METHODDEF
17193
    {NULL,              NULL}            /* Sentinel */
17194
};
17195
17196
static int
17197
all_ins(PyObject *m)
17198
16
{
17199
16
#ifdef F_OK
17200
16
    if (PyModule_AddIntMacro(m, F_OK)) return -1;
17201
16
#endif
17202
16
#ifdef R_OK
17203
16
    if (PyModule_AddIntMacro(m, R_OK)) return -1;
17204
16
#endif
17205
16
#ifdef W_OK
17206
16
    if (PyModule_AddIntMacro(m, W_OK)) return -1;
17207
16
#endif
17208
16
#ifdef X_OK
17209
16
    if (PyModule_AddIntMacro(m, X_OK)) return -1;
17210
16
#endif
17211
16
#ifdef NGROUPS_MAX
17212
16
    if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
17213
16
#endif
17214
16
#ifdef TMP_MAX
17215
16
    if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
17216
16
#endif
17217
16
#ifdef WCONTINUED
17218
16
    if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
17219
16
#endif
17220
16
#ifdef WNOHANG
17221
16
    if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
17222
16
#endif
17223
16
#ifdef WUNTRACED
17224
16
    if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
17225
16
#endif
17226
16
#ifdef O_RDONLY
17227
16
    if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
17228
16
#endif
17229
16
#ifdef O_WRONLY
17230
16
    if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
17231
16
#endif
17232
16
#ifdef O_RDWR
17233
16
    if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
17234
16
#endif
17235
16
#ifdef O_NDELAY
17236
16
    if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
17237
16
#endif
17238
16
#ifdef O_NONBLOCK
17239
16
    if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
17240
16
#endif
17241
16
#ifdef O_APPEND
17242
16
    if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
17243
16
#endif
17244
16
#ifdef O_DSYNC
17245
16
    if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
17246
16
#endif
17247
16
#ifdef O_RSYNC
17248
16
    if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
17249
16
#endif
17250
16
#ifdef O_SYNC
17251
16
    if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
17252
16
#endif
17253
16
#ifdef O_NOCTTY
17254
16
    if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
17255
16
#endif
17256
16
#ifdef O_CREAT
17257
16
    if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
17258
16
#endif
17259
16
#ifdef O_EXCL
17260
16
    if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
17261
16
#endif
17262
16
#ifdef O_TRUNC
17263
16
    if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
17264
16
#endif
17265
#ifdef O_BINARY
17266
    if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
17267
#endif
17268
#ifdef O_TEXT
17269
    if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
17270
#endif
17271
#ifdef O_XATTR
17272
    if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
17273
#endif
17274
16
#ifdef O_LARGEFILE
17275
16
    if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
17276
16
#endif
17277
16
#ifndef __GNU__
17278
#ifdef O_SHLOCK
17279
    if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
17280
#endif
17281
#ifdef O_EXLOCK
17282
    if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
17283
#endif
17284
16
#endif
17285
#ifdef O_EXEC
17286
    if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
17287
#endif
17288
#ifdef O_SEARCH
17289
    if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
17290
#endif
17291
16
#ifdef O_PATH
17292
16
    if (PyModule_AddIntMacro(m, O_PATH)) return -1;
17293
16
#endif
17294
#ifdef O_TTY_INIT
17295
    if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
17296
#endif
17297
16
#ifdef O_TMPFILE
17298
16
    if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
17299
16
#endif
17300
16
#ifdef PRIO_PROCESS
17301
16
    if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
17302
16
#endif
17303
16
#ifdef PRIO_PGRP
17304
16
    if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
17305
16
#endif
17306
16
#ifdef PRIO_USER
17307
16
    if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
17308
16
#endif
17309
#ifdef PRIO_DARWIN_THREAD
17310
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_THREAD)) return -1;
17311
#endif
17312
#ifdef PRIO_DARWIN_PROCESS
17313
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_PROCESS)) return -1;
17314
#endif
17315
#ifdef PRIO_DARWIN_BG
17316
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_BG)) return -1;
17317
#endif
17318
#ifdef PRIO_DARWIN_NONUI
17319
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_NONUI)) return -1;
17320
#endif
17321
16
#ifdef O_CLOEXEC
17322
16
    if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
17323
16
#endif
17324
16
#ifdef O_ACCMODE
17325
16
    if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
17326
16
#endif
17327
#ifdef O_EVTONLY
17328
    if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
17329
#endif
17330
16
#ifdef O_FSYNC
17331
16
    if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
17332
16
#endif
17333
#ifdef O_SYMLINK
17334
    if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
17335
#endif
17336
17337
16
#ifdef SEEK_HOLE
17338
16
    if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
17339
16
#endif
17340
16
#ifdef SEEK_DATA
17341
16
    if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
17342
16
#endif
17343
17344
/* MS Windows */
17345
#ifdef O_NOINHERIT
17346
    /* Don't inherit in child processes. */
17347
    if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
17348
#endif
17349
#ifdef _O_SHORT_LIVED
17350
    /* Optimize for short life (keep in memory). */
17351
    /* MS forgot to define this one with a non-underscore form too. */
17352
    if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
17353
#endif
17354
#ifdef O_TEMPORARY
17355
    /* Automatically delete when last handle is closed. */
17356
    if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
17357
#endif
17358
#ifdef O_RANDOM
17359
    /* Optimize for random access. */
17360
    if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
17361
#endif
17362
#ifdef O_SEQUENTIAL
17363
    /* Optimize for sequential access. */
17364
    if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
17365
#endif
17366
17367
/* GNU extensions. */
17368
16
#ifdef O_ASYNC
17369
    /* Send a SIGIO signal whenever input or output
17370
       becomes available on file descriptor */
17371
16
    if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
17372
16
#endif
17373
16
#ifdef O_DIRECT
17374
    /* Direct disk access. */
17375
16
    if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
17376
16
#endif
17377
16
#ifdef O_DIRECTORY
17378
    /* Must be a directory.      */
17379
16
    if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
17380
16
#endif
17381
16
#ifdef O_NOFOLLOW
17382
    /* Do not follow links.      */
17383
16
    if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
17384
16
#endif
17385
#ifdef O_NOFOLLOW_ANY
17386
    if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
17387
#endif
17388
#ifdef O_NOLINKS
17389
    /* Fails if link count of the named file is greater than 1 */
17390
    if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
17391
#endif
17392
16
#ifdef O_NOATIME
17393
    /* Do not update the access time. */
17394
16
    if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
17395
16
#endif
17396
17397
    /* These come from sysexits.h */
17398
16
#ifdef EX_OK
17399
16
    if (PyModule_AddIntMacro(m, EX_OK)) return -1;
17400
16
#endif /* EX_OK */
17401
16
#ifdef EX_USAGE
17402
16
    if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
17403
16
#endif /* EX_USAGE */
17404
16
#ifdef EX_DATAERR
17405
16
    if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
17406
16
#endif /* EX_DATAERR */
17407
16
#ifdef EX_NOINPUT
17408
16
    if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
17409
16
#endif /* EX_NOINPUT */
17410
16
#ifdef EX_NOUSER
17411
16
    if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
17412
16
#endif /* EX_NOUSER */
17413
16
#ifdef EX_NOHOST
17414
16
    if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
17415
16
#endif /* EX_NOHOST */
17416
16
#ifdef EX_UNAVAILABLE
17417
16
    if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
17418
16
#endif /* EX_UNAVAILABLE */
17419
16
#ifdef EX_SOFTWARE
17420
16
    if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
17421
16
#endif /* EX_SOFTWARE */
17422
16
#ifdef EX_OSERR
17423
16
    if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
17424
16
#endif /* EX_OSERR */
17425
16
#ifdef EX_OSFILE
17426
16
    if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
17427
16
#endif /* EX_OSFILE */
17428
16
#ifdef EX_CANTCREAT
17429
16
    if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
17430
16
#endif /* EX_CANTCREAT */
17431
16
#ifdef EX_IOERR
17432
16
    if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
17433
16
#endif /* EX_IOERR */
17434
16
#ifdef EX_TEMPFAIL
17435
16
    if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
17436
16
#endif /* EX_TEMPFAIL */
17437
16
#ifdef EX_PROTOCOL
17438
16
    if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
17439
16
#endif /* EX_PROTOCOL */
17440
16
#ifdef EX_NOPERM
17441
16
    if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
17442
16
#endif /* EX_NOPERM */
17443
16
#ifdef EX_CONFIG
17444
16
    if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
17445
16
#endif /* EX_CONFIG */
17446
#ifdef EX_NOTFOUND
17447
    if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
17448
#endif /* EX_NOTFOUND */
17449
17450
    /* statvfs */
17451
16
#ifdef ST_RDONLY
17452
16
    if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
17453
16
#endif /* ST_RDONLY */
17454
16
#ifdef ST_NOSUID
17455
16
    if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
17456
16
#endif /* ST_NOSUID */
17457
17458
       /* GNU extensions */
17459
16
#ifdef ST_NODEV
17460
16
    if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
17461
16
#endif /* ST_NODEV */
17462
16
#ifdef ST_NOEXEC
17463
16
    if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
17464
16
#endif /* ST_NOEXEC */
17465
16
#ifdef ST_SYNCHRONOUS
17466
16
    if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
17467
16
#endif /* ST_SYNCHRONOUS */
17468
16
#ifdef ST_MANDLOCK
17469
16
    if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
17470
16
#endif /* ST_MANDLOCK */
17471
16
#ifdef ST_WRITE
17472
16
    if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
17473
16
#endif /* ST_WRITE */
17474
16
#ifdef ST_APPEND
17475
16
    if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
17476
16
#endif /* ST_APPEND */
17477
16
#ifdef ST_NOATIME
17478
16
    if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
17479
16
#endif /* ST_NOATIME */
17480
16
#ifdef ST_NODIRATIME
17481
16
    if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
17482
16
#endif /* ST_NODIRATIME */
17483
16
#ifdef ST_RELATIME
17484
16
    if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
17485
16
#endif /* ST_RELATIME */
17486
17487
    /* FreeBSD sendfile() constants */
17488
#ifdef SF_NODISKIO
17489
    if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
17490
#endif
17491
    /* is obsolete since the 11.x release */
17492
#ifdef SF_MNOWAIT
17493
    if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
17494
#endif
17495
#ifdef SF_SYNC
17496
    if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
17497
#endif
17498
#ifdef SF_NOCACHE
17499
    if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
17500
#endif
17501
17502
16
#ifdef TFD_NONBLOCK
17503
16
    if (PyModule_AddIntMacro(m, TFD_NONBLOCK)) return -1;
17504
16
#endif
17505
16
#ifdef TFD_CLOEXEC
17506
16
    if (PyModule_AddIntMacro(m, TFD_CLOEXEC)) return -1;
17507
16
#endif
17508
16
#ifdef TFD_TIMER_ABSTIME
17509
16
    if (PyModule_AddIntMacro(m, TFD_TIMER_ABSTIME)) return -1;
17510
16
#endif
17511
16
#ifdef TFD_TIMER_CANCEL_ON_SET
17512
16
    if (PyModule_AddIntMacro(m, TFD_TIMER_CANCEL_ON_SET)) return -1;
17513
16
#endif
17514
17515
    /* constants for posix_fadvise */
17516
16
#ifdef POSIX_FADV_NORMAL
17517
16
    if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
17518
16
#endif
17519
16
#ifdef POSIX_FADV_SEQUENTIAL
17520
16
    if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
17521
16
#endif
17522
16
#ifdef POSIX_FADV_RANDOM
17523
16
    if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
17524
16
#endif
17525
16
#ifdef POSIX_FADV_NOREUSE
17526
16
    if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
17527
16
#endif
17528
16
#ifdef POSIX_FADV_WILLNEED
17529
16
    if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
17530
16
#endif
17531
16
#ifdef POSIX_FADV_DONTNEED
17532
16
    if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
17533
16
#endif
17534
17535
    /* constants for waitid */
17536
16
#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
17537
16
    if (PyModule_AddIntMacro(m, P_PID)) return -1;
17538
16
    if (PyModule_AddIntMacro(m, P_PGID)) return -1;
17539
16
    if (PyModule_AddIntMacro(m, P_ALL)) return -1;
17540
16
#ifdef P_PIDFD
17541
16
    if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
17542
16
#endif
17543
#ifdef PIDFD_NONBLOCK
17544
    if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1;
17545
#endif
17546
16
#endif
17547
16
#ifdef WEXITED
17548
16
    if (PyModule_AddIntMacro(m, WEXITED)) return -1;
17549
16
#endif
17550
16
#ifdef WNOWAIT
17551
16
    if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
17552
16
#endif
17553
16
#ifdef WSTOPPED
17554
16
    if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
17555
16
#endif
17556
16
#ifdef CLD_EXITED
17557
16
    if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
17558
16
#endif
17559
16
#ifdef CLD_KILLED
17560
16
    if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
17561
16
#endif
17562
16
#ifdef CLD_DUMPED
17563
16
    if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
17564
16
#endif
17565
16
#ifdef CLD_TRAPPED
17566
16
    if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
17567
16
#endif
17568
16
#ifdef CLD_STOPPED
17569
16
    if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
17570
16
#endif
17571
16
#ifdef CLD_CONTINUED
17572
16
    if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
17573
16
#endif
17574
17575
    /* constants for lockf */
17576
16
#ifdef F_LOCK
17577
16
    if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
17578
16
#endif
17579
16
#ifdef F_TLOCK
17580
16
    if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
17581
16
#endif
17582
16
#ifdef F_ULOCK
17583
16
    if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
17584
16
#endif
17585
16
#ifdef F_TEST
17586
16
    if (PyModule_AddIntMacro(m, F_TEST)) return -1;
17587
16
#endif
17588
17589
16
#ifdef RWF_DSYNC
17590
16
    if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
17591
16
#endif
17592
16
#ifdef RWF_HIPRI
17593
16
    if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
17594
16
#endif
17595
16
#ifdef RWF_SYNC
17596
16
    if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
17597
16
#endif
17598
16
#ifdef RWF_NOWAIT
17599
16
    if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
17600
16
#endif
17601
16
#ifdef RWF_APPEND
17602
16
    if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
17603
16
#endif
17604
17605
/* constants for splice */
17606
16
#if defined(HAVE_SPLICE) && defined(__linux__)
17607
16
    if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
17608
16
    if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
17609
16
    if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
17610
16
#endif
17611
17612
/* constants for posix_spawn */
17613
16
#ifdef HAVE_POSIX_SPAWN
17614
16
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
17615
16
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
17616
16
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
17617
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
17618
    if (PyModule_AddIntMacro(m, POSIX_SPAWN_CLOSEFROM)) return -1;
17619
#endif
17620
16
#endif
17621
17622
#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
17623
    if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
17624
    if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
17625
    if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
17626
#endif
17627
#ifdef HAVE_SPAWNV
17628
    if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
17629
    if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
17630
#endif
17631
17632
16
#ifdef HAVE_SCHED_H
17633
16
#ifdef SCHED_OTHER
17634
16
    if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
17635
16
#endif
17636
16
#ifdef SCHED_DEADLINE
17637
16
    if (PyModule_AddIntMacro(m, SCHED_DEADLINE)) return -1;
17638
16
#endif
17639
16
#ifdef SCHED_FIFO
17640
16
    if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
17641
16
#endif
17642
16
#ifdef SCHED_NORMAL
17643
16
    if (PyModule_AddIntMacro(m, SCHED_NORMAL)) return -1;
17644
16
#endif
17645
16
#ifdef SCHED_RR
17646
16
    if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
17647
16
#endif
17648
#ifdef SCHED_SPORADIC
17649
    if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
17650
#endif
17651
16
#ifdef SCHED_BATCH
17652
16
    if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
17653
16
#endif
17654
16
#ifdef SCHED_IDLE
17655
16
    if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
17656
16
#endif
17657
16
#ifdef SCHED_RESET_ON_FORK
17658
16
    if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
17659
16
#endif
17660
#ifdef SCHED_SYS
17661
    if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
17662
#endif
17663
#ifdef SCHED_IA
17664
    if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
17665
#endif
17666
#ifdef SCHED_FSS
17667
    if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
17668
#endif
17669
#ifdef SCHED_FX
17670
    if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
17671
#endif
17672
17673
/* constants for namespaces */
17674
16
#if defined(HAVE_SETNS) || defined(HAVE_UNSHARE)
17675
16
#ifdef CLONE_FS
17676
16
    if (PyModule_AddIntMacro(m, CLONE_FS)) return -1;
17677
16
#endif
17678
16
#ifdef CLONE_FILES
17679
16
    if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1;
17680
16
#endif
17681
16
#ifdef CLONE_NEWNS
17682
16
    if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1;
17683
16
#endif
17684
16
#ifdef CLONE_NEWCGROUP
17685
16
    if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1;
17686
16
#endif
17687
16
#ifdef CLONE_NEWUTS
17688
16
    if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1;
17689
16
#endif
17690
16
#ifdef CLONE_NEWIPC
17691
16
    if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1;
17692
16
#endif
17693
16
#ifdef CLONE_NEWUSER
17694
16
    if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1;
17695
16
#endif
17696
16
#ifdef CLONE_NEWPID
17697
16
    if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1;
17698
16
#endif
17699
16
#ifdef CLONE_NEWNET
17700
16
    if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1;
17701
16
#endif
17702
#ifdef CLONE_NEWTIME
17703
    if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1;
17704
#endif
17705
16
#ifdef CLONE_SYSVSEM
17706
16
    if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1;
17707
16
#endif
17708
16
#ifdef CLONE_THREAD
17709
16
    if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1;
17710
16
#endif
17711
16
#ifdef CLONE_SIGHAND
17712
16
    if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1;
17713
16
#endif
17714
16
#ifdef CLONE_VM
17715
16
    if (PyModule_AddIntMacro(m, CLONE_VM)) return -1;
17716
16
#endif
17717
16
#endif
17718
17719
16
#endif
17720
17721
16
#ifdef USE_XATTRS
17722
16
    if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
17723
16
    if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
17724
16
    if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
17725
16
#endif
17726
17727
16
#if HAVE_DECL_RTLD_LAZY
17728
16
    if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
17729
16
#endif
17730
16
#if HAVE_DECL_RTLD_NOW
17731
16
    if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
17732
16
#endif
17733
16
#if HAVE_DECL_RTLD_GLOBAL
17734
16
    if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
17735
16
#endif
17736
16
#if HAVE_DECL_RTLD_LOCAL
17737
16
    if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
17738
16
#endif
17739
16
#if HAVE_DECL_RTLD_NODELETE
17740
16
    if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
17741
16
#endif
17742
16
#if HAVE_DECL_RTLD_NOLOAD
17743
16
    if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
17744
16
#endif
17745
16
#if HAVE_DECL_RTLD_DEEPBIND
17746
16
    if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
17747
16
#endif
17748
#if HAVE_DECL_RTLD_MEMBER
17749
    if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
17750
#endif
17751
17752
16
#ifdef HAVE_GETRANDOM_SYSCALL
17753
16
    if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
17754
16
    if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
17755
16
#endif
17756
16
#ifdef HAVE_MEMFD_CREATE
17757
16
    if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
17758
16
    if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
17759
16
#ifdef MFD_HUGETLB
17760
16
    if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
17761
16
#endif
17762
16
#ifdef MFD_HUGE_SHIFT
17763
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
17764
16
#endif
17765
16
#ifdef MFD_HUGE_MASK
17766
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
17767
16
#endif
17768
16
#ifdef MFD_HUGE_64KB
17769
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
17770
16
#endif
17771
16
#ifdef MFD_HUGE_512KB
17772
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
17773
16
#endif
17774
16
#ifdef MFD_HUGE_1MB
17775
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
17776
16
#endif
17777
16
#ifdef MFD_HUGE_2MB
17778
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
17779
16
#endif
17780
16
#ifdef MFD_HUGE_8MB
17781
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
17782
16
#endif
17783
16
#ifdef MFD_HUGE_16MB
17784
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
17785
16
#endif
17786
16
#ifdef MFD_HUGE_32MB
17787
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
17788
16
#endif
17789
16
#ifdef MFD_HUGE_256MB
17790
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
17791
16
#endif
17792
16
#ifdef MFD_HUGE_512MB
17793
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
17794
16
#endif
17795
16
#ifdef MFD_HUGE_1GB
17796
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
17797
16
#endif
17798
16
#ifdef MFD_HUGE_2GB
17799
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
17800
16
#endif
17801
16
#ifdef MFD_HUGE_16GB
17802
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
17803
16
#endif
17804
16
#endif /* HAVE_MEMFD_CREATE */
17805
17806
16
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
17807
16
    if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
17808
16
#ifdef EFD_NONBLOCK
17809
16
    if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
17810
16
#endif
17811
16
#ifdef EFD_SEMAPHORE
17812
16
    if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
17813
16
#endif
17814
16
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
17815
17816
#if defined(__APPLE__)
17817
    if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
17818
    if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
17819
    if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
17820
    if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
17821
#endif
17822
17823
#ifdef MS_WINDOWS
17824
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
17825
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
17826
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
17827
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
17828
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
17829
#endif
17830
17831
16
    return 0;
17832
16
}
17833
17834
17835
17836
#define PROBE(name, test) \
17837
   static int name(void)  \
17838
272
   {                      \
17839
272
      if (test) {        \
17840
272
          return 1;       \
17841
272
      } else {            \
17842
0
          return 0;       \
17843
0
      }                   \
17844
272
   }
posixmodule.c:probe_faccessat
Line
Count
Source
17838
16
   {                      \
17839
16
      if (test) {        \
17840
16
          return 1;       \
17841
16
      } else {            \
17842
0
          return 0;       \
17843
0
      }                   \
17844
16
   }
posixmodule.c:probe_fchmodat
Line
Count
Source
17838
16
   {                      \
17839
16
      if (test) {        \
17840
16
          return 1;       \
17841
16
      } else {            \
17842
0
          return 0;       \
17843
0
      }                   \
17844
16
   }
posixmodule.c:probe_fchownat
Line
Count
Source
17838
16
   {                      \
17839
16
      if (test) {        \
17840
16
          return 1;       \
17841
16
      } else {            \
17842
0
          return 0;       \
17843
0
      }                   \
17844
16
   }
posixmodule.c:probe_fdopendir
Line
Count
Source
17838
16
   {                      \
17839
16
      if (test) {        \
17840
16
          return 1;       \
17841
16
      } else {            \
17842
0
          return 0;       \
17843
0
      }                   \
17844
16
   }
posixmodule.c:probe_fstatat
Line
Count
Source
17838
16
   {                      \
17839
16
      if (test) {        \
17840
16
          return 1;       \
17841
16
      } else {            \
17842
0
          return 0;       \
17843
0
      }                   \
17844
16
   }
posixmodule.c:probe_futimens
Line
Count
Source
17838
16
   {                      \
17839
16
      if (test) {        \
17840
16
          return 1;       \
17841
16
      } else {            \
17842
0
          return 0;       \
17843
0
      }                   \
17844
16
   }
posixmodule.c:probe_linkat
Line
Count
Source
17838
16
   {                      \
17839
16
      if (test) {        \
17840
16
          return 1;       \
17841
16
      } else {            \
17842
0
          return 0;       \
17843
0
      }                   \
17844
16
   }
posixmodule.c:probe_mkdirat
Line
Count
Source
17838
16
   {                      \
17839
16
      if (test) {        \
17840
16
          return 1;       \
17841
16
      } else {            \
17842
0
          return 0;       \
17843
0
      }                   \
17844
16
   }
posixmodule.c:probe_mkfifoat
Line
Count
Source
17838
16
   {                      \
17839
16
      if (test) {        \
17840
16
          return 1;       \
17841
16
      } else {            \
17842
0
          return 0;       \
17843
0
      }                   \
17844
16
   }
posixmodule.c:probe_mknodat
Line
Count
Source
17838
16
   {                      \
17839
16
      if (test) {        \
17840
16
          return 1;       \
17841
16
      } else {            \
17842
0
          return 0;       \
17843
0
      }                   \
17844
16
   }
posixmodule.c:probe_openat
Line
Count
Source
17838
16
   {                      \
17839
16
      if (test) {        \
17840
16
          return 1;       \
17841
16
      } else {            \
17842
0
          return 0;       \
17843
0
      }                   \
17844
16
   }
posixmodule.c:probe_readlinkat
Line
Count
Source
17838
16
   {                      \
17839
16
      if (test) {        \
17840
16
          return 1;       \
17841
16
      } else {            \
17842
0
          return 0;       \
17843
0
      }                   \
17844
16
   }
posixmodule.c:probe_renameat
Line
Count
Source
17838
16
   {                      \
17839
16
      if (test) {        \
17840
16
          return 1;       \
17841
16
      } else {            \
17842
0
          return 0;       \
17843
0
      }                   \
17844
16
   }
posixmodule.c:probe_symlinkat
Line
Count
Source
17838
16
   {                      \
17839
16
      if (test) {        \
17840
16
          return 1;       \
17841
16
      } else {            \
17842
0
          return 0;       \
17843
0
      }                   \
17844
16
   }
posixmodule.c:probe_unlinkat
Line
Count
Source
17838
16
   {                      \
17839
16
      if (test) {        \
17840
16
          return 1;       \
17841
16
      } else {            \
17842
0
          return 0;       \
17843
0
      }                   \
17844
16
   }
posixmodule.c:probe_utimensat
Line
Count
Source
17838
16
   {                      \
17839
16
      if (test) {        \
17840
16
          return 1;       \
17841
16
      } else {            \
17842
0
          return 0;       \
17843
0
      }                   \
17844
16
   }
posixmodule.c:probe_ptsname_r
Line
Count
Source
17838
16
   {                      \
17839
16
      if (test) {        \
17840
16
          return 1;       \
17841
16
      } else {            \
17842
0
          return 0;       \
17843
0
      }                   \
17844
16
   }
17845
17846
#ifdef HAVE_FSTATAT
17847
PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
17848
#endif
17849
17850
#ifdef HAVE_FACCESSAT
17851
PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
17852
#endif
17853
17854
#ifdef HAVE_FCHMODAT
17855
PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
17856
#endif
17857
17858
#ifdef HAVE_FCHOWNAT
17859
PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
17860
#endif
17861
17862
#ifdef HAVE_LINKAT
17863
PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
17864
#endif
17865
17866
#ifdef HAVE_FDOPENDIR
17867
PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
17868
#endif
17869
17870
#ifdef HAVE_MKDIRAT
17871
PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
17872
#endif
17873
17874
#ifdef HAVE_MKFIFOAT
17875
PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
17876
#endif
17877
17878
#ifdef HAVE_MKNODAT
17879
PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
17880
#endif
17881
17882
#ifdef HAVE_RENAMEAT
17883
PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
17884
#endif
17885
17886
#ifdef HAVE_UNLINKAT
17887
PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
17888
#endif
17889
17890
#ifdef HAVE_OPENAT
17891
PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
17892
#endif
17893
17894
#ifdef HAVE_READLINKAT
17895
PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
17896
#endif
17897
17898
#ifdef HAVE_SYMLINKAT
17899
PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
17900
#endif
17901
17902
#ifdef HAVE_FUTIMENS
17903
PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
17904
#endif
17905
17906
#ifdef HAVE_UTIMENSAT
17907
PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
17908
#endif
17909
17910
#ifdef HAVE_PTSNAME_R
17911
PROBE(probe_ptsname_r, HAVE_PTSNAME_R_RUNTIME)
17912
#endif
17913
17914
17915
17916
static const struct have_function {
17917
    const char * const label;
17918
    int (*probe)(void);
17919
} have_functions[] = {
17920
17921
#ifdef HAVE_EVENTFD
17922
    {"HAVE_EVENTFD", NULL},
17923
#endif
17924
17925
#ifdef HAVE_TIMERFD_CREATE
17926
    {"HAVE_TIMERFD_CREATE", NULL},
17927
#endif
17928
17929
#ifdef HAVE_FACCESSAT
17930
    { "HAVE_FACCESSAT", probe_faccessat },
17931
#endif
17932
17933
#ifdef HAVE_FCHDIR
17934
    { "HAVE_FCHDIR", NULL },
17935
#endif
17936
17937
#ifdef HAVE_FCHMOD
17938
    { "HAVE_FCHMOD", NULL },
17939
#endif
17940
17941
#ifdef HAVE_FCHMODAT
17942
    { "HAVE_FCHMODAT", probe_fchmodat },
17943
#endif
17944
17945
#ifdef HAVE_FCHOWN
17946
    { "HAVE_FCHOWN", NULL },
17947
#endif
17948
17949
#ifdef HAVE_FCHOWNAT
17950
    { "HAVE_FCHOWNAT", probe_fchownat },
17951
#endif
17952
17953
#ifdef HAVE_FEXECVE
17954
    { "HAVE_FEXECVE", NULL },
17955
#endif
17956
17957
#ifdef HAVE_FDOPENDIR
17958
    { "HAVE_FDOPENDIR", probe_fdopendir },
17959
#endif
17960
17961
#ifdef HAVE_FPATHCONF
17962
    { "HAVE_FPATHCONF", NULL },
17963
#endif
17964
17965
#ifdef HAVE_FSTATAT
17966
    { "HAVE_FSTATAT", probe_fstatat },
17967
#endif
17968
17969
#ifdef HAVE_FSTATVFS
17970
    { "HAVE_FSTATVFS", NULL },
17971
#endif
17972
17973
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
17974
    { "HAVE_FTRUNCATE", NULL },
17975
#endif
17976
17977
#ifdef HAVE_FUTIMENS
17978
    { "HAVE_FUTIMENS", probe_futimens },
17979
#endif
17980
17981
#ifdef HAVE_FUTIMES
17982
    { "HAVE_FUTIMES", NULL },
17983
#endif
17984
17985
#ifdef HAVE_FUTIMESAT
17986
    { "HAVE_FUTIMESAT", NULL },
17987
#endif
17988
17989
#ifdef HAVE_LINKAT
17990
    { "HAVE_LINKAT", probe_linkat },
17991
#endif
17992
17993
#ifdef HAVE_LCHFLAGS
17994
    { "HAVE_LCHFLAGS", NULL },
17995
#endif
17996
17997
#ifdef HAVE_LCHMOD
17998
    { "HAVE_LCHMOD", NULL },
17999
#endif
18000
18001
#ifdef HAVE_LCHOWN
18002
    { "HAVE_LCHOWN", NULL },
18003
#endif
18004
18005
#ifdef HAVE_LSTAT
18006
    { "HAVE_LSTAT", NULL },
18007
#endif
18008
18009
#ifdef HAVE_LUTIMES
18010
    { "HAVE_LUTIMES", NULL },
18011
#endif
18012
18013
#ifdef HAVE_MEMFD_CREATE
18014
    { "HAVE_MEMFD_CREATE", NULL },
18015
#endif
18016
18017
#ifdef HAVE_MKDIRAT
18018
    { "HAVE_MKDIRAT", probe_mkdirat },
18019
#endif
18020
18021
#ifdef HAVE_MKFIFOAT
18022
    { "HAVE_MKFIFOAT", probe_mkfifoat },
18023
#endif
18024
18025
#ifdef HAVE_MKNODAT
18026
    { "HAVE_MKNODAT", probe_mknodat },
18027
#endif
18028
18029
#ifdef HAVE_OPENAT
18030
    { "HAVE_OPENAT", probe_openat },
18031
#endif
18032
18033
#ifdef HAVE_READLINKAT
18034
    { "HAVE_READLINKAT", probe_readlinkat },
18035
#endif
18036
18037
#ifdef HAVE_RENAMEAT
18038
    { "HAVE_RENAMEAT", probe_renameat },
18039
#endif
18040
18041
#ifdef HAVE_SYMLINKAT
18042
    { "HAVE_SYMLINKAT", probe_symlinkat },
18043
#endif
18044
18045
#ifdef HAVE_UNLINKAT
18046
    { "HAVE_UNLINKAT", probe_unlinkat },
18047
#endif
18048
18049
#ifdef HAVE_UTIMENSAT
18050
    { "HAVE_UTIMENSAT", probe_utimensat },
18051
#endif
18052
18053
#ifdef HAVE_PTSNAME_R
18054
    { "HAVE_PTSNAME_R", probe_ptsname_r },
18055
#endif
18056
18057
#ifdef MS_WINDOWS
18058
    { "MS_WINDOWS", NULL },
18059
#endif
18060
18061
    { NULL, NULL }
18062
};
18063
18064
18065
static int
18066
posixmodule_exec(PyObject *m)
18067
16
{
18068
16
    _posixstate *state = get_posix_state(m);
18069
18070
16
#if defined(HAVE_PWRITEV)
18071
16
    if (HAVE_PWRITEV_RUNTIME) {} else {
18072
0
        PyObject* dct = PyModule_GetDict(m);
18073
18074
0
        if (dct == NULL) {
18075
0
            return -1;
18076
0
        }
18077
18078
0
        if (PyDict_PopString(dct, "pwritev", NULL) < 0) {
18079
0
            return -1;
18080
0
        }
18081
0
        if (PyDict_PopString(dct, "preadv", NULL) < 0) {
18082
0
            return -1;
18083
0
        }
18084
0
    }
18085
16
#endif
18086
18087
    /* Initialize environ dictionary */
18088
16
    if (PyModule_Add(m, "environ", convertenviron()) != 0) {
18089
0
        return -1;
18090
0
    }
18091
18092
16
    if (all_ins(m))
18093
0
        return -1;
18094
18095
16
    if (setup_confname_tables(m))
18096
0
        return -1;
18097
18098
16
    if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) {
18099
0
        return -1;
18100
0
    }
18101
18102
16
#if defined(HAVE_WAITID)
18103
16
    waitid_result_desc.name = MODNAME ".waitid_result";
18104
16
    state->WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
18105
16
    if (PyModule_AddObjectRef(m, "waitid_result", state->WaitidResultType) < 0) {
18106
0
        return -1;
18107
0
    }
18108
16
#endif
18109
18110
16
    stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
18111
16
    stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
18112
16
    stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
18113
16
    stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
18114
16
    state->StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
18115
16
    if (PyModule_AddObjectRef(m, "stat_result", state->StatResultType) < 0) {
18116
0
        return -1;
18117
0
    }
18118
16
    state->statresult_new_orig = ((PyTypeObject *)state->StatResultType)->tp_new;
18119
16
    ((PyTypeObject *)state->StatResultType)->tp_new = statresult_new;
18120
18121
16
    statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
18122
16
    state->StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
18123
16
    if (PyModule_AddObjectRef(m, "statvfs_result", state->StatVFSResultType) < 0) {
18124
0
        return -1;
18125
0
    }
18126
18127
16
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
18128
16
    sched_param_desc.name = MODNAME ".sched_param";
18129
16
    state->SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
18130
16
    if (PyModule_AddObjectRef(m, "sched_param", state->SchedParamType) < 0) {
18131
0
        return -1;
18132
0
    }
18133
16
    ((PyTypeObject *)state->SchedParamType)->tp_new = os_sched_param;
18134
16
    if (_PyType_AddMethod((PyTypeObject *)state->SchedParamType,
18135
16
                          &os_sched_param_reduce_method) < 0)
18136
0
    {
18137
0
        return -1;
18138
0
    }
18139
16
    PyType_Modified((PyTypeObject *)state->SchedParamType);
18140
16
#endif
18141
18142
    /* initialize TerminalSize_info */
18143
16
    state->TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
18144
16
    if (PyModule_AddObjectRef(m, "terminal_size", state->TerminalSizeType) < 0) {
18145
0
        return -1;
18146
0
    }
18147
18148
    /* initialize scandir types */
18149
16
    PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
18150
16
    if (ScandirIteratorType == NULL) {
18151
0
        return -1;
18152
0
    }
18153
16
    state->ScandirIteratorType = ScandirIteratorType;
18154
18155
16
    state->DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
18156
16
    if (PyModule_AddObjectRef(m, "DirEntry", state->DirEntryType) < 0) {
18157
0
        return -1;
18158
0
    }
18159
18160
16
    times_result_desc.name = MODNAME ".times_result";
18161
16
    state->TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
18162
16
    if (PyModule_AddObjectRef(m, "times_result", state->TimesResultType) < 0) {
18163
0
        return -1;
18164
0
    }
18165
18166
16
    state->UnameResultType = (PyObject *)PyStructSequence_NewType(&uname_result_desc);
18167
16
    if (PyModule_AddObjectRef(m, "uname_result", state->UnameResultType) < 0) {
18168
0
        return -1;
18169
0
    }
18170
18171
16
    if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
18172
0
        return -1;
18173
16
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
18174
16
    state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
18175
16
    if (state->struct_rusage == NULL)
18176
0
        return -1;
18177
16
#endif
18178
16
    state->st_mode = PyUnicode_InternFromString("st_mode");
18179
16
    if (state->st_mode == NULL)
18180
0
        return -1;
18181
18182
    /* suppress "function not used" warnings */
18183
16
    {
18184
16
    int ignored;
18185
16
    fd_specified("", -1);
18186
16
    follow_symlinks_specified("", 1);
18187
16
    dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
18188
16
    dir_fd_converter(Py_None, &ignored);
18189
16
    dir_fd_unavailable(Py_None, &ignored);
18190
16
    }
18191
18192
    /*
18193
     * provide list of locally available functions
18194
     * so os.py can populate support_* lists
18195
     */
18196
16
    PyObject *list = PyList_New(0);
18197
16
    if (!list) {
18198
0
        return -1;
18199
0
    }
18200
528
    for (const struct have_function *trace = have_functions; trace->label; trace++) {
18201
512
        PyObject *unicode;
18202
512
        if (trace->probe && !trace->probe()) continue;
18203
512
        unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
18204
512
        if (!unicode)
18205
0
            return -1;
18206
512
        if (PyList_Append(list, unicode))
18207
0
            return -1;
18208
512
        Py_DECREF(unicode);
18209
512
    }
18210
18211
16
#ifndef MS_WINDOWS
18212
16
    if (_Py_GetTicksPerSecond(&state->ticks_per_second) < 0) {
18213
0
        PyErr_SetString(PyExc_RuntimeError,
18214
0
                        "cannot read ticks_per_second");
18215
0
        return -1;
18216
0
    }
18217
16
    assert(state->ticks_per_second >= 1);
18218
16
#endif
18219
18220
16
    return PyModule_Add(m, "_have_functions", list);
18221
16
}
18222
18223
18224
static PyModuleDef_Slot posixmodile_slots[] = {
18225
    {Py_mod_exec, posixmodule_exec},
18226
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
18227
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
18228
    {0, NULL}
18229
};
18230
18231
static struct PyModuleDef posixmodule = {
18232
    PyModuleDef_HEAD_INIT,
18233
    .m_name = MODNAME,
18234
    .m_doc = posix__doc__,
18235
    .m_size = sizeof(_posixstate),
18236
    .m_methods = posix_methods,
18237
    .m_slots = posixmodile_slots,
18238
    .m_traverse = _posix_traverse,
18239
    .m_clear = _posix_clear,
18240
    .m_free = _posix_free,
18241
};
18242
18243
PyMODINIT_FUNC
18244
INITFUNC(void)
18245
16
{
18246
16
    return PyModuleDef_Init(&posixmodule);
18247
16
}