Coverage Report

Created: 2025-07-11 06:59

/src/Python-3.8.3/Modules/posixmodule.c
Line
Count
Source (jump to first uncovered line)
1
2
/* POSIX module implementation */
3
4
/* This file is also used for Windows NT/MS-Win.  In that case the
5
   module actually calls itself 'nt', not 'posix', and a few
6
   functions are either unimplemented or implemented differently.  The source
7
   assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
8
   of the compiler used.  Different compilers define their own feature
9
   test macro, e.g. '_MSC_VER'. */
10
11
12
13
#ifdef __APPLE__
14
   /*
15
    * Step 1 of support for weak-linking a number of symbols existing on
16
    * OSX 10.4 and later, see the comment in the #ifdef __APPLE__ block
17
    * at the end of this file for more information.
18
    */
19
#  pragma weak lchown
20
#  pragma weak statvfs
21
#  pragma weak fstatvfs
22
23
#endif /* __APPLE__ */
24
25
#define PY_SSIZE_T_CLEAN
26
27
#include "Python.h"
28
#ifdef MS_WINDOWS
29
   /* include <windows.h> early to avoid conflict with pycore_condvar.h:
30
31
        #define WIN32_LEAN_AND_MEAN
32
        #include <windows.h>
33
34
      FSCTL_GET_REPARSE_POINT is not exported with WIN32_LEAN_AND_MEAN. */
35
#  include <windows.h>
36
#endif
37
38
#include "pycore_ceval.h"     /* _PyEval_ReInitThreads() */
39
#include "pycore_pystate.h"   /* _PyRuntime */
40
#include "pythread.h"
41
#include "structmember.h"
42
#ifndef MS_WINDOWS
43
#  include "posixmodule.h"
44
#else
45
#  include "winreparse.h"
46
#endif
47
48
/* On android API level 21, 'AT_EACCESS' is not declared although
49
 * HAVE_FACCESSAT is defined. */
50
#ifdef __ANDROID__
51
#undef HAVE_FACCESSAT
52
#endif
53
54
#include <stdio.h>  /* needed for ctermid() */
55
56
#ifdef __cplusplus
57
extern "C" {
58
#endif
59
60
PyDoc_STRVAR(posix__doc__,
61
"This module provides access to operating system functionality that is\n\
62
standardized by the C Standard and the POSIX standard (a thinly\n\
63
disguised Unix interface).  Refer to the library manual and\n\
64
corresponding Unix manual entries for more information on calls.");
65
66
67
#ifdef HAVE_SYS_UIO_H
68
#include <sys/uio.h>
69
#endif
70
71
#ifdef HAVE_SYS_SYSMACROS_H
72
/* GNU C Library: major(), minor(), makedev() */
73
#include <sys/sysmacros.h>
74
#endif
75
76
#ifdef HAVE_SYS_TYPES_H
77
#include <sys/types.h>
78
#endif /* HAVE_SYS_TYPES_H */
79
80
#ifdef HAVE_SYS_STAT_H
81
#include <sys/stat.h>
82
#endif /* HAVE_SYS_STAT_H */
83
84
#ifdef HAVE_SYS_WAIT_H
85
#include <sys/wait.h>           /* For WNOHANG */
86
#endif
87
88
#ifdef HAVE_SIGNAL_H
89
#include <signal.h>
90
#endif
91
92
#ifdef HAVE_FCNTL_H
93
#include <fcntl.h>
94
#endif /* HAVE_FCNTL_H */
95
96
#ifdef HAVE_GRP_H
97
#include <grp.h>
98
#endif
99
100
#ifdef HAVE_SYSEXITS_H
101
#include <sysexits.h>
102
#endif /* HAVE_SYSEXITS_H */
103
104
#ifdef HAVE_SYS_LOADAVG_H
105
#include <sys/loadavg.h>
106
#endif
107
108
#ifdef HAVE_SYS_SENDFILE_H
109
#include <sys/sendfile.h>
110
#endif
111
112
#if defined(__APPLE__)
113
#include <copyfile.h>
114
#endif
115
116
#ifdef HAVE_SCHED_H
117
#include <sched.h>
118
#endif
119
120
#ifdef HAVE_COPY_FILE_RANGE
121
#include <unistd.h>
122
#endif
123
124
#if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
125
#undef HAVE_SCHED_SETAFFINITY
126
#endif
127
128
#if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
129
#define USE_XATTRS
130
#endif
131
132
#ifdef USE_XATTRS
133
#include <sys/xattr.h>
134
#endif
135
136
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
137
#ifdef HAVE_SYS_SOCKET_H
138
#include <sys/socket.h>
139
#endif
140
#endif
141
142
#ifdef HAVE_DLFCN_H
143
#include <dlfcn.h>
144
#endif
145
146
#ifdef __hpux
147
#include <sys/mpctl.h>
148
#endif
149
150
#if defined(__DragonFly__) || \
151
    defined(__OpenBSD__)   || \
152
    defined(__FreeBSD__)   || \
153
    defined(__NetBSD__)    || \
154
    defined(__APPLE__)
155
#include <sys/sysctl.h>
156
#endif
157
158
#ifdef HAVE_LINUX_RANDOM_H
159
#  include <linux/random.h>
160
#endif
161
#ifdef HAVE_GETRANDOM_SYSCALL
162
#  include <sys/syscall.h>
163
#endif
164
165
#if defined(MS_WINDOWS)
166
#  define TERMSIZE_USE_CONIO
167
#elif defined(HAVE_SYS_IOCTL_H)
168
#  include <sys/ioctl.h>
169
#  if defined(HAVE_TERMIOS_H)
170
#    include <termios.h>
171
#  endif
172
#  if defined(TIOCGWINSZ)
173
#    define TERMSIZE_USE_IOCTL
174
#  endif
175
#endif /* MS_WINDOWS */
176
177
/* Various compilers have only certain posix functions */
178
/* XXX Gosh I wish these were all moved into pyconfig.h */
179
#if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
180
#define HAVE_OPENDIR    1
181
#define HAVE_SYSTEM     1
182
#include <process.h>
183
#else
184
#ifdef _MSC_VER         /* Microsoft compiler */
185
#define HAVE_GETPPID    1
186
#define HAVE_GETLOGIN   1
187
#define HAVE_SPAWNV     1
188
#define HAVE_EXECV      1
189
#define HAVE_WSPAWNV    1
190
#define HAVE_WEXECV     1
191
#define HAVE_PIPE       1
192
#define HAVE_SYSTEM     1
193
#define HAVE_CWAIT      1
194
#define HAVE_FSYNC      1
195
#define fsync _commit
196
#else
197
/* Unix functions that the configure script doesn't check for */
198
#ifndef __VXWORKS__
199
#define HAVE_EXECV      1
200
#define HAVE_FORK       1
201
#if defined(__USLC__) && defined(__SCO_VERSION__)       /* SCO UDK Compiler */
202
#define HAVE_FORK1      1
203
#endif
204
#endif
205
#define HAVE_GETEGID    1
206
#define HAVE_GETEUID    1
207
#define HAVE_GETGID     1
208
#define HAVE_GETPPID    1
209
#define HAVE_GETUID     1
210
#define HAVE_KILL       1
211
#define HAVE_OPENDIR    1
212
#define HAVE_PIPE       1
213
#define HAVE_SYSTEM     1
214
#define HAVE_WAIT       1
215
#define HAVE_TTYNAME    1
216
#endif  /* _MSC_VER */
217
#endif  /* ! __WATCOMC__ || __QNX__ */
218
219
220
/*[clinic input]
221
# one of the few times we lie about this name!
222
module os
223
[clinic start generated code]*/
224
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
225
226
#ifndef _MSC_VER
227
228
#if defined(__sgi)&&_COMPILER_VERSION>=700
229
/* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
230
   (default) */
231
extern char        *ctermid_r(char *);
232
#endif
233
234
#endif /* !_MSC_VER */
235
236
#if defined(__VXWORKS__)
237
#include <vxCpuLib.h>
238
#include <rtpLib.h>
239
#include <wait.h>
240
#include <taskLib.h>
241
#ifndef _P_WAIT
242
#define _P_WAIT          0
243
#define _P_NOWAIT        1
244
#define _P_NOWAITO       1
245
#endif
246
#endif /* __VXWORKS__ */
247
248
#ifdef HAVE_POSIX_SPAWN
249
#include <spawn.h>
250
#endif
251
252
#ifdef HAVE_UTIME_H
253
#include <utime.h>
254
#endif /* HAVE_UTIME_H */
255
256
#ifdef HAVE_SYS_UTIME_H
257
#include <sys/utime.h>
258
#define HAVE_UTIME_H /* pretend we do for the rest of this file */
259
#endif /* HAVE_SYS_UTIME_H */
260
261
#ifdef HAVE_SYS_TIMES_H
262
#include <sys/times.h>
263
#endif /* HAVE_SYS_TIMES_H */
264
265
#ifdef HAVE_SYS_PARAM_H
266
#include <sys/param.h>
267
#endif /* HAVE_SYS_PARAM_H */
268
269
#ifdef HAVE_SYS_UTSNAME_H
270
#include <sys/utsname.h>
271
#endif /* HAVE_SYS_UTSNAME_H */
272
273
#ifdef HAVE_DIRENT_H
274
#include <dirent.h>
275
4.71k
#define NAMLEN(dirent) strlen((dirent)->d_name)
276
#else
277
#if defined(__WATCOMC__) && !defined(__QNX__)
278
#include <direct.h>
279
#define NAMLEN(dirent) strlen((dirent)->d_name)
280
#else
281
#define dirent direct
282
#define NAMLEN(dirent) (dirent)->d_namlen
283
#endif
284
#ifdef HAVE_SYS_NDIR_H
285
#include <sys/ndir.h>
286
#endif
287
#ifdef HAVE_SYS_DIR_H
288
#include <sys/dir.h>
289
#endif
290
#ifdef HAVE_NDIR_H
291
#include <ndir.h>
292
#endif
293
#endif
294
295
#ifdef _MSC_VER
296
#ifdef HAVE_DIRECT_H
297
#include <direct.h>
298
#endif
299
#ifdef HAVE_IO_H
300
#include <io.h>
301
#endif
302
#ifdef HAVE_PROCESS_H
303
#include <process.h>
304
#endif
305
#ifndef IO_REPARSE_TAG_SYMLINK
306
#define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
307
#endif
308
#ifndef IO_REPARSE_TAG_MOUNT_POINT
309
#define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
310
#endif
311
#include "osdefs.h"
312
#include <malloc.h>
313
#include <windows.h>
314
#include <shellapi.h>   /* for ShellExecute() */
315
#include <lmcons.h>     /* for UNLEN */
316
#define HAVE_SYMLINK
317
#endif /* _MSC_VER */
318
319
#ifndef MAXPATHLEN
320
#if defined(PATH_MAX) && PATH_MAX > 1024
321
#define MAXPATHLEN PATH_MAX
322
#else
323
#define MAXPATHLEN 1024
324
#endif
325
#endif /* MAXPATHLEN */
326
327
#ifdef UNION_WAIT
328
/* Emulate some macros on systems that have a union instead of macros */
329
330
#ifndef WIFEXITED
331
#define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
332
#endif
333
334
#ifndef WEXITSTATUS
335
#define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
336
#endif
337
338
#ifndef WTERMSIG
339
#define WTERMSIG(u_wait) ((u_wait).w_termsig)
340
#endif
341
342
#define WAIT_TYPE union wait
343
#define WAIT_STATUS_INT(s) (s.w_status)
344
345
#else /* !UNION_WAIT */
346
0
#define WAIT_TYPE int
347
0
#define WAIT_STATUS_INT(s) (s)
348
#endif /* UNION_WAIT */
349
350
/* Don't use the "_r" form if we don't need it (also, won't have a
351
   prototype for it, at least on Solaris -- maybe others as well?). */
352
#if defined(HAVE_CTERMID_R)
353
#define USE_CTERMID_R
354
#endif
355
356
/* choose the appropriate stat and fstat functions and return structs */
357
#undef STAT
358
#undef FSTAT
359
#undef STRUCT_STAT
360
#ifdef MS_WINDOWS
361
#       define STAT win32_stat
362
#       define LSTAT win32_lstat
363
#       define FSTAT _Py_fstat_noraise
364
#       define STRUCT_STAT struct _Py_stat_struct
365
#else
366
1.08k
#       define STAT stat
367
0
#       define LSTAT lstat
368
0
#       define FSTAT fstat
369
1.08k
#       define STRUCT_STAT struct stat
370
#endif
371
372
#if defined(MAJOR_IN_MKDEV)
373
#include <sys/mkdev.h>
374
#else
375
#if defined(MAJOR_IN_SYSMACROS)
376
#include <sys/sysmacros.h>
377
#endif
378
#if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
379
#include <sys/mkdev.h>
380
#endif
381
#endif
382
383
#ifdef MS_WINDOWS
384
#define INITFUNC PyInit_nt
385
#define MODNAME "nt"
386
#else
387
#define INITFUNC PyInit_posix
388
56
#define MODNAME "posix"
389
#endif
390
391
#if defined(__sun)
392
/* Something to implement in autoconf, not present in autoconf 2.69 */
393
#define HAVE_STRUCT_STAT_ST_FSTYPE 1
394
#endif
395
396
/* memfd_create is either defined in sys/mman.h or sys/memfd.h
397
 * linux/memfd.h defines additional flags
398
 */
399
#ifdef HAVE_SYS_MMAN_H
400
#include <sys/mman.h>
401
#endif
402
#ifdef HAVE_SYS_MEMFD_H
403
#include <sys/memfd.h>
404
#endif
405
#ifdef HAVE_LINUX_MEMFD_H
406
#include <linux/memfd.h>
407
#endif
408
409
#ifdef _Py_MEMORY_SANITIZER
410
# include <sanitizer/msan_interface.h>
411
#endif
412
413
#ifdef HAVE_FORK
414
static void
415
run_at_forkers(PyObject *lst, int reverse)
416
0
{
417
0
    Py_ssize_t i;
418
0
    PyObject *cpy;
419
420
0
    if (lst != NULL) {
421
0
        assert(PyList_CheckExact(lst));
422
423
        /* Use a list copy in case register_at_fork() is called from
424
         * one of the callbacks.
425
         */
426
0
        cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
427
0
        if (cpy == NULL)
428
0
            PyErr_WriteUnraisable(lst);
429
0
        else {
430
0
            if (reverse)
431
0
                PyList_Reverse(cpy);
432
0
            for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
433
0
                PyObject *func, *res;
434
0
                func = PyList_GET_ITEM(cpy, i);
435
0
                res = PyObject_CallObject(func, NULL);
436
0
                if (res == NULL)
437
0
                    PyErr_WriteUnraisable(func);
438
0
                else
439
0
                    Py_DECREF(res);
440
0
            }
441
0
            Py_DECREF(cpy);
442
0
        }
443
0
    }
444
0
}
445
446
void
447
PyOS_BeforeFork(void)
448
0
{
449
0
    run_at_forkers(_PyInterpreterState_Get()->before_forkers, 1);
450
451
0
    _PyImport_AcquireLock();
452
0
}
453
454
void
455
PyOS_AfterFork_Parent(void)
456
0
{
457
0
    if (_PyImport_ReleaseLock() <= 0)
458
0
        Py_FatalError("failed releasing import lock after fork");
459
460
0
    run_at_forkers(_PyInterpreterState_Get()->after_forkers_parent, 0);
461
0
}
462
463
void
464
PyOS_AfterFork_Child(void)
465
0
{
466
0
    _PyRuntimeState *runtime = &_PyRuntime;
467
0
    _PyGILState_Reinit(runtime);
468
0
    _PyEval_ReInitThreads(runtime);
469
0
    _PyImport_ReInitLock();
470
0
    _PySignal_AfterFork();
471
0
    _PyRuntimeState_ReInitThreads(runtime);
472
0
    _PyInterpreterState_DeleteExceptMain(runtime);
473
474
0
    run_at_forkers(_PyInterpreterState_Get()->after_forkers_child, 0);
475
0
}
476
477
static int
478
register_at_forker(PyObject **lst, PyObject *func)
479
6
{
480
6
    if (func == NULL)  /* nothing to register? do nothing. */
481
2
        return 0;
482
4
    if (*lst == NULL) {
483
3
        *lst = PyList_New(0);
484
3
        if (*lst == NULL)
485
0
            return -1;
486
3
    }
487
4
    return PyList_Append(*lst, func);
488
4
}
489
#endif
490
491
/* Legacy wrapper */
492
void
493
PyOS_AfterFork(void)
494
0
{
495
0
#ifdef HAVE_FORK
496
0
    PyOS_AfterFork_Child();
497
0
#endif
498
0
}
499
500
501
#ifdef MS_WINDOWS
502
/* defined in fileutils.c */
503
void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
504
void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,
505
                                            ULONG, struct _Py_stat_struct *);
506
#endif
507
508
509
#ifndef MS_WINDOWS
510
PyObject *
511
_PyLong_FromUid(uid_t uid)
512
854
{
513
854
    if (uid == (uid_t)-1)
514
0
        return PyLong_FromLong(-1);
515
854
    return PyLong_FromUnsignedLong(uid);
516
854
}
517
518
PyObject *
519
_PyLong_FromGid(gid_t gid)
520
854
{
521
854
    if (gid == (gid_t)-1)
522
0
        return PyLong_FromLong(-1);
523
854
    return PyLong_FromUnsignedLong(gid);
524
854
}
525
526
int
527
_Py_Uid_Converter(PyObject *obj, void *p)
528
0
{
529
0
    uid_t uid;
530
0
    PyObject *index;
531
0
    int overflow;
532
0
    long result;
533
0
    unsigned long uresult;
534
535
0
    index = PyNumber_Index(obj);
536
0
    if (index == NULL) {
537
0
        PyErr_Format(PyExc_TypeError,
538
0
                     "uid should be integer, not %.200s",
539
0
                     Py_TYPE(obj)->tp_name);
540
0
        return 0;
541
0
    }
542
543
    /*
544
     * Handling uid_t is complicated for two reasons:
545
     *  * Although uid_t is (always?) unsigned, it still
546
     *    accepts -1.
547
     *  * We don't know its size in advance--it may be
548
     *    bigger than an int, or it may be smaller than
549
     *    a long.
550
     *
551
     * So a bit of defensive programming is in order.
552
     * Start with interpreting the value passed
553
     * in as a signed long and see if it works.
554
     */
555
556
0
    result = PyLong_AsLongAndOverflow(index, &overflow);
557
558
0
    if (!overflow) {
559
0
        uid = (uid_t)result;
560
561
0
        if (result == -1) {
562
0
            if (PyErr_Occurred())
563
0
                goto fail;
564
            /* It's a legitimate -1, we're done. */
565
0
            goto success;
566
0
        }
567
568
        /* Any other negative number is disallowed. */
569
0
        if (result < 0)
570
0
            goto underflow;
571
572
        /* Ensure the value wasn't truncated. */
573
0
        if (sizeof(uid_t) < sizeof(long) &&
574
0
            (long)uid != result)
575
0
            goto underflow;
576
0
        goto success;
577
0
    }
578
579
0
    if (overflow < 0)
580
0
        goto underflow;
581
582
    /*
583
     * Okay, the value overflowed a signed long.  If it
584
     * fits in an *unsigned* long, it may still be okay,
585
     * as uid_t may be unsigned long on this platform.
586
     */
587
0
    uresult = PyLong_AsUnsignedLong(index);
588
0
    if (PyErr_Occurred()) {
589
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError))
590
0
            goto overflow;
591
0
        goto fail;
592
0
    }
593
594
0
    uid = (uid_t)uresult;
595
596
    /*
597
     * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
598
     * but this value would get interpreted as (uid_t)-1  by chown
599
     * and its siblings.   That's not what the user meant!  So we
600
     * throw an overflow exception instead.   (We already
601
     * handled a real -1 with PyLong_AsLongAndOverflow() above.)
602
     */
603
0
    if (uid == (uid_t)-1)
604
0
        goto overflow;
605
606
    /* Ensure the value wasn't truncated. */
607
0
    if (sizeof(uid_t) < sizeof(long) &&
608
0
        (unsigned long)uid != uresult)
609
0
        goto overflow;
610
    /* fallthrough */
611
612
0
success:
613
0
    Py_DECREF(index);
614
0
    *(uid_t *)p = uid;
615
0
    return 1;
616
617
0
underflow:
618
0
    PyErr_SetString(PyExc_OverflowError,
619
0
                    "uid is less than minimum");
620
0
    goto fail;
621
622
0
overflow:
623
0
    PyErr_SetString(PyExc_OverflowError,
624
0
                    "uid is greater than maximum");
625
    /* fallthrough */
626
627
0
fail:
628
0
    Py_DECREF(index);
629
0
    return 0;
630
0
}
631
632
int
633
_Py_Gid_Converter(PyObject *obj, void *p)
634
0
{
635
0
    gid_t gid;
636
0
    PyObject *index;
637
0
    int overflow;
638
0
    long result;
639
0
    unsigned long uresult;
640
641
0
    index = PyNumber_Index(obj);
642
0
    if (index == NULL) {
643
0
        PyErr_Format(PyExc_TypeError,
644
0
                     "gid should be integer, not %.200s",
645
0
                     Py_TYPE(obj)->tp_name);
646
0
        return 0;
647
0
    }
648
649
    /*
650
     * Handling gid_t is complicated for two reasons:
651
     *  * Although gid_t is (always?) unsigned, it still
652
     *    accepts -1.
653
     *  * We don't know its size in advance--it may be
654
     *    bigger than an int, or it may be smaller than
655
     *    a long.
656
     *
657
     * So a bit of defensive programming is in order.
658
     * Start with interpreting the value passed
659
     * in as a signed long and see if it works.
660
     */
661
662
0
    result = PyLong_AsLongAndOverflow(index, &overflow);
663
664
0
    if (!overflow) {
665
0
        gid = (gid_t)result;
666
667
0
        if (result == -1) {
668
0
            if (PyErr_Occurred())
669
0
                goto fail;
670
            /* It's a legitimate -1, we're done. */
671
0
            goto success;
672
0
        }
673
674
        /* Any other negative number is disallowed. */
675
0
        if (result < 0) {
676
0
            goto underflow;
677
0
        }
678
679
        /* Ensure the value wasn't truncated. */
680
0
        if (sizeof(gid_t) < sizeof(long) &&
681
0
            (long)gid != result)
682
0
            goto underflow;
683
0
        goto success;
684
0
    }
685
686
0
    if (overflow < 0)
687
0
        goto underflow;
688
689
    /*
690
     * Okay, the value overflowed a signed long.  If it
691
     * fits in an *unsigned* long, it may still be okay,
692
     * as gid_t may be unsigned long on this platform.
693
     */
694
0
    uresult = PyLong_AsUnsignedLong(index);
695
0
    if (PyErr_Occurred()) {
696
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError))
697
0
            goto overflow;
698
0
        goto fail;
699
0
    }
700
701
0
    gid = (gid_t)uresult;
702
703
    /*
704
     * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
705
     * but this value would get interpreted as (gid_t)-1  by chown
706
     * and its siblings.   That's not what the user meant!  So we
707
     * throw an overflow exception instead.   (We already
708
     * handled a real -1 with PyLong_AsLongAndOverflow() above.)
709
     */
710
0
    if (gid == (gid_t)-1)
711
0
        goto overflow;
712
713
    /* Ensure the value wasn't truncated. */
714
0
    if (sizeof(gid_t) < sizeof(long) &&
715
0
        (unsigned long)gid != uresult)
716
0
        goto overflow;
717
    /* fallthrough */
718
719
0
success:
720
0
    Py_DECREF(index);
721
0
    *(gid_t *)p = gid;
722
0
    return 1;
723
724
0
underflow:
725
0
    PyErr_SetString(PyExc_OverflowError,
726
0
                    "gid is less than minimum");
727
0
    goto fail;
728
729
0
overflow:
730
0
    PyErr_SetString(PyExc_OverflowError,
731
0
                    "gid is greater than maximum");
732
    /* fallthrough */
733
734
0
fail:
735
0
    Py_DECREF(index);
736
0
    return 0;
737
0
}
738
#endif /* MS_WINDOWS */
739
740
741
0
#define _PyLong_FromDev PyLong_FromLongLong
742
743
744
#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
745
static int
746
_Py_Dev_Converter(PyObject *obj, void *p)
747
0
{
748
0
    *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj);
749
0
    if (PyErr_Occurred())
750
0
        return 0;
751
0
    return 1;
752
0
}
753
#endif /* HAVE_MKNOD && HAVE_MAKEDEV */
754
755
756
#ifdef AT_FDCWD
757
/*
758
 * Why the (int) cast?  Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
759
 * without the int cast, the value gets interpreted as uint (4291925331),
760
 * which doesn't play nicely with all the initializer lines in this file that
761
 * look like this:
762
 *      int dir_fd = DEFAULT_DIR_FD;
763
 */
764
4.40k
#define DEFAULT_DIR_FD (int)AT_FDCWD
765
#else
766
#define DEFAULT_DIR_FD (-100)
767
#endif
768
769
static int
770
_fd_converter(PyObject *o, int *p)
771
0
{
772
0
    int overflow;
773
0
    long long_value;
774
775
0
    PyObject *index = PyNumber_Index(o);
776
0
    if (index == NULL) {
777
0
        return 0;
778
0
    }
779
780
0
    assert(PyLong_Check(index));
781
0
    long_value = PyLong_AsLongAndOverflow(index, &overflow);
782
0
    Py_DECREF(index);
783
0
    assert(!PyErr_Occurred());
784
0
    if (overflow > 0 || long_value > INT_MAX) {
785
0
        PyErr_SetString(PyExc_OverflowError,
786
0
                        "fd is greater than maximum");
787
0
        return 0;
788
0
    }
789
0
    if (overflow < 0 || long_value < INT_MIN) {
790
0
        PyErr_SetString(PyExc_OverflowError,
791
0
                        "fd is less than minimum");
792
0
        return 0;
793
0
    }
794
795
0
    *p = (int)long_value;
796
0
    return 1;
797
0
}
798
799
static int
800
dir_fd_converter(PyObject *o, void *p)
801
28
{
802
28
    if (o == Py_None) {
803
28
        *(int *)p = DEFAULT_DIR_FD;
804
28
        return 1;
805
28
    }
806
0
    else if (PyIndex_Check(o)) {
807
0
        return _fd_converter(o, (int *)p);
808
0
    }
809
0
    else {
810
0
        PyErr_Format(PyExc_TypeError,
811
0
                     "argument should be integer or None, not %.200s",
812
0
                     Py_TYPE(o)->tp_name);
813
0
        return 0;
814
0
    }
815
28
}
816
817
818
/*
819
 * A PyArg_ParseTuple "converter" function
820
 * that handles filesystem paths in the manner
821
 * preferred by the os module.
822
 *
823
 * path_converter accepts (Unicode) strings and their
824
 * subclasses, and bytes and their subclasses.  What
825
 * it does with the argument depends on the platform:
826
 *
827
 *   * On Windows, if we get a (Unicode) string we
828
 *     extract the wchar_t * and return it; if we get
829
 *     bytes we decode to wchar_t * and return that.
830
 *
831
 *   * On all other platforms, strings are encoded
832
 *     to bytes using PyUnicode_FSConverter, then we
833
 *     extract the char * from the bytes object and
834
 *     return that.
835
 *
836
 * path_converter also optionally accepts signed
837
 * integers (representing open file descriptors) instead
838
 * of path strings.
839
 *
840
 * Input fields:
841
 *   path.nullable
842
 *     If nonzero, the path is permitted to be None.
843
 *   path.allow_fd
844
 *     If nonzero, the path is permitted to be a file handle
845
 *     (a signed int) instead of a string.
846
 *   path.function_name
847
 *     If non-NULL, path_converter will use that as the name
848
 *     of the function in error messages.
849
 *     (If path.function_name is NULL it omits the function name.)
850
 *   path.argument_name
851
 *     If non-NULL, path_converter will use that as the name
852
 *     of the parameter in error messages.
853
 *     (If path.argument_name is NULL it uses "path".)
854
 *
855
 * Output fields:
856
 *   path.wide
857
 *     Points to the path if it was expressed as Unicode
858
 *     and was not encoded.  (Only used on Windows.)
859
 *   path.narrow
860
 *     Points to the path if it was expressed as bytes,
861
 *     or it was Unicode and was encoded to bytes. (On Windows,
862
 *     is a non-zero integer if the path was expressed as bytes.
863
 *     The type is deliberately incompatible to prevent misuse.)
864
 *   path.fd
865
 *     Contains a file descriptor if path.accept_fd was true
866
 *     and the caller provided a signed integer instead of any
867
 *     sort of string.
868
 *
869
 *     WARNING: if your "path" parameter is optional, and is
870
 *     unspecified, path_converter will never get called.
871
 *     So if you set allow_fd, you *MUST* initialize path.fd = -1
872
 *     yourself!
873
 *   path.length
874
 *     The length of the path in characters, if specified as
875
 *     a string.
876
 *   path.object
877
 *     The original object passed in (if get a PathLike object,
878
 *     the result of PyOS_FSPath() is treated as the original object).
879
 *     Own a reference to the object.
880
 *   path.cleanup
881
 *     For internal use only.  May point to a temporary object.
882
 *     (Pay no attention to the man behind the curtain.)
883
 *
884
 *   At most one of path.wide or path.narrow will be non-NULL.
885
 *   If path was None and path.nullable was set,
886
 *     or if path was an integer and path.allow_fd was set,
887
 *     both path.wide and path.narrow will be NULL
888
 *     and path.length will be 0.
889
 *
890
 *   path_converter takes care to not write to the path_t
891
 *   unless it's successful.  However it must reset the
892
 *   "cleanup" field each time it's called.
893
 *
894
 * Use as follows:
895
 *      path_t path;
896
 *      memset(&path, 0, sizeof(path));
897
 *      PyArg_ParseTuple(args, "O&", path_converter, &path);
898
 *      // ... use values from path ...
899
 *      path_cleanup(&path);
900
 *
901
 * (Note that if PyArg_Parse fails you don't need to call
902
 * path_cleanup().  However it is safe to do so.)
903
 */
904
typedef struct {
905
    const char *function_name;
906
    const char *argument_name;
907
    int nullable;
908
    int allow_fd;
909
    const wchar_t *wide;
910
#ifdef MS_WINDOWS
911
    BOOL narrow;
912
#else
913
    const char *narrow;
914
#endif
915
    int fd;
916
    Py_ssize_t length;
917
    PyObject *object;
918
    PyObject *cleanup;
919
} path_t;
920
921
#ifdef MS_WINDOWS
922
#define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
923
    {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL}
924
#else
925
#define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
926
1.11k
    {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL}
927
#endif
928
929
static void
930
path_cleanup(path_t *path)
931
1.11k
{
932
1.11k
    Py_CLEAR(path->object);
933
1.11k
    Py_CLEAR(path->cleanup);
934
1.11k
}
935
936
static int
937
path_converter(PyObject *o, void *p)
938
1.11k
{
939
1.11k
    path_t *path = (path_t *)p;
940
1.11k
    PyObject *bytes = NULL;
941
1.11k
    Py_ssize_t length = 0;
942
1.11k
    int is_index, is_buffer, is_bytes, is_unicode;
943
1.11k
    const char *narrow;
944
#ifdef MS_WINDOWS
945
    PyObject *wo = NULL;
946
    const wchar_t *wide;
947
#endif
948
949
1.11k
#define FORMAT_EXCEPTION(exc, fmt) \
950
1.11k
    PyErr_Format(exc, "%s%s" fmt, \
951
0
        path->function_name ? path->function_name : "", \
952
0
        path->function_name ? ": "                : "", \
953
0
        path->argument_name ? path->argument_name : "path")
954
955
    /* Py_CLEANUP_SUPPORTED support */
956
1.11k
    if (o == NULL) {
957
0
        path_cleanup(path);
958
0
        return 1;
959
0
    }
960
961
    /* Ensure it's always safe to call path_cleanup(). */
962
1.11k
    path->object = path->cleanup = NULL;
963
    /* path->object owns a reference to the original object */
964
1.11k
    Py_INCREF(o);
965
966
1.11k
    if ((o == Py_None) && path->nullable) {
967
0
        path->wide = NULL;
968
#ifdef MS_WINDOWS
969
        path->narrow = FALSE;
970
#else
971
0
        path->narrow = NULL;
972
0
#endif
973
0
        path->fd = -1;
974
0
        goto success_exit;
975
0
    }
976
977
    /* Only call this here so that we don't treat the return value of
978
       os.fspath() as an fd or buffer. */
979
1.11k
    is_index = path->allow_fd && PyIndex_Check(o);
980
1.11k
    is_buffer = PyObject_CheckBuffer(o);
981
1.11k
    is_bytes = PyBytes_Check(o);
982
1.11k
    is_unicode = PyUnicode_Check(o);
983
984
1.11k
    if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
985
        /* Inline PyOS_FSPath() for better error messages. */
986
0
        _Py_IDENTIFIER(__fspath__);
987
0
        PyObject *func, *res;
988
989
0
        func = _PyObject_LookupSpecial(o, &PyId___fspath__);
990
0
        if (NULL == func) {
991
0
            goto error_format;
992
0
        }
993
0
        res = _PyObject_CallNoArg(func);
994
0
        Py_DECREF(func);
995
0
        if (NULL == res) {
996
0
            goto error_exit;
997
0
        }
998
0
        else if (PyUnicode_Check(res)) {
999
0
            is_unicode = 1;
1000
0
        }
1001
0
        else if (PyBytes_Check(res)) {
1002
0
            is_bytes = 1;
1003
0
        }
1004
0
        else {
1005
0
            PyErr_Format(PyExc_TypeError,
1006
0
                 "expected %.200s.__fspath__() to return str or bytes, "
1007
0
                 "not %.200s", Py_TYPE(o)->tp_name,
1008
0
                 Py_TYPE(res)->tp_name);
1009
0
            Py_DECREF(res);
1010
0
            goto error_exit;
1011
0
        }
1012
1013
        /* still owns a reference to the original object */
1014
0
        Py_DECREF(o);
1015
0
        o = res;
1016
0
    }
1017
1018
1.11k
    if (is_unicode) {
1019
#ifdef MS_WINDOWS
1020
        wide = PyUnicode_AsUnicodeAndSize(o, &length);
1021
        if (!wide) {
1022
            goto error_exit;
1023
        }
1024
        if (length > 32767) {
1025
            FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1026
            goto error_exit;
1027
        }
1028
        if (wcslen(wide) != length) {
1029
            FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1030
            goto error_exit;
1031
        }
1032
1033
        path->wide = wide;
1034
        path->narrow = FALSE;
1035
        path->fd = -1;
1036
        goto success_exit;
1037
#else
1038
1.11k
        if (!PyUnicode_FSConverter(o, &bytes)) {
1039
0
            goto error_exit;
1040
0
        }
1041
1.11k
#endif
1042
1.11k
    }
1043
0
    else if (is_bytes) {
1044
0
        bytes = o;
1045
0
        Py_INCREF(bytes);
1046
0
    }
1047
0
    else if (is_buffer) {
1048
        /* XXX Replace PyObject_CheckBuffer with PyBytes_Check in other code
1049
           after removing support of non-bytes buffer objects. */
1050
0
        if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
1051
0
            "%s%s%s should be %s, not %.200s",
1052
0
            path->function_name ? path->function_name : "",
1053
0
            path->function_name ? ": "                : "",
1054
0
            path->argument_name ? path->argument_name : "path",
1055
0
            path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1056
0
                                               "integer or None" :
1057
0
            path->allow_fd ? "string, bytes, os.PathLike or integer" :
1058
0
            path->nullable ? "string, bytes, os.PathLike or None" :
1059
0
                             "string, bytes or os.PathLike",
1060
0
            Py_TYPE(o)->tp_name)) {
1061
0
            goto error_exit;
1062
0
        }
1063
0
        bytes = PyBytes_FromObject(o);
1064
0
        if (!bytes) {
1065
0
            goto error_exit;
1066
0
        }
1067
0
    }
1068
0
    else if (is_index) {
1069
0
        if (!_fd_converter(o, &path->fd)) {
1070
0
            goto error_exit;
1071
0
        }
1072
0
        path->wide = NULL;
1073
#ifdef MS_WINDOWS
1074
        path->narrow = FALSE;
1075
#else
1076
0
        path->narrow = NULL;
1077
0
#endif
1078
0
        goto success_exit;
1079
0
    }
1080
0
    else {
1081
0
 error_format:
1082
0
        PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1083
0
            path->function_name ? path->function_name : "",
1084
0
            path->function_name ? ": "                : "",
1085
0
            path->argument_name ? path->argument_name : "path",
1086
0
            path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1087
0
                                               "integer or None" :
1088
0
            path->allow_fd ? "string, bytes, os.PathLike or integer" :
1089
0
            path->nullable ? "string, bytes, os.PathLike or None" :
1090
0
                             "string, bytes or os.PathLike",
1091
0
            Py_TYPE(o)->tp_name);
1092
0
        goto error_exit;
1093
0
    }
1094
1095
1.11k
    length = PyBytes_GET_SIZE(bytes);
1096
1.11k
    narrow = PyBytes_AS_STRING(bytes);
1097
1.11k
    if ((size_t)length != strlen(narrow)) {
1098
0
        FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1099
0
        goto error_exit;
1100
0
    }
1101
1102
#ifdef MS_WINDOWS
1103
    wo = PyUnicode_DecodeFSDefaultAndSize(
1104
        narrow,
1105
        length
1106
    );
1107
    if (!wo) {
1108
        goto error_exit;
1109
    }
1110
1111
    wide = PyUnicode_AsUnicodeAndSize(wo, &length);
1112
    if (!wide) {
1113
        goto error_exit;
1114
    }
1115
    if (length > 32767) {
1116
        FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1117
        goto error_exit;
1118
    }
1119
    if (wcslen(wide) != length) {
1120
        FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1121
        goto error_exit;
1122
    }
1123
    path->wide = wide;
1124
    path->narrow = TRUE;
1125
    path->cleanup = wo;
1126
    Py_DECREF(bytes);
1127
#else
1128
1.11k
    path->wide = NULL;
1129
1.11k
    path->narrow = narrow;
1130
1.11k
    if (bytes == o) {
1131
        /* Still a reference owned by path->object, don't have to
1132
           worry about path->narrow is used after free. */
1133
0
        Py_DECREF(bytes);
1134
0
    }
1135
1.11k
    else {
1136
1.11k
        path->cleanup = bytes;
1137
1.11k
    }
1138
1.11k
#endif
1139
1.11k
    path->fd = -1;
1140
1141
1.11k
 success_exit:
1142
1.11k
    path->length = length;
1143
1.11k
    path->object = o;
1144
1.11k
    return Py_CLEANUP_SUPPORTED;
1145
1146
0
 error_exit:
1147
0
    Py_XDECREF(o);
1148
0
    Py_XDECREF(bytes);
1149
#ifdef MS_WINDOWS
1150
    Py_XDECREF(wo);
1151
#endif
1152
0
    return 0;
1153
1.11k
}
1154
1155
static void
1156
argument_unavailable_error(const char *function_name, const char *argument_name)
1157
0
{
1158
0
    PyErr_Format(PyExc_NotImplementedError,
1159
0
        "%s%s%s unavailable on this platform",
1160
0
        (function_name != NULL) ? function_name : "",
1161
0
        (function_name != NULL) ? ": ": "",
1162
0
        argument_name);
1163
0
}
1164
1165
static int
1166
dir_fd_unavailable(PyObject *o, void *p)
1167
14
{
1168
14
    int dir_fd;
1169
14
    if (!dir_fd_converter(o, &dir_fd))
1170
0
        return 0;
1171
14
    if (dir_fd != DEFAULT_DIR_FD) {
1172
0
        argument_unavailable_error(NULL, "dir_fd");
1173
0
        return 0;
1174
0
    }
1175
14
    *(int *)p = dir_fd;
1176
14
    return 1;
1177
14
}
1178
1179
static int
1180
fd_specified(const char *function_name, int fd)
1181
14
{
1182
14
    if (fd == -1)
1183
14
        return 0;
1184
1185
0
    argument_unavailable_error(function_name, "fd");
1186
0
    return 1;
1187
14
}
1188
1189
static int
1190
follow_symlinks_specified(const char *function_name, int follow_symlinks)
1191
14
{
1192
14
    if (follow_symlinks)
1193
14
        return 0;
1194
1195
0
    argument_unavailable_error(function_name, "follow_symlinks");
1196
0
    return 1;
1197
14
}
1198
1199
static int
1200
path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1201
1.08k
{
1202
1.08k
    if (!path->wide && (dir_fd != DEFAULT_DIR_FD)
1203
1.08k
#ifndef MS_WINDOWS
1204
1.08k
        && !path->narrow
1205
1.08k
#endif
1206
1.08k
    ) {
1207
0
        PyErr_Format(PyExc_ValueError,
1208
0
                     "%s: can't specify dir_fd without matching path",
1209
0
                     function_name);
1210
0
        return 1;
1211
0
    }
1212
1.08k
    return 0;
1213
1.08k
}
1214
1215
static int
1216
dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1217
1.08k
{
1218
1.08k
    if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1219
0
        PyErr_Format(PyExc_ValueError,
1220
0
                     "%s: can't specify both dir_fd and fd",
1221
0
                     function_name);
1222
0
        return 1;
1223
0
    }
1224
1.08k
    return 0;
1225
1.08k
}
1226
1227
static int
1228
fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1229
                               int follow_symlinks)
1230
1.08k
{
1231
1.08k
    if ((fd > 0) && (!follow_symlinks)) {
1232
0
        PyErr_Format(PyExc_ValueError,
1233
0
                     "%s: cannot use fd and follow_symlinks together",
1234
0
                     function_name);
1235
0
        return 1;
1236
0
    }
1237
1.08k
    return 0;
1238
1.08k
}
1239
1240
static int
1241
dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1242
                                   int follow_symlinks)
1243
14
{
1244
14
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1245
0
        PyErr_Format(PyExc_ValueError,
1246
0
                     "%s: cannot use dir_fd and follow_symlinks together",
1247
0
                     function_name);
1248
0
        return 1;
1249
0
    }
1250
14
    return 0;
1251
14
}
1252
1253
#ifdef MS_WINDOWS
1254
    typedef long long Py_off_t;
1255
#else
1256
    typedef off_t Py_off_t;
1257
#endif
1258
1259
static int
1260
Py_off_t_converter(PyObject *arg, void *addr)
1261
0
{
1262
#ifdef HAVE_LARGEFILE_SUPPORT
1263
    *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1264
#else
1265
0
    *((Py_off_t *)addr) = PyLong_AsLong(arg);
1266
0
#endif
1267
0
    if (PyErr_Occurred())
1268
0
        return 0;
1269
0
    return 1;
1270
0
}
1271
1272
static PyObject *
1273
PyLong_FromPy_off_t(Py_off_t offset)
1274
0
{
1275
#ifdef HAVE_LARGEFILE_SUPPORT
1276
    return PyLong_FromLongLong(offset);
1277
#else
1278
0
    return PyLong_FromLong(offset);
1279
0
#endif
1280
0
}
1281
1282
#ifdef HAVE_SIGSET_T
1283
/* Convert an iterable of integers to a sigset.
1284
   Return 1 on success, return 0 and raise an exception on error. */
1285
int
1286
_Py_Sigset_Converter(PyObject *obj, void *addr)
1287
0
{
1288
0
    sigset_t *mask = (sigset_t *)addr;
1289
0
    PyObject *iterator, *item;
1290
0
    long signum;
1291
0
    int overflow;
1292
1293
    // The extra parens suppress the unreachable-code warning with clang on MacOS
1294
0
    if (sigemptyset(mask) < (0)) {
1295
        /* Probably only if mask == NULL. */
1296
0
        PyErr_SetFromErrno(PyExc_OSError);
1297
0
        return 0;
1298
0
    }
1299
1300
0
    iterator = PyObject_GetIter(obj);
1301
0
    if (iterator == NULL) {
1302
0
        return 0;
1303
0
    }
1304
1305
0
    while ((item = PyIter_Next(iterator)) != NULL) {
1306
0
        signum = PyLong_AsLongAndOverflow(item, &overflow);
1307
0
        Py_DECREF(item);
1308
0
        if (signum <= 0 || signum >= NSIG) {
1309
0
            if (overflow || signum != -1 || !PyErr_Occurred()) {
1310
0
                PyErr_Format(PyExc_ValueError,
1311
0
                             "signal number %ld out of range", signum);
1312
0
            }
1313
0
            goto error;
1314
0
        }
1315
0
        if (sigaddset(mask, (int)signum)) {
1316
0
            if (errno != EINVAL) {
1317
                /* Probably impossible */
1318
0
                PyErr_SetFromErrno(PyExc_OSError);
1319
0
                goto error;
1320
0
            }
1321
            /* For backwards compatibility, allow idioms such as
1322
             * `range(1, NSIG)` but warn about invalid signal numbers
1323
             */
1324
0
            const char msg[] =
1325
0
                "invalid signal number %ld, please use valid_signals()";
1326
0
            if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1327
0
                goto error;
1328
0
            }
1329
0
        }
1330
0
    }
1331
0
    if (!PyErr_Occurred()) {
1332
0
        Py_DECREF(iterator);
1333
0
        return 1;
1334
0
    }
1335
1336
0
error:
1337
0
    Py_DECREF(iterator);
1338
0
    return 0;
1339
0
}
1340
#endif /* HAVE_SIGSET_T */
1341
1342
#ifdef MS_WINDOWS
1343
1344
static int
1345
win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
1346
{
1347
    char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
1348
    _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
1349
    DWORD n_bytes_returned;
1350
1351
    if (0 == DeviceIoControl(
1352
        reparse_point_handle,
1353
        FSCTL_GET_REPARSE_POINT,
1354
        NULL, 0, /* in buffer */
1355
        target_buffer, sizeof(target_buffer),
1356
        &n_bytes_returned,
1357
        NULL)) /* we're not using OVERLAPPED_IO */
1358
        return FALSE;
1359
1360
    if (reparse_tag)
1361
        *reparse_tag = rdb->ReparseTag;
1362
1363
    return TRUE;
1364
}
1365
1366
#endif /* MS_WINDOWS */
1367
1368
/* Return a dictionary corresponding to the POSIX environment table */
1369
#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1370
/* On Darwin/MacOSX a shared library or framework has no access to
1371
** environ directly, we must obtain it with _NSGetEnviron(). See also
1372
** man environ(7).
1373
*/
1374
#include <crt_externs.h>
1375
#elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1376
extern char **environ;
1377
#endif /* !_MSC_VER */
1378
1379
static PyObject *
1380
convertenviron(void)
1381
14
{
1382
14
    PyObject *d;
1383
#ifdef MS_WINDOWS
1384
    wchar_t **e;
1385
#else
1386
14
    char **e;
1387
14
#endif
1388
1389
14
    d = PyDict_New();
1390
14
    if (d == NULL)
1391
0
        return NULL;
1392
#ifdef MS_WINDOWS
1393
    /* _wenviron must be initialized in this way if the program is started
1394
       through main() instead of wmain(). */
1395
    _wgetenv(L"");
1396
    e = _wenviron;
1397
#elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1398
    /* environ is not accessible as an extern in a shared object on OSX; use
1399
       _NSGetEnviron to resolve it. The value changes if you add environment
1400
       variables between calls to Py_Initialize, so don't cache the value. */
1401
    e = *_NSGetEnviron();
1402
#else
1403
14
    e = environ;
1404
14
#endif
1405
14
    if (e == NULL)
1406
0
        return d;
1407
546
    for (; *e != NULL; e++) {
1408
532
        PyObject *k;
1409
532
        PyObject *v;
1410
#ifdef MS_WINDOWS
1411
        const wchar_t *p = wcschr(*e, L'=');
1412
#else
1413
532
        const char *p = strchr(*e, '=');
1414
532
#endif
1415
532
        if (p == NULL)
1416
0
            continue;
1417
#ifdef MS_WINDOWS
1418
        k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1419
#else
1420
532
        k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1421
532
#endif
1422
532
        if (k == NULL) {
1423
0
            Py_DECREF(d);
1424
0
            return NULL;
1425
0
        }
1426
#ifdef MS_WINDOWS
1427
        v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
1428
#else
1429
532
        v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1430
532
#endif
1431
532
        if (v == NULL) {
1432
0
            Py_DECREF(k);
1433
0
            Py_DECREF(d);
1434
0
            return NULL;
1435
0
        }
1436
532
        if (PyDict_GetItemWithError(d, k) == NULL) {
1437
532
            if (PyErr_Occurred() || PyDict_SetItem(d, k, v) != 0) {
1438
0
                Py_DECREF(v);
1439
0
                Py_DECREF(k);
1440
0
                Py_DECREF(d);
1441
0
                return NULL;
1442
0
            }
1443
532
        }
1444
532
        Py_DECREF(k);
1445
532
        Py_DECREF(v);
1446
532
    }
1447
14
    return d;
1448
14
}
1449
1450
/* Set a POSIX-specific error from errno, and return NULL */
1451
1452
static PyObject *
1453
posix_error(void)
1454
0
{
1455
0
    return PyErr_SetFromErrno(PyExc_OSError);
1456
0
}
1457
1458
#ifdef MS_WINDOWS
1459
static PyObject *
1460
win32_error(const char* function, const char* filename)
1461
{
1462
    /* XXX We should pass the function name along in the future.
1463
       (winreg.c also wants to pass the function name.)
1464
       This would however require an additional param to the
1465
       Windows error object, which is non-trivial.
1466
    */
1467
    errno = GetLastError();
1468
    if (filename)
1469
        return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1470
    else
1471
        return PyErr_SetFromWindowsErr(errno);
1472
}
1473
1474
static PyObject *
1475
win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1476
{
1477
    /* XXX - see win32_error for comments on 'function' */
1478
    if (filename)
1479
        return PyErr_SetExcFromWindowsErrWithFilenameObject(
1480
                    PyExc_OSError,
1481
                    err,
1482
                    filename);
1483
    else
1484
        return PyErr_SetFromWindowsErr(err);
1485
}
1486
1487
static PyObject *
1488
win32_error_object(const char* function, PyObject* filename)
1489
{
1490
    errno = GetLastError();
1491
    return win32_error_object_err(function, filename, errno);
1492
}
1493
1494
#endif /* MS_WINDOWS */
1495
1496
static PyObject *
1497
posix_path_object_error(PyObject *path)
1498
230
{
1499
230
    return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1500
230
}
1501
1502
static PyObject *
1503
path_object_error(PyObject *path)
1504
230
{
1505
#ifdef MS_WINDOWS
1506
    return PyErr_SetExcFromWindowsErrWithFilenameObject(
1507
                PyExc_OSError, 0, path);
1508
#else
1509
230
    return posix_path_object_error(path);
1510
230
#endif
1511
230
}
1512
1513
static PyObject *
1514
path_object_error2(PyObject *path, PyObject *path2)
1515
0
{
1516
#ifdef MS_WINDOWS
1517
    return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1518
                PyExc_OSError, 0, path, path2);
1519
#else
1520
0
    return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1521
0
#endif
1522
0
}
1523
1524
static PyObject *
1525
path_error(path_t *path)
1526
230
{
1527
230
    return path_object_error(path->object);
1528
230
}
1529
1530
static PyObject *
1531
posix_path_error(path_t *path)
1532
0
{
1533
0
    return posix_path_object_error(path->object);
1534
0
}
1535
1536
static PyObject *
1537
path_error2(path_t *path, path_t *path2)
1538
0
{
1539
0
    return path_object_error2(path->object, path2->object);
1540
0
}
1541
1542
1543
/* POSIX generic methods */
1544
1545
static int
1546
fildes_converter(PyObject *o, void *p)
1547
0
{
1548
0
    int fd;
1549
0
    int *pointer = (int *)p;
1550
0
    fd = PyObject_AsFileDescriptor(o);
1551
0
    if (fd < 0)
1552
0
        return 0;
1553
0
    *pointer = fd;
1554
0
    return 1;
1555
0
}
1556
1557
static PyObject *
1558
posix_fildes_fd(int fd, int (*func)(int))
1559
0
{
1560
0
    int res;
1561
0
    int async_err = 0;
1562
1563
0
    do {
1564
0
        Py_BEGIN_ALLOW_THREADS
1565
0
        _Py_BEGIN_SUPPRESS_IPH
1566
0
        res = (*func)(fd);
1567
0
        _Py_END_SUPPRESS_IPH
1568
0
        Py_END_ALLOW_THREADS
1569
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1570
0
    if (res != 0)
1571
0
        return (!async_err) ? posix_error() : NULL;
1572
0
    Py_RETURN_NONE;
1573
0
}
1574
1575
1576
#ifdef MS_WINDOWS
1577
/* This is a reimplementation of the C library's chdir function,
1578
   but one that produces Win32 errors instead of DOS error codes.
1579
   chdir is essentially a wrapper around SetCurrentDirectory; however,
1580
   it also needs to set "magic" environment variables indicating
1581
   the per-drive current directory, which are of the form =<drive>: */
1582
static BOOL __stdcall
1583
win32_wchdir(LPCWSTR path)
1584
{
1585
    wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1586
    int result;
1587
    wchar_t env[4] = L"=x:";
1588
1589
    if(!SetCurrentDirectoryW(path))
1590
        return FALSE;
1591
    result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1592
    if (!result)
1593
        return FALSE;
1594
    if (result > Py_ARRAY_LENGTH(path_buf)) {
1595
        new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1596
        if (!new_path) {
1597
            SetLastError(ERROR_OUTOFMEMORY);
1598
            return FALSE;
1599
        }
1600
        result = GetCurrentDirectoryW(result, new_path);
1601
        if (!result) {
1602
            PyMem_RawFree(new_path);
1603
            return FALSE;
1604
        }
1605
    }
1606
    int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1607
                            wcsncmp(new_path, L"//", 2) == 0);
1608
    if (!is_unc_like_path) {
1609
        env[1] = new_path[0];
1610
        result = SetEnvironmentVariableW(env, new_path);
1611
    }
1612
    if (new_path != path_buf)
1613
        PyMem_RawFree(new_path);
1614
    return result ? TRUE : FALSE;
1615
}
1616
#endif
1617
1618
#ifdef MS_WINDOWS
1619
/* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1620
   - time stamps are restricted to second resolution
1621
   - file modification times suffer from forth-and-back conversions between
1622
     UTC and local time
1623
   Therefore, we implement our own stat, based on the Win32 API directly.
1624
*/
1625
#define HAVE_STAT_NSEC 1
1626
#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
1627
#define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
1628
1629
static void
1630
find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
1631
                       BY_HANDLE_FILE_INFORMATION *info,
1632
                       ULONG *reparse_tag)
1633
{
1634
    memset(info, 0, sizeof(*info));
1635
    info->dwFileAttributes = pFileData->dwFileAttributes;
1636
    info->ftCreationTime   = pFileData->ftCreationTime;
1637
    info->ftLastAccessTime = pFileData->ftLastAccessTime;
1638
    info->ftLastWriteTime  = pFileData->ftLastWriteTime;
1639
    info->nFileSizeHigh    = pFileData->nFileSizeHigh;
1640
    info->nFileSizeLow     = pFileData->nFileSizeLow;
1641
/*  info->nNumberOfLinks   = 1; */
1642
    if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1643
        *reparse_tag = pFileData->dwReserved0;
1644
    else
1645
        *reparse_tag = 0;
1646
}
1647
1648
static BOOL
1649
attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1650
{
1651
    HANDLE hFindFile;
1652
    WIN32_FIND_DATAW FileData;
1653
    hFindFile = FindFirstFileW(pszFile, &FileData);
1654
    if (hFindFile == INVALID_HANDLE_VALUE)
1655
        return FALSE;
1656
    FindClose(hFindFile);
1657
    find_data_to_file_info(&FileData, info, reparse_tag);
1658
    return TRUE;
1659
}
1660
1661
static int
1662
win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
1663
                 BOOL traverse)
1664
{
1665
    HANDLE hFile;
1666
    BY_HANDLE_FILE_INFORMATION fileInfo;
1667
    FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
1668
    DWORD fileType, error;
1669
    BOOL isUnhandledTag = FALSE;
1670
    int retval = 0;
1671
1672
    DWORD access = FILE_READ_ATTRIBUTES;
1673
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
1674
    if (!traverse) {
1675
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
1676
    }
1677
1678
    hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
1679
    if (hFile == INVALID_HANDLE_VALUE) {
1680
        /* Either the path doesn't exist, or the caller lacks access. */
1681
        error = GetLastError();
1682
        switch (error) {
1683
        case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
1684
        case ERROR_SHARING_VIOLATION: /* It's a paging file. */
1685
            /* Try reading the parent directory. */
1686
            if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
1687
                /* Cannot read the parent directory. */
1688
                SetLastError(error);
1689
                return -1;
1690
            }
1691
            if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1692
                if (traverse ||
1693
                    !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1694
                    /* The stat call has to traverse but cannot, so fail. */
1695
                    SetLastError(error);
1696
                    return -1;
1697
                }
1698
            }
1699
            break;
1700
1701
        case ERROR_INVALID_PARAMETER:
1702
            /* \\.\con requires read or write access. */
1703
            hFile = CreateFileW(path, access | GENERIC_READ,
1704
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1705
                        OPEN_EXISTING, flags, NULL);
1706
            if (hFile == INVALID_HANDLE_VALUE) {
1707
                SetLastError(error);
1708
                return -1;
1709
            }
1710
            break;
1711
1712
        case ERROR_CANT_ACCESS_FILE:
1713
            /* bpo37834: open unhandled reparse points if traverse fails. */
1714
            if (traverse) {
1715
                traverse = FALSE;
1716
                isUnhandledTag = TRUE;
1717
                hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
1718
                            flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
1719
            }
1720
            if (hFile == INVALID_HANDLE_VALUE) {
1721
                SetLastError(error);
1722
                return -1;
1723
            }
1724
            break;
1725
1726
        default:
1727
            return -1;
1728
        }
1729
    }
1730
1731
    if (hFile != INVALID_HANDLE_VALUE) {
1732
        /* Handle types other than files on disk. */
1733
        fileType = GetFileType(hFile);
1734
        if (fileType != FILE_TYPE_DISK) {
1735
            if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
1736
                retval = -1;
1737
                goto cleanup;
1738
            }
1739
            DWORD fileAttributes = GetFileAttributesW(path);
1740
            memset(result, 0, sizeof(*result));
1741
            if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
1742
                fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1743
                /* \\.\pipe\ or \\.\mailslot\ */
1744
                result->st_mode = _S_IFDIR;
1745
            } else if (fileType == FILE_TYPE_CHAR) {
1746
                /* \\.\nul */
1747
                result->st_mode = _S_IFCHR;
1748
            } else if (fileType == FILE_TYPE_PIPE) {
1749
                /* \\.\pipe\spam */
1750
                result->st_mode = _S_IFIFO;
1751
            }
1752
            /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
1753
            goto cleanup;
1754
        }
1755
1756
        /* Query the reparse tag, and traverse a non-link. */
1757
        if (!traverse) {
1758
            if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
1759
                    &tagInfo, sizeof(tagInfo))) {
1760
                /* Allow devices that do not support FileAttributeTagInfo. */
1761
                switch (GetLastError()) {
1762
                case ERROR_INVALID_PARAMETER:
1763
                case ERROR_INVALID_FUNCTION:
1764
                case ERROR_NOT_SUPPORTED:
1765
                    tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1766
                    tagInfo.ReparseTag = 0;
1767
                    break;
1768
                default:
1769
                    retval = -1;
1770
                    goto cleanup;
1771
                }
1772
            } else if (tagInfo.FileAttributes &
1773
                         FILE_ATTRIBUTE_REPARSE_POINT) {
1774
                if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1775
                    if (isUnhandledTag) {
1776
                        /* Traversing previously failed for either this link
1777
                           or its target. */
1778
                        SetLastError(ERROR_CANT_ACCESS_FILE);
1779
                        retval = -1;
1780
                        goto cleanup;
1781
                    }
1782
                /* Traverse a non-link, but not if traversing already failed
1783
                   for an unhandled tag. */
1784
                } else if (!isUnhandledTag) {
1785
                    CloseHandle(hFile);
1786
                    return win32_xstat_impl(path, result, TRUE);
1787
                }
1788
            }
1789
        }
1790
1791
        if (!GetFileInformationByHandle(hFile, &fileInfo)) {
1792
            switch (GetLastError()) {
1793
            case ERROR_INVALID_PARAMETER:
1794
            case ERROR_INVALID_FUNCTION:
1795
            case ERROR_NOT_SUPPORTED:
1796
                /* Volumes and physical disks are block devices, e.g.
1797
                   \\.\C: and \\.\PhysicalDrive0. */
1798
                memset(result, 0, sizeof(*result));
1799
                result->st_mode = 0x6000; /* S_IFBLK */
1800
                goto cleanup;
1801
            }
1802
            retval = -1;
1803
            goto cleanup;
1804
        }
1805
    }
1806
1807
    _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result);
1808
1809
    if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
1810
        /* Fix the file execute permissions. This hack sets S_IEXEC if
1811
           the filename has an extension that is commonly used by files
1812
           that CreateProcessW can execute. A real implementation calls
1813
           GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
1814
           AccessCheck to check for generic read, write, and execute
1815
           access. */
1816
        const wchar_t *fileExtension = wcsrchr(path, '.');
1817
        if (fileExtension) {
1818
            if (_wcsicmp(fileExtension, L".exe") == 0 ||
1819
                _wcsicmp(fileExtension, L".bat") == 0 ||
1820
                _wcsicmp(fileExtension, L".cmd") == 0 ||
1821
                _wcsicmp(fileExtension, L".com") == 0) {
1822
                result->st_mode |= 0111;
1823
            }
1824
        }
1825
    }
1826
1827
cleanup:
1828
    if (hFile != INVALID_HANDLE_VALUE) {
1829
        /* Preserve last error if we are failing */
1830
        error = retval ? GetLastError() : 0;
1831
        if (!CloseHandle(hFile)) {
1832
            retval = -1;
1833
        } else if (retval) {
1834
            /* Restore last error */
1835
            SetLastError(error);
1836
        }
1837
    }
1838
1839
    return retval;
1840
}
1841
1842
static int
1843
win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
1844
{
1845
    /* Protocol violation: we explicitly clear errno, instead of
1846
       setting it to a POSIX error. Callers should use GetLastError. */
1847
    int code = win32_xstat_impl(path, result, traverse);
1848
    errno = 0;
1849
    return code;
1850
}
1851
/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
1852
1853
   In Posix, stat automatically traverses symlinks and returns the stat
1854
   structure for the target.  In Windows, the equivalent GetFileAttributes by
1855
   default does not traverse symlinks and instead returns attributes for
1856
   the symlink.
1857
1858
   Instead, we will open the file (which *does* traverse symlinks by default)
1859
   and GetFileInformationByHandle(). */
1860
1861
static int
1862
win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
1863
{
1864
    return win32_xstat(path, result, FALSE);
1865
}
1866
1867
static int
1868
win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
1869
{
1870
    return win32_xstat(path, result, TRUE);
1871
}
1872
1873
#endif /* MS_WINDOWS */
1874
1875
PyDoc_STRVAR(stat_result__doc__,
1876
"stat_result: Result from stat, fstat, or lstat.\n\n\
1877
This object may be accessed either as a tuple of\n\
1878
  (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
1879
or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
1880
\n\
1881
Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
1882
or st_flags, they are available as attributes only.\n\
1883
\n\
1884
See os.stat for more information.");
1885
1886
static PyStructSequence_Field stat_result_fields[] = {
1887
    {"st_mode",    "protection bits"},
1888
    {"st_ino",     "inode"},
1889
    {"st_dev",     "device"},
1890
    {"st_nlink",   "number of hard links"},
1891
    {"st_uid",     "user ID of owner"},
1892
    {"st_gid",     "group ID of owner"},
1893
    {"st_size",    "total size, in bytes"},
1894
    /* The NULL is replaced with PyStructSequence_UnnamedField later. */
1895
    {NULL,   "integer time of last access"},
1896
    {NULL,   "integer time of last modification"},
1897
    {NULL,   "integer time of last change"},
1898
    {"st_atime",   "time of last access"},
1899
    {"st_mtime",   "time of last modification"},
1900
    {"st_ctime",   "time of last change"},
1901
    {"st_atime_ns",   "time of last access in nanoseconds"},
1902
    {"st_mtime_ns",   "time of last modification in nanoseconds"},
1903
    {"st_ctime_ns",   "time of last change in nanoseconds"},
1904
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1905
    {"st_blksize", "blocksize for filesystem I/O"},
1906
#endif
1907
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1908
    {"st_blocks",  "number of blocks allocated"},
1909
#endif
1910
#ifdef HAVE_STRUCT_STAT_ST_RDEV
1911
    {"st_rdev",    "device type (if inode device)"},
1912
#endif
1913
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
1914
    {"st_flags",   "user defined flags for file"},
1915
#endif
1916
#ifdef HAVE_STRUCT_STAT_ST_GEN
1917
    {"st_gen",    "generation number"},
1918
#endif
1919
#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1920
    {"st_birthtime",   "time of creation"},
1921
#endif
1922
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
1923
    {"st_file_attributes", "Windows file attribute bits"},
1924
#endif
1925
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
1926
    {"st_fstype",  "Type of filesystem"},
1927
#endif
1928
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
1929
    {"st_reparse_tag", "Windows reparse tag"},
1930
#endif
1931
    {0}
1932
};
1933
1934
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1935
#define ST_BLKSIZE_IDX 16
1936
#else
1937
#define ST_BLKSIZE_IDX 15
1938
#endif
1939
1940
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1941
#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
1942
#else
1943
#define ST_BLOCKS_IDX ST_BLKSIZE_IDX
1944
#endif
1945
1946
#ifdef HAVE_STRUCT_STAT_ST_RDEV
1947
#define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
1948
#else
1949
#define ST_RDEV_IDX ST_BLOCKS_IDX
1950
#endif
1951
1952
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
1953
#define ST_FLAGS_IDX (ST_RDEV_IDX+1)
1954
#else
1955
#define ST_FLAGS_IDX ST_RDEV_IDX
1956
#endif
1957
1958
#ifdef HAVE_STRUCT_STAT_ST_GEN
1959
#define ST_GEN_IDX (ST_FLAGS_IDX+1)
1960
#else
1961
#define ST_GEN_IDX ST_FLAGS_IDX
1962
#endif
1963
1964
#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1965
#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
1966
#else
1967
#define ST_BIRTHTIME_IDX ST_GEN_IDX
1968
#endif
1969
1970
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
1971
#define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1)
1972
#else
1973
#define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX
1974
#endif
1975
1976
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
1977
#define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
1978
#else
1979
#define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
1980
#endif
1981
1982
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
1983
#define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
1984
#else
1985
#define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
1986
#endif
1987
1988
static PyStructSequence_Desc stat_result_desc = {
1989
    "stat_result", /* name */
1990
    stat_result__doc__, /* doc */
1991
    stat_result_fields,
1992
    10
1993
};
1994
1995
PyDoc_STRVAR(statvfs_result__doc__,
1996
"statvfs_result: Result from statvfs or fstatvfs.\n\n\
1997
This object may be accessed either as a tuple of\n\
1998
  (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
1999
or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2000
\n\
2001
See os.statvfs for more information.");
2002
2003
static PyStructSequence_Field statvfs_result_fields[] = {
2004
    {"f_bsize",  },
2005
    {"f_frsize", },
2006
    {"f_blocks", },
2007
    {"f_bfree",  },
2008
    {"f_bavail", },
2009
    {"f_files",  },
2010
    {"f_ffree",  },
2011
    {"f_favail", },
2012
    {"f_flag",   },
2013
    {"f_namemax",},
2014
    {"f_fsid",   },
2015
    {0}
2016
};
2017
2018
static PyStructSequence_Desc statvfs_result_desc = {
2019
    "statvfs_result", /* name */
2020
    statvfs_result__doc__, /* doc */
2021
    statvfs_result_fields,
2022
    10
2023
};
2024
2025
#if defined(HAVE_WAITID) && !defined(__APPLE__)
2026
PyDoc_STRVAR(waitid_result__doc__,
2027
"waitid_result: Result from waitid.\n\n\
2028
This object may be accessed either as a tuple of\n\
2029
  (si_pid, si_uid, si_signo, si_status, si_code),\n\
2030
or via the attributes si_pid, si_uid, and so on.\n\
2031
\n\
2032
See os.waitid for more information.");
2033
2034
static PyStructSequence_Field waitid_result_fields[] = {
2035
    {"si_pid",  },
2036
    {"si_uid", },
2037
    {"si_signo", },
2038
    {"si_status",  },
2039
    {"si_code", },
2040
    {0}
2041
};
2042
2043
static PyStructSequence_Desc waitid_result_desc = {
2044
    "waitid_result", /* name */
2045
    waitid_result__doc__, /* doc */
2046
    waitid_result_fields,
2047
    5
2048
};
2049
static PyTypeObject* WaitidResultType;
2050
#endif
2051
2052
static int initialized;
2053
static PyTypeObject* StatResultType;
2054
static PyTypeObject* StatVFSResultType;
2055
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2056
static PyTypeObject* SchedParamType;
2057
#endif
2058
static newfunc structseq_new;
2059
2060
static PyObject *
2061
statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2062
0
{
2063
0
    PyStructSequence *result;
2064
0
    int i;
2065
2066
0
    result = (PyStructSequence*)structseq_new(type, args, kwds);
2067
0
    if (!result)
2068
0
        return NULL;
2069
    /* If we have been initialized from a tuple,
2070
       st_?time might be set to None. Initialize it
2071
       from the int slots.  */
2072
0
    for (i = 7; i <= 9; i++) {
2073
0
        if (result->ob_item[i+3] == Py_None) {
2074
0
            Py_DECREF(Py_None);
2075
0
            Py_INCREF(result->ob_item[i]);
2076
0
            result->ob_item[i+3] = result->ob_item[i];
2077
0
        }
2078
0
    }
2079
0
    return (PyObject*)result;
2080
0
}
2081
2082
2083
static PyObject *billion = NULL;
2084
2085
static void
2086
fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
2087
2.56k
{
2088
2.56k
    PyObject *s = _PyLong_FromTime_t(sec);
2089
2.56k
    PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2090
2.56k
    PyObject *s_in_ns = NULL;
2091
2.56k
    PyObject *ns_total = NULL;
2092
2.56k
    PyObject *float_s = NULL;
2093
2094
2.56k
    if (!(s && ns_fractional))
2095
0
        goto exit;
2096
2097
2.56k
    s_in_ns = PyNumber_Multiply(s, billion);
2098
2.56k
    if (!s_in_ns)
2099
0
        goto exit;
2100
2101
2.56k
    ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2102
2.56k
    if (!ns_total)
2103
0
        goto exit;
2104
2105
2.56k
    float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2106
2.56k
    if (!float_s) {
2107
0
        goto exit;
2108
0
    }
2109
2110
2.56k
    PyStructSequence_SET_ITEM(v, index, s);
2111
2.56k
    PyStructSequence_SET_ITEM(v, index+3, float_s);
2112
2.56k
    PyStructSequence_SET_ITEM(v, index+6, ns_total);
2113
2.56k
    s = NULL;
2114
2.56k
    float_s = NULL;
2115
2.56k
    ns_total = NULL;
2116
2.56k
exit:
2117
2.56k
    Py_XDECREF(s);
2118
2.56k
    Py_XDECREF(ns_fractional);
2119
2.56k
    Py_XDECREF(s_in_ns);
2120
2.56k
    Py_XDECREF(ns_total);
2121
2.56k
    Py_XDECREF(float_s);
2122
2.56k
}
2123
2124
/* pack a system stat C structure into the Python stat tuple
2125
   (used by posix_stat() and posix_fstat()) */
2126
static PyObject*
2127
_pystat_fromstructstat(STRUCT_STAT *st)
2128
854
{
2129
854
    unsigned long ansec, mnsec, cnsec;
2130
854
    PyObject *v = PyStructSequence_New(StatResultType);
2131
854
    if (v == NULL)
2132
0
        return NULL;
2133
2134
854
    PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
2135
854
    Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(st->st_ino));
2136
854
    PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino));
2137
#ifdef MS_WINDOWS
2138
    PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));
2139
#else
2140
854
    PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));
2141
854
#endif
2142
854
    PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
2143
#if defined(MS_WINDOWS)
2144
    PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0));
2145
    PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0));
2146
#else
2147
854
    PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));
2148
854
    PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid));
2149
854
#endif
2150
854
    Py_BUILD_ASSERT(sizeof(long long) >= sizeof(st->st_size));
2151
854
    PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size));
2152
2153
854
#if defined(HAVE_STAT_TV_NSEC)
2154
854
    ansec = st->st_atim.tv_nsec;
2155
854
    mnsec = st->st_mtim.tv_nsec;
2156
854
    cnsec = st->st_ctim.tv_nsec;
2157
#elif defined(HAVE_STAT_TV_NSEC2)
2158
    ansec = st->st_atimespec.tv_nsec;
2159
    mnsec = st->st_mtimespec.tv_nsec;
2160
    cnsec = st->st_ctimespec.tv_nsec;
2161
#elif defined(HAVE_STAT_NSEC)
2162
    ansec = st->st_atime_nsec;
2163
    mnsec = st->st_mtime_nsec;
2164
    cnsec = st->st_ctime_nsec;
2165
#else
2166
    ansec = mnsec = cnsec = 0;
2167
#endif
2168
854
    fill_time(v, 7, st->st_atime, ansec);
2169
854
    fill_time(v, 8, st->st_mtime, mnsec);
2170
854
    fill_time(v, 9, st->st_ctime, cnsec);
2171
2172
854
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2173
854
    PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
2174
854
                              PyLong_FromLong((long)st->st_blksize));
2175
854
#endif
2176
854
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2177
854
    PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
2178
854
                              PyLong_FromLong((long)st->st_blocks));
2179
854
#endif
2180
854
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2181
854
    PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
2182
854
                              PyLong_FromLong((long)st->st_rdev));
2183
854
#endif
2184
#ifdef HAVE_STRUCT_STAT_ST_GEN
2185
    PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
2186
                              PyLong_FromLong((long)st->st_gen));
2187
#endif
2188
#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2189
    {
2190
      PyObject *val;
2191
      unsigned long bsec,bnsec;
2192
      bsec = (long)st->st_birthtime;
2193
#ifdef HAVE_STAT_TV_NSEC2
2194
      bnsec = st->st_birthtimespec.tv_nsec;
2195
#else
2196
      bnsec = 0;
2197
#endif
2198
      val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
2199
      PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
2200
                                val);
2201
    }
2202
#endif
2203
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2204
    PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
2205
                              PyLong_FromLong((long)st->st_flags));
2206
#endif
2207
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2208
    PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,
2209
                              PyLong_FromUnsignedLong(st->st_file_attributes));
2210
#endif
2211
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2212
   PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX,
2213
                              PyUnicode_FromString(st->st_fstype));
2214
#endif
2215
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2216
    PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX,
2217
                              PyLong_FromUnsignedLong(st->st_reparse_tag));
2218
#endif
2219
2220
854
    if (PyErr_Occurred()) {
2221
0
        Py_DECREF(v);
2222
0
        return NULL;
2223
0
    }
2224
2225
854
    return v;
2226
854
}
2227
2228
/* POSIX methods */
2229
2230
2231
static PyObject *
2232
posix_do_stat(const char *function_name, path_t *path,
2233
              int dir_fd, int follow_symlinks)
2234
1.08k
{
2235
1.08k
    STRUCT_STAT st;
2236
1.08k
    int result;
2237
2238
#if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2239
    if (follow_symlinks_specified(function_name, follow_symlinks))
2240
        return NULL;
2241
#endif
2242
2243
1.08k
    if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2244
1.08k
        dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2245
1.08k
        fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2246
0
        return NULL;
2247
2248
1.08k
    Py_BEGIN_ALLOW_THREADS
2249
1.08k
    if (path->fd != -1)
2250
0
        result = FSTAT(path->fd, &st);
2251
#ifdef MS_WINDOWS
2252
    else if (follow_symlinks)
2253
        result = win32_stat(path->wide, &st);
2254
    else
2255
        result = win32_lstat(path->wide, &st);
2256
#else
2257
1.08k
    else
2258
1.08k
#if defined(HAVE_LSTAT)
2259
1.08k
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2260
0
        result = LSTAT(path->narrow, &st);
2261
1.08k
    else
2262
1.08k
#endif /* HAVE_LSTAT */
2263
1.08k
#ifdef HAVE_FSTATAT
2264
1.08k
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks)
2265
0
        result = fstatat(dir_fd, path->narrow, &st,
2266
0
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2267
1.08k
    else
2268
1.08k
#endif /* HAVE_FSTATAT */
2269
1.08k
        result = STAT(path->narrow, &st);
2270
1.08k
#endif /* MS_WINDOWS */
2271
1.08k
    Py_END_ALLOW_THREADS
2272
2273
1.08k
    if (result != 0) {
2274
230
        return path_error(path);
2275
230
    }
2276
2277
854
    return _pystat_fromstructstat(&st);
2278
1.08k
}
2279
2280
/*[python input]
2281
2282
for s in """
2283
2284
FACCESSAT
2285
FCHMODAT
2286
FCHOWNAT
2287
FSTATAT
2288
LINKAT
2289
MKDIRAT
2290
MKFIFOAT
2291
MKNODAT
2292
OPENAT
2293
READLINKAT
2294
SYMLINKAT
2295
UNLINKAT
2296
2297
""".strip().split():
2298
    s = s.strip()
2299
    print("""
2300
#ifdef HAVE_{s}
2301
    #define {s}_DIR_FD_CONVERTER dir_fd_converter
2302
#else
2303
    #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2304
#endif
2305
""".rstrip().format(s=s))
2306
2307
for s in """
2308
2309
FCHDIR
2310
FCHMOD
2311
FCHOWN
2312
FDOPENDIR
2313
FEXECVE
2314
FPATHCONF
2315
FSTATVFS
2316
FTRUNCATE
2317
2318
""".strip().split():
2319
    s = s.strip()
2320
    print("""
2321
#ifdef HAVE_{s}
2322
    #define PATH_HAVE_{s} 1
2323
#else
2324
    #define PATH_HAVE_{s} 0
2325
#endif
2326
2327
""".rstrip().format(s=s))
2328
[python start generated code]*/
2329
2330
#ifdef HAVE_FACCESSAT
2331
0
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2332
#else
2333
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2334
#endif
2335
2336
#ifdef HAVE_FCHMODAT
2337
0
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2338
#else
2339
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2340
#endif
2341
2342
#ifdef HAVE_FCHOWNAT
2343
0
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2344
#else
2345
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2346
#endif
2347
2348
#ifdef HAVE_FSTATAT
2349
0
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2350
#else
2351
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2352
#endif
2353
2354
#ifdef HAVE_LINKAT
2355
    #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2356
#else
2357
    #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2358
#endif
2359
2360
#ifdef HAVE_MKDIRAT
2361
0
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
2362
#else
2363
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
2364
#endif
2365
2366
#ifdef HAVE_MKFIFOAT
2367
0
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
2368
#else
2369
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
2370
#endif
2371
2372
#ifdef HAVE_MKNODAT
2373
0
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
2374
#else
2375
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
2376
#endif
2377
2378
#ifdef HAVE_OPENAT
2379
0
    #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
2380
#else
2381
    #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
2382
#endif
2383
2384
#ifdef HAVE_READLINKAT
2385
0
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
2386
#else
2387
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2388
#endif
2389
2390
#ifdef HAVE_SYMLINKAT
2391
0
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
2392
#else
2393
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2394
#endif
2395
2396
#ifdef HAVE_UNLINKAT
2397
0
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
2398
#else
2399
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2400
#endif
2401
2402
#ifdef HAVE_FCHDIR
2403
    #define PATH_HAVE_FCHDIR 1
2404
#else
2405
    #define PATH_HAVE_FCHDIR 0
2406
#endif
2407
2408
#ifdef HAVE_FCHMOD
2409
    #define PATH_HAVE_FCHMOD 1
2410
#else
2411
    #define PATH_HAVE_FCHMOD 0
2412
#endif
2413
2414
#ifdef HAVE_FCHOWN
2415
    #define PATH_HAVE_FCHOWN 1
2416
#else
2417
    #define PATH_HAVE_FCHOWN 0
2418
#endif
2419
2420
#ifdef HAVE_FDOPENDIR
2421
    #define PATH_HAVE_FDOPENDIR 1
2422
#else
2423
    #define PATH_HAVE_FDOPENDIR 0
2424
#endif
2425
2426
#ifdef HAVE_FEXECVE
2427
    #define PATH_HAVE_FEXECVE 1
2428
#else
2429
    #define PATH_HAVE_FEXECVE 0
2430
#endif
2431
2432
#ifdef HAVE_FPATHCONF
2433
    #define PATH_HAVE_FPATHCONF 1
2434
#else
2435
    #define PATH_HAVE_FPATHCONF 0
2436
#endif
2437
2438
#ifdef HAVE_FSTATVFS
2439
    #define PATH_HAVE_FSTATVFS 1
2440
#else
2441
    #define PATH_HAVE_FSTATVFS 0
2442
#endif
2443
2444
#ifdef HAVE_FTRUNCATE
2445
    #define PATH_HAVE_FTRUNCATE 1
2446
#else
2447
    #define PATH_HAVE_FTRUNCATE 0
2448
#endif
2449
/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
2450
2451
#ifdef MS_WINDOWS
2452
    #undef PATH_HAVE_FTRUNCATE
2453
    #define PATH_HAVE_FTRUNCATE 1
2454
#endif
2455
2456
/*[python input]
2457
2458
class path_t_converter(CConverter):
2459
2460
    type = "path_t"
2461
    impl_by_reference = True
2462
    parse_by_reference = True
2463
2464
    converter = 'path_converter'
2465
2466
    def converter_init(self, *, allow_fd=False, nullable=False):
2467
        # right now path_t doesn't support default values.
2468
        # to support a default value, you'll need to override initialize().
2469
        if self.default not in (unspecified, None):
2470
            fail("Can't specify a default to the path_t converter!")
2471
2472
        if self.c_default not in (None, 'Py_None'):
2473
            raise RuntimeError("Can't specify a c_default to the path_t converter!")
2474
2475
        self.nullable = nullable
2476
        self.allow_fd = allow_fd
2477
2478
    def pre_render(self):
2479
        def strify(value):
2480
            if isinstance(value, str):
2481
                return value
2482
            return str(int(bool(value)))
2483
2484
        # add self.py_name here when merging with posixmodule conversion
2485
        self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format(
2486
            self.function.name,
2487
            self.name,
2488
            strify(self.nullable),
2489
            strify(self.allow_fd),
2490
            )
2491
2492
    def cleanup(self):
2493
        return "path_cleanup(&" + self.name + ");\n"
2494
2495
2496
class dir_fd_converter(CConverter):
2497
    type = 'int'
2498
2499
    def converter_init(self, requires=None):
2500
        if self.default in (unspecified, None):
2501
            self.c_default = 'DEFAULT_DIR_FD'
2502
        if isinstance(requires, str):
2503
            self.converter = requires.upper() + '_DIR_FD_CONVERTER'
2504
        else:
2505
            self.converter = 'dir_fd_converter'
2506
2507
class fildes_converter(CConverter):
2508
    type = 'int'
2509
    converter = 'fildes_converter'
2510
2511
class uid_t_converter(CConverter):
2512
    type = "uid_t"
2513
    converter = '_Py_Uid_Converter'
2514
2515
class gid_t_converter(CConverter):
2516
    type = "gid_t"
2517
    converter = '_Py_Gid_Converter'
2518
2519
class dev_t_converter(CConverter):
2520
    type = 'dev_t'
2521
    converter = '_Py_Dev_Converter'
2522
2523
class dev_t_return_converter(unsigned_long_return_converter):
2524
    type = 'dev_t'
2525
    conversion_fn = '_PyLong_FromDev'
2526
    unsigned_cast = '(dev_t)'
2527
2528
class FSConverter_converter(CConverter):
2529
    type = 'PyObject *'
2530
    converter = 'PyUnicode_FSConverter'
2531
    def converter_init(self):
2532
        if self.default is not unspecified:
2533
            fail("FSConverter_converter does not support default values")
2534
        self.c_default = 'NULL'
2535
2536
    def cleanup(self):
2537
        return "Py_XDECREF(" + self.name + ");\n"
2538
2539
class pid_t_converter(CConverter):
2540
    type = 'pid_t'
2541
    format_unit = '" _Py_PARSE_PID "'
2542
2543
class idtype_t_converter(int_converter):
2544
    type = 'idtype_t'
2545
2546
class id_t_converter(CConverter):
2547
    type = 'id_t'
2548
    format_unit = '" _Py_PARSE_PID "'
2549
2550
class intptr_t_converter(CConverter):
2551
    type = 'intptr_t'
2552
    format_unit = '" _Py_PARSE_INTPTR "'
2553
2554
class Py_off_t_converter(CConverter):
2555
    type = 'Py_off_t'
2556
    converter = 'Py_off_t_converter'
2557
2558
class Py_off_t_return_converter(long_return_converter):
2559
    type = 'Py_off_t'
2560
    conversion_fn = 'PyLong_FromPy_off_t'
2561
2562
class path_confname_converter(CConverter):
2563
    type="int"
2564
    converter="conv_path_confname"
2565
2566
class confstr_confname_converter(path_confname_converter):
2567
    converter='conv_confstr_confname'
2568
2569
class sysconf_confname_converter(path_confname_converter):
2570
    converter="conv_sysconf_confname"
2571
2572
class sched_param_converter(CConverter):
2573
    type = 'struct sched_param'
2574
    converter = 'convert_sched_param'
2575
    impl_by_reference = True;
2576
2577
[python start generated code]*/
2578
/*[python end generated code: output=da39a3ee5e6b4b0d input=418fce0e01144461]*/
2579
2580
/*[clinic input]
2581
2582
os.stat
2583
2584
    path : path_t(allow_fd=True)
2585
        Path to be examined; can be string, bytes, a path-like object or
2586
        open-file-descriptor int.
2587
2588
    *
2589
2590
    dir_fd : dir_fd(requires='fstatat') = None
2591
        If not None, it should be a file descriptor open to a directory,
2592
        and path should be a relative string; path will then be relative to
2593
        that directory.
2594
2595
    follow_symlinks: bool = True
2596
        If False, and the last element of the path is a symbolic link,
2597
        stat will examine the symbolic link itself instead of the file
2598
        the link points to.
2599
2600
Perform a stat system call on the given path.
2601
2602
dir_fd and follow_symlinks may not be implemented
2603
  on your platform.  If they are unavailable, using them will raise a
2604
  NotImplementedError.
2605
2606
It's an error to use dir_fd or follow_symlinks when specifying path as
2607
  an open file descriptor.
2608
2609
[clinic start generated code]*/
2610
2611
static PyObject *
2612
os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
2613
/*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
2614
1.08k
{
2615
1.08k
    return posix_do_stat("stat", path, dir_fd, follow_symlinks);
2616
1.08k
}
2617
2618
2619
/*[clinic input]
2620
os.lstat
2621
2622
    path : path_t
2623
2624
    *
2625
2626
    dir_fd : dir_fd(requires='fstatat') = None
2627
2628
Perform a stat system call on the given path, without following symbolic links.
2629
2630
Like stat(), but do not follow symbolic links.
2631
Equivalent to stat(path, follow_symlinks=False).
2632
[clinic start generated code]*/
2633
2634
static PyObject *
2635
os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
2636
/*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
2637
0
{
2638
0
    int follow_symlinks = 0;
2639
0
    return posix_do_stat("lstat", path, dir_fd, follow_symlinks);
2640
0
}
2641
2642
2643
/*[clinic input]
2644
os.access -> bool
2645
2646
    path: path_t
2647
        Path to be tested; can be string, bytes, or a path-like object.
2648
2649
    mode: int
2650
        Operating-system mode bitfield.  Can be F_OK to test existence,
2651
        or the inclusive-OR of R_OK, W_OK, and X_OK.
2652
2653
    *
2654
2655
    dir_fd : dir_fd(requires='faccessat') = None
2656
        If not None, it should be a file descriptor open to a directory,
2657
        and path should be relative; path will then be relative to that
2658
        directory.
2659
2660
    effective_ids: bool = False
2661
        If True, access will use the effective uid/gid instead of
2662
        the real uid/gid.
2663
2664
    follow_symlinks: bool = True
2665
        If False, and the last element of the path is a symbolic link,
2666
        access will examine the symbolic link itself instead of the file
2667
        the link points to.
2668
2669
Use the real uid/gid to test for access to a path.
2670
2671
{parameters}
2672
dir_fd, effective_ids, and follow_symlinks may not be implemented
2673
  on your platform.  If they are unavailable, using them will raise a
2674
  NotImplementedError.
2675
2676
Note that most operations will use the effective uid/gid, therefore this
2677
  routine can be used in a suid/sgid environment to test if the invoking user
2678
  has the specified access to the path.
2679
2680
[clinic start generated code]*/
2681
2682
static int
2683
os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
2684
               int effective_ids, int follow_symlinks)
2685
/*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/
2686
0
{
2687
0
    int return_value;
2688
2689
#ifdef MS_WINDOWS
2690
    DWORD attr;
2691
#else
2692
0
    int result;
2693
0
#endif
2694
2695
#ifndef HAVE_FACCESSAT
2696
    if (follow_symlinks_specified("access", follow_symlinks))
2697
        return -1;
2698
2699
    if (effective_ids) {
2700
        argument_unavailable_error("access", "effective_ids");
2701
        return -1;
2702
    }
2703
#endif
2704
2705
#ifdef MS_WINDOWS
2706
    Py_BEGIN_ALLOW_THREADS
2707
    attr = GetFileAttributesW(path->wide);
2708
    Py_END_ALLOW_THREADS
2709
2710
    /*
2711
     * Access is possible if
2712
     *   * we didn't get a -1, and
2713
     *     * write access wasn't requested,
2714
     *     * or the file isn't read-only,
2715
     *     * or it's a directory.
2716
     * (Directories cannot be read-only on Windows.)
2717
    */
2718
    return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
2719
            (!(mode & 2) ||
2720
            !(attr & FILE_ATTRIBUTE_READONLY) ||
2721
            (attr & FILE_ATTRIBUTE_DIRECTORY));
2722
#else
2723
2724
0
    Py_BEGIN_ALLOW_THREADS
2725
0
#ifdef HAVE_FACCESSAT
2726
0
    if ((dir_fd != DEFAULT_DIR_FD) ||
2727
0
        effective_ids ||
2728
0
        !follow_symlinks) {
2729
0
        int flags = 0;
2730
0
        if (!follow_symlinks)
2731
0
            flags |= AT_SYMLINK_NOFOLLOW;
2732
0
        if (effective_ids)
2733
0
            flags |= AT_EACCESS;
2734
0
        result = faccessat(dir_fd, path->narrow, mode, flags);
2735
0
    }
2736
0
    else
2737
0
#endif
2738
0
        result = access(path->narrow, mode);
2739
0
    Py_END_ALLOW_THREADS
2740
0
    return_value = !result;
2741
0
#endif
2742
2743
0
    return return_value;
2744
0
}
2745
2746
#ifndef F_OK
2747
#define F_OK 0
2748
#endif
2749
#ifndef R_OK
2750
#define R_OK 4
2751
#endif
2752
#ifndef W_OK
2753
#define W_OK 2
2754
#endif
2755
#ifndef X_OK
2756
#define X_OK 1
2757
#endif
2758
2759
2760
#ifdef HAVE_TTYNAME
2761
/*[clinic input]
2762
os.ttyname
2763
2764
    fd: int
2765
        Integer file descriptor handle.
2766
2767
    /
2768
2769
Return the name of the terminal device connected to 'fd'.
2770
[clinic start generated code]*/
2771
2772
static PyObject *
2773
os_ttyname_impl(PyObject *module, int fd)
2774
/*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
2775
0
{
2776
0
    char *ret;
2777
2778
0
    ret = ttyname(fd);
2779
0
    if (ret == NULL) {
2780
0
        return posix_error();
2781
0
    }
2782
0
    return PyUnicode_DecodeFSDefault(ret);
2783
0
}
2784
#endif
2785
2786
#ifdef HAVE_CTERMID
2787
/*[clinic input]
2788
os.ctermid
2789
2790
Return the name of the controlling terminal for this process.
2791
[clinic start generated code]*/
2792
2793
static PyObject *
2794
os_ctermid_impl(PyObject *module)
2795
/*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
2796
0
{
2797
0
    char *ret;
2798
0
    char buffer[L_ctermid];
2799
2800
#ifdef USE_CTERMID_R
2801
    ret = ctermid_r(buffer);
2802
#else
2803
0
    ret = ctermid(buffer);
2804
0
#endif
2805
0
    if (ret == NULL)
2806
0
        return posix_error();
2807
0
    return PyUnicode_DecodeFSDefault(buffer);
2808
0
}
2809
#endif /* HAVE_CTERMID */
2810
2811
2812
/*[clinic input]
2813
os.chdir
2814
2815
    path: path_t(allow_fd='PATH_HAVE_FCHDIR')
2816
2817
Change the current working directory to the specified path.
2818
2819
path may always be specified as a string.
2820
On some platforms, path may also be specified as an open file descriptor.
2821
  If this functionality is unavailable, using it raises an exception.
2822
[clinic start generated code]*/
2823
2824
static PyObject *
2825
os_chdir_impl(PyObject *module, path_t *path)
2826
/*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
2827
0
{
2828
0
    int result;
2829
2830
0
    if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
2831
0
        return NULL;
2832
0
    }
2833
2834
0
    Py_BEGIN_ALLOW_THREADS
2835
#ifdef MS_WINDOWS
2836
    /* on unix, success = 0, on windows, success = !0 */
2837
    result = !win32_wchdir(path->wide);
2838
#else
2839
0
#ifdef HAVE_FCHDIR
2840
0
    if (path->fd != -1)
2841
0
        result = fchdir(path->fd);
2842
0
    else
2843
0
#endif
2844
0
        result = chdir(path->narrow);
2845
0
#endif
2846
0
    Py_END_ALLOW_THREADS
2847
2848
0
    if (result) {
2849
0
        return path_error(path);
2850
0
    }
2851
2852
0
    Py_RETURN_NONE;
2853
0
}
2854
2855
2856
#ifdef HAVE_FCHDIR
2857
/*[clinic input]
2858
os.fchdir
2859
2860
    fd: fildes
2861
2862
Change to the directory of the given file descriptor.
2863
2864
fd must be opened on a directory, not a file.
2865
Equivalent to os.chdir(fd).
2866
2867
[clinic start generated code]*/
2868
2869
static PyObject *
2870
os_fchdir_impl(PyObject *module, int fd)
2871
/*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
2872
0
{
2873
0
    if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
2874
0
        return NULL;
2875
0
    }
2876
0
    return posix_fildes_fd(fd, fchdir);
2877
0
}
2878
#endif /* HAVE_FCHDIR */
2879
2880
2881
/*[clinic input]
2882
os.chmod
2883
2884
    path: path_t(allow_fd='PATH_HAVE_FCHMOD')
2885
        Path to be modified.  May always be specified as a str, bytes, or a path-like object.
2886
        On some platforms, path may also be specified as an open file descriptor.
2887
        If this functionality is unavailable, using it raises an exception.
2888
2889
    mode: int
2890
        Operating-system mode bitfield.
2891
2892
    *
2893
2894
    dir_fd : dir_fd(requires='fchmodat') = None
2895
        If not None, it should be a file descriptor open to a directory,
2896
        and path should be relative; path will then be relative to that
2897
        directory.
2898
2899
    follow_symlinks: bool = True
2900
        If False, and the last element of the path is a symbolic link,
2901
        chmod will modify the symbolic link itself instead of the file
2902
        the link points to.
2903
2904
Change the access permissions of a file.
2905
2906
It is an error to use dir_fd or follow_symlinks when specifying path as
2907
  an open file descriptor.
2908
dir_fd and follow_symlinks may not be implemented on your platform.
2909
  If they are unavailable, using them will raise a NotImplementedError.
2910
2911
[clinic start generated code]*/
2912
2913
static PyObject *
2914
os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
2915
              int follow_symlinks)
2916
/*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/
2917
0
{
2918
0
    int result;
2919
2920
#ifdef MS_WINDOWS
2921
    DWORD attr;
2922
#endif
2923
2924
0
#ifdef HAVE_FCHMODAT
2925
0
    int fchmodat_nofollow_unsupported = 0;
2926
0
#endif
2927
2928
#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
2929
    if (follow_symlinks_specified("chmod", follow_symlinks))
2930
        return NULL;
2931
#endif
2932
2933
0
    if (PySys_Audit("os.chmod", "Oii", path->object, mode,
2934
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
2935
0
        return NULL;
2936
0
    }
2937
2938
#ifdef MS_WINDOWS
2939
    Py_BEGIN_ALLOW_THREADS
2940
    attr = GetFileAttributesW(path->wide);
2941
    if (attr == INVALID_FILE_ATTRIBUTES)
2942
        result = 0;
2943
    else {
2944
        if (mode & _S_IWRITE)
2945
            attr &= ~FILE_ATTRIBUTE_READONLY;
2946
        else
2947
            attr |= FILE_ATTRIBUTE_READONLY;
2948
        result = SetFileAttributesW(path->wide, attr);
2949
    }
2950
    Py_END_ALLOW_THREADS
2951
2952
    if (!result) {
2953
        return path_error(path);
2954
    }
2955
#else /* MS_WINDOWS */
2956
0
    Py_BEGIN_ALLOW_THREADS
2957
0
#ifdef HAVE_FCHMOD
2958
0
    if (path->fd != -1)
2959
0
        result = fchmod(path->fd, mode);
2960
0
    else
2961
0
#endif
2962
#ifdef HAVE_LCHMOD
2963
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2964
        result = lchmod(path->narrow, mode);
2965
    else
2966
#endif
2967
0
#ifdef HAVE_FCHMODAT
2968
0
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2969
        /*
2970
         * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
2971
         * The documentation specifically shows how to use it,
2972
         * and then says it isn't implemented yet.
2973
         * (true on linux with glibc 2.15, and openindiana 3.x)
2974
         *
2975
         * Once it is supported, os.chmod will automatically
2976
         * support dir_fd and follow_symlinks=False.  (Hopefully.)
2977
         * Until then, we need to be careful what exception we raise.
2978
         */
2979
0
        result = fchmodat(dir_fd, path->narrow, mode,
2980
0
                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2981
        /*
2982
         * But wait!  We can't throw the exception without allowing threads,
2983
         * and we can't do that in this nested scope.  (Macro trickery, sigh.)
2984
         */
2985
0
        fchmodat_nofollow_unsupported =
2986
0
                         result &&
2987
0
                         ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
2988
0
                         !follow_symlinks;
2989
0
    }
2990
0
    else
2991
0
#endif
2992
0
        result = chmod(path->narrow, mode);
2993
0
    Py_END_ALLOW_THREADS
2994
2995
0
    if (result) {
2996
0
#ifdef HAVE_FCHMODAT
2997
0
        if (fchmodat_nofollow_unsupported) {
2998
0
            if (dir_fd != DEFAULT_DIR_FD)
2999
0
                dir_fd_and_follow_symlinks_invalid("chmod",
3000
0
                                                   dir_fd, follow_symlinks);
3001
0
            else
3002
0
                follow_symlinks_specified("chmod", follow_symlinks);
3003
0
            return NULL;
3004
0
        }
3005
0
        else
3006
0
#endif
3007
0
        return path_error(path);
3008
0
    }
3009
0
#endif
3010
3011
0
    Py_RETURN_NONE;
3012
0
}
3013
3014
3015
#ifdef HAVE_FCHMOD
3016
/*[clinic input]
3017
os.fchmod
3018
3019
    fd: int
3020
    mode: int
3021
3022
Change the access permissions of the file given by file descriptor fd.
3023
3024
Equivalent to os.chmod(fd, mode).
3025
[clinic start generated code]*/
3026
3027
static PyObject *
3028
os_fchmod_impl(PyObject *module, int fd, int mode)
3029
/*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/
3030
0
{
3031
0
    int res;
3032
0
    int async_err = 0;
3033
3034
0
    if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
3035
0
        return NULL;
3036
0
    }
3037
3038
0
    do {
3039
0
        Py_BEGIN_ALLOW_THREADS
3040
0
        res = fchmod(fd, mode);
3041
0
        Py_END_ALLOW_THREADS
3042
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3043
0
    if (res != 0)
3044
0
        return (!async_err) ? posix_error() : NULL;
3045
3046
0
    Py_RETURN_NONE;
3047
0
}
3048
#endif /* HAVE_FCHMOD */
3049
3050
3051
#ifdef HAVE_LCHMOD
3052
/*[clinic input]
3053
os.lchmod
3054
3055
    path: path_t
3056
    mode: int
3057
3058
Change the access permissions of a file, without following symbolic links.
3059
3060
If path is a symlink, this affects the link itself rather than the target.
3061
Equivalent to chmod(path, mode, follow_symlinks=False)."
3062
[clinic start generated code]*/
3063
3064
static PyObject *
3065
os_lchmod_impl(PyObject *module, path_t *path, int mode)
3066
/*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
3067
{
3068
    int res;
3069
    if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
3070
        return NULL;
3071
    }
3072
    Py_BEGIN_ALLOW_THREADS
3073
    res = lchmod(path->narrow, mode);
3074
    Py_END_ALLOW_THREADS
3075
    if (res < 0) {
3076
        path_error(path);
3077
        return NULL;
3078
    }
3079
    Py_RETURN_NONE;
3080
}
3081
#endif /* HAVE_LCHMOD */
3082
3083
3084
#ifdef HAVE_CHFLAGS
3085
/*[clinic input]
3086
os.chflags
3087
3088
    path: path_t
3089
    flags: unsigned_long(bitwise=True)
3090
    follow_symlinks: bool=True
3091
3092
Set file flags.
3093
3094
If follow_symlinks is False, and the last element of the path is a symbolic
3095
  link, chflags will change flags on the symbolic link itself instead of the
3096
  file the link points to.
3097
follow_symlinks may not be implemented on your platform.  If it is
3098
unavailable, using it will raise a NotImplementedError.
3099
3100
[clinic start generated code]*/
3101
3102
static PyObject *
3103
os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
3104
                int follow_symlinks)
3105
/*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
3106
{
3107
    int result;
3108
3109
#ifndef HAVE_LCHFLAGS
3110
    if (follow_symlinks_specified("chflags", follow_symlinks))
3111
        return NULL;
3112
#endif
3113
3114
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3115
        return NULL;
3116
    }
3117
3118
    Py_BEGIN_ALLOW_THREADS
3119
#ifdef HAVE_LCHFLAGS
3120
    if (!follow_symlinks)
3121
        result = lchflags(path->narrow, flags);
3122
    else
3123
#endif
3124
        result = chflags(path->narrow, flags);
3125
    Py_END_ALLOW_THREADS
3126
3127
    if (result)
3128
        return path_error(path);
3129
3130
    Py_RETURN_NONE;
3131
}
3132
#endif /* HAVE_CHFLAGS */
3133
3134
3135
#ifdef HAVE_LCHFLAGS
3136
/*[clinic input]
3137
os.lchflags
3138
3139
    path: path_t
3140
    flags: unsigned_long(bitwise=True)
3141
3142
Set file flags.
3143
3144
This function will not follow symbolic links.
3145
Equivalent to chflags(path, flags, follow_symlinks=False).
3146
[clinic start generated code]*/
3147
3148
static PyObject *
3149
os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
3150
/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
3151
{
3152
    int res;
3153
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3154
        return NULL;
3155
    }
3156
    Py_BEGIN_ALLOW_THREADS
3157
    res = lchflags(path->narrow, flags);
3158
    Py_END_ALLOW_THREADS
3159
    if (res < 0) {
3160
        return path_error(path);
3161
    }
3162
    Py_RETURN_NONE;
3163
}
3164
#endif /* HAVE_LCHFLAGS */
3165
3166
3167
#ifdef HAVE_CHROOT
3168
/*[clinic input]
3169
os.chroot
3170
    path: path_t
3171
3172
Change root directory to path.
3173
3174
[clinic start generated code]*/
3175
3176
static PyObject *
3177
os_chroot_impl(PyObject *module, path_t *path)
3178
/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
3179
0
{
3180
0
    int res;
3181
0
    Py_BEGIN_ALLOW_THREADS
3182
0
    res = chroot(path->narrow);
3183
0
    Py_END_ALLOW_THREADS
3184
0
    if (res < 0)
3185
0
        return path_error(path);
3186
0
    Py_RETURN_NONE;
3187
0
}
3188
#endif /* HAVE_CHROOT */
3189
3190
3191
#ifdef HAVE_FSYNC
3192
/*[clinic input]
3193
os.fsync
3194
3195
    fd: fildes
3196
3197
Force write of fd to disk.
3198
[clinic start generated code]*/
3199
3200
static PyObject *
3201
os_fsync_impl(PyObject *module, int fd)
3202
/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
3203
0
{
3204
0
    return posix_fildes_fd(fd, fsync);
3205
0
}
3206
#endif /* HAVE_FSYNC */
3207
3208
3209
#ifdef HAVE_SYNC
3210
/*[clinic input]
3211
os.sync
3212
3213
Force write of everything to disk.
3214
[clinic start generated code]*/
3215
3216
static PyObject *
3217
os_sync_impl(PyObject *module)
3218
/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
3219
0
{
3220
0
    Py_BEGIN_ALLOW_THREADS
3221
0
    sync();
3222
0
    Py_END_ALLOW_THREADS
3223
0
    Py_RETURN_NONE;
3224
0
}
3225
#endif /* HAVE_SYNC */
3226
3227
3228
#ifdef HAVE_FDATASYNC
3229
#ifdef __hpux
3230
extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
3231
#endif
3232
3233
/*[clinic input]
3234
os.fdatasync
3235
3236
    fd: fildes
3237
3238
Force write of fd to disk without forcing update of metadata.
3239
[clinic start generated code]*/
3240
3241
static PyObject *
3242
os_fdatasync_impl(PyObject *module, int fd)
3243
/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
3244
0
{
3245
0
    return posix_fildes_fd(fd, fdatasync);
3246
0
}
3247
#endif /* HAVE_FDATASYNC */
3248
3249
3250
#ifdef HAVE_CHOWN
3251
/*[clinic input]
3252
os.chown
3253
3254
    path : path_t(allow_fd='PATH_HAVE_FCHOWN')
3255
        Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
3256
3257
    uid: uid_t
3258
3259
    gid: gid_t
3260
3261
    *
3262
3263
    dir_fd : dir_fd(requires='fchownat') = None
3264
        If not None, it should be a file descriptor open to a directory,
3265
        and path should be relative; path will then be relative to that
3266
        directory.
3267
3268
    follow_symlinks: bool = True
3269
        If False, and the last element of the path is a symbolic link,
3270
        stat will examine the symbolic link itself instead of the file
3271
        the link points to.
3272
3273
Change the owner and group id of path to the numeric uid and gid.\
3274
3275
path may always be specified as a string.
3276
On some platforms, path may also be specified as an open file descriptor.
3277
  If this functionality is unavailable, using it raises an exception.
3278
If dir_fd is not None, it should be a file descriptor open to a directory,
3279
  and path should be relative; path will then be relative to that directory.
3280
If follow_symlinks is False, and the last element of the path is a symbolic
3281
  link, chown will modify the symbolic link itself instead of the file the
3282
  link points to.
3283
It is an error to use dir_fd or follow_symlinks when specifying path as
3284
  an open file descriptor.
3285
dir_fd and follow_symlinks may not be implemented on your platform.
3286
  If they are unavailable, using them will raise a NotImplementedError.
3287
3288
[clinic start generated code]*/
3289
3290
static PyObject *
3291
os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
3292
              int dir_fd, int follow_symlinks)
3293
/*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
3294
0
{
3295
0
    int result;
3296
3297
#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
3298
    if (follow_symlinks_specified("chown", follow_symlinks))
3299
        return NULL;
3300
#endif
3301
0
    if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
3302
0
        fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
3303
0
        return NULL;
3304
3305
#ifdef __APPLE__
3306
    /*
3307
     * This is for Mac OS X 10.3, which doesn't have lchown.
3308
     * (But we still have an lchown symbol because of weak-linking.)
3309
     * It doesn't have fchownat either.  So there's no possibility
3310
     * of a graceful failover.
3311
     */
3312
    if ((!follow_symlinks) && (lchown == NULL)) {
3313
        follow_symlinks_specified("chown", follow_symlinks);
3314
        return NULL;
3315
    }
3316
#endif
3317
3318
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
3319
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3320
0
        return NULL;
3321
0
    }
3322
3323
0
    Py_BEGIN_ALLOW_THREADS
3324
0
#ifdef HAVE_FCHOWN
3325
0
    if (path->fd != -1)
3326
0
        result = fchown(path->fd, uid, gid);
3327
0
    else
3328
0
#endif
3329
0
#ifdef HAVE_LCHOWN
3330
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3331
0
        result = lchown(path->narrow, uid, gid);
3332
0
    else
3333
0
#endif
3334
0
#ifdef HAVE_FCHOWNAT
3335
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))
3336
0
        result = fchownat(dir_fd, path->narrow, uid, gid,
3337
0
                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3338
0
    else
3339
0
#endif
3340
0
        result = chown(path->narrow, uid, gid);
3341
0
    Py_END_ALLOW_THREADS
3342
3343
0
    if (result)
3344
0
        return path_error(path);
3345
3346
0
    Py_RETURN_NONE;
3347
0
}
3348
#endif /* HAVE_CHOWN */
3349
3350
3351
#ifdef HAVE_FCHOWN
3352
/*[clinic input]
3353
os.fchown
3354
3355
    fd: int
3356
    uid: uid_t
3357
    gid: gid_t
3358
3359
Change the owner and group id of the file specified by file descriptor.
3360
3361
Equivalent to os.chown(fd, uid, gid).
3362
3363
[clinic start generated code]*/
3364
3365
static PyObject *
3366
os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
3367
/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
3368
0
{
3369
0
    int res;
3370
0
    int async_err = 0;
3371
3372
0
    if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
3373
0
        return NULL;
3374
0
    }
3375
3376
0
    do {
3377
0
        Py_BEGIN_ALLOW_THREADS
3378
0
        res = fchown(fd, uid, gid);
3379
0
        Py_END_ALLOW_THREADS
3380
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3381
0
    if (res != 0)
3382
0
        return (!async_err) ? posix_error() : NULL;
3383
3384
0
    Py_RETURN_NONE;
3385
0
}
3386
#endif /* HAVE_FCHOWN */
3387
3388
3389
#ifdef HAVE_LCHOWN
3390
/*[clinic input]
3391
os.lchown
3392
3393
    path : path_t
3394
    uid: uid_t
3395
    gid: gid_t
3396
3397
Change the owner and group id of path to the numeric uid and gid.
3398
3399
This function will not follow symbolic links.
3400
Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
3401
[clinic start generated code]*/
3402
3403
static PyObject *
3404
os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
3405
/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
3406
0
{
3407
0
    int res;
3408
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
3409
0
        return NULL;
3410
0
    }
3411
0
    Py_BEGIN_ALLOW_THREADS
3412
0
    res = lchown(path->narrow, uid, gid);
3413
0
    Py_END_ALLOW_THREADS
3414
0
    if (res < 0) {
3415
0
        return path_error(path);
3416
0
    }
3417
0
    Py_RETURN_NONE;
3418
0
}
3419
#endif /* HAVE_LCHOWN */
3420
3421
3422
static PyObject *
3423
posix_getcwd(int use_bytes)
3424
0
{
3425
#ifdef MS_WINDOWS
3426
    wchar_t wbuf[MAXPATHLEN];
3427
    wchar_t *wbuf2 = wbuf;
3428
    DWORD len;
3429
3430
    Py_BEGIN_ALLOW_THREADS
3431
    len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
3432
    /* If the buffer is large enough, len does not include the
3433
       terminating \0. If the buffer is too small, len includes
3434
       the space needed for the terminator. */
3435
    if (len >= Py_ARRAY_LENGTH(wbuf)) {
3436
        if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
3437
            wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
3438
        }
3439
        else {
3440
            wbuf2 = NULL;
3441
        }
3442
        if (wbuf2) {
3443
            len = GetCurrentDirectoryW(len, wbuf2);
3444
        }
3445
    }
3446
    Py_END_ALLOW_THREADS
3447
3448
    if (!wbuf2) {
3449
        PyErr_NoMemory();
3450
        return NULL;
3451
    }
3452
    if (!len) {
3453
        if (wbuf2 != wbuf)
3454
            PyMem_RawFree(wbuf2);
3455
        return PyErr_SetFromWindowsErr(0);
3456
    }
3457
3458
    PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
3459
    if (wbuf2 != wbuf) {
3460
        PyMem_RawFree(wbuf2);
3461
    }
3462
3463
    if (use_bytes) {
3464
        if (resobj == NULL) {
3465
            return NULL;
3466
        }
3467
        Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
3468
    }
3469
3470
    return resobj;
3471
#else
3472
0
    const size_t chunk = 1024;
3473
3474
0
    char *buf = NULL;
3475
0
    char *cwd = NULL;
3476
0
    size_t buflen = 0;
3477
3478
0
    Py_BEGIN_ALLOW_THREADS
3479
0
    do {
3480
0
        char *newbuf;
3481
0
        if (buflen <= PY_SSIZE_T_MAX - chunk) {
3482
0
            buflen += chunk;
3483
0
            newbuf = PyMem_RawRealloc(buf, buflen);
3484
0
        }
3485
0
        else {
3486
0
            newbuf = NULL;
3487
0
        }
3488
0
        if (newbuf == NULL) {
3489
0
            PyMem_RawFree(buf);
3490
0
            buf = NULL;
3491
0
            break;
3492
0
        }
3493
0
        buf = newbuf;
3494
3495
0
        cwd = getcwd(buf, buflen);
3496
0
    } while (cwd == NULL && errno == ERANGE);
3497
0
    Py_END_ALLOW_THREADS
3498
3499
0
    if (buf == NULL) {
3500
0
        return PyErr_NoMemory();
3501
0
    }
3502
0
    if (cwd == NULL) {
3503
0
        PyMem_RawFree(buf);
3504
0
        return posix_error();
3505
0
    }
3506
3507
0
    PyObject *obj;
3508
0
    if (use_bytes) {
3509
0
        obj = PyBytes_FromStringAndSize(buf, strlen(buf));
3510
0
    }
3511
0
    else {
3512
0
        obj = PyUnicode_DecodeFSDefault(buf);
3513
0
    }
3514
0
    PyMem_RawFree(buf);
3515
3516
0
    return obj;
3517
0
#endif   /* !MS_WINDOWS */
3518
0
}
3519
3520
3521
/*[clinic input]
3522
os.getcwd
3523
3524
Return a unicode string representing the current working directory.
3525
[clinic start generated code]*/
3526
3527
static PyObject *
3528
os_getcwd_impl(PyObject *module)
3529
/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
3530
0
{
3531
0
    return posix_getcwd(0);
3532
0
}
3533
3534
3535
/*[clinic input]
3536
os.getcwdb
3537
3538
Return a bytes string representing the current working directory.
3539
[clinic start generated code]*/
3540
3541
static PyObject *
3542
os_getcwdb_impl(PyObject *module)
3543
/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
3544
0
{
3545
0
    return posix_getcwd(1);
3546
0
}
3547
3548
3549
#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
3550
#define HAVE_LINK 1
3551
#endif
3552
3553
#ifdef HAVE_LINK
3554
/*[clinic input]
3555
3556
os.link
3557
3558
    src : path_t
3559
    dst : path_t
3560
    *
3561
    src_dir_fd : dir_fd = None
3562
    dst_dir_fd : dir_fd = None
3563
    follow_symlinks: bool = True
3564
3565
Create a hard link to a file.
3566
3567
If either src_dir_fd or dst_dir_fd is not None, it should be a file
3568
  descriptor open to a directory, and the respective path string (src or dst)
3569
  should be relative; the path will then be relative to that directory.
3570
If follow_symlinks is False, and the last element of src is a symbolic
3571
  link, link will create a link to the symbolic link itself instead of the
3572
  file the link points to.
3573
src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
3574
  platform.  If they are unavailable, using them will raise a
3575
  NotImplementedError.
3576
[clinic start generated code]*/
3577
3578
static PyObject *
3579
os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
3580
             int dst_dir_fd, int follow_symlinks)
3581
/*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/
3582
0
{
3583
#ifdef MS_WINDOWS
3584
    BOOL result = FALSE;
3585
#else
3586
0
    int result;
3587
0
#endif
3588
3589
#ifndef HAVE_LINKAT
3590
    if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
3591
        argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
3592
        return NULL;
3593
    }
3594
#endif
3595
3596
0
#ifndef MS_WINDOWS
3597
0
    if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
3598
0
        PyErr_SetString(PyExc_NotImplementedError,
3599
0
                        "link: src and dst must be the same type");
3600
0
        return NULL;
3601
0
    }
3602
0
#endif
3603
3604
0
    if (PySys_Audit("os.link", "OOii", src->object, dst->object,
3605
0
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
3606
0
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
3607
0
        return NULL;
3608
0
    }
3609
3610
#ifdef MS_WINDOWS
3611
    Py_BEGIN_ALLOW_THREADS
3612
    result = CreateHardLinkW(dst->wide, src->wide, NULL);
3613
    Py_END_ALLOW_THREADS
3614
3615
    if (!result)
3616
        return path_error2(src, dst);
3617
#else
3618
0
    Py_BEGIN_ALLOW_THREADS
3619
0
#ifdef HAVE_LINKAT
3620
0
    if ((src_dir_fd != DEFAULT_DIR_FD) ||
3621
0
        (dst_dir_fd != DEFAULT_DIR_FD) ||
3622
0
        (!follow_symlinks))
3623
0
        result = linkat(src_dir_fd, src->narrow,
3624
0
            dst_dir_fd, dst->narrow,
3625
0
            follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
3626
0
    else
3627
0
#endif /* HAVE_LINKAT */
3628
0
        result = link(src->narrow, dst->narrow);
3629
0
    Py_END_ALLOW_THREADS
3630
3631
0
    if (result)
3632
0
        return path_error2(src, dst);
3633
0
#endif /* MS_WINDOWS */
3634
3635
0
    Py_RETURN_NONE;
3636
0
}
3637
#endif
3638
3639
3640
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
3641
static PyObject *
3642
_listdir_windows_no_opendir(path_t *path, PyObject *list)
3643
{
3644
    PyObject *v;
3645
    HANDLE hFindFile = INVALID_HANDLE_VALUE;
3646
    BOOL result;
3647
    wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
3648
    /* only claim to have space for MAX_PATH */
3649
    Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
3650
    wchar_t *wnamebuf = NULL;
3651
3652
    WIN32_FIND_DATAW wFileData;
3653
    const wchar_t *po_wchars;
3654
3655
    if (!path->wide) { /* Default arg: "." */
3656
        po_wchars = L".";
3657
        len = 1;
3658
    } else {
3659
        po_wchars = path->wide;
3660
        len = wcslen(path->wide);
3661
    }
3662
    /* The +5 is so we can append "\\*.*\0" */
3663
    wnamebuf = PyMem_New(wchar_t, len + 5);
3664
    if (!wnamebuf) {
3665
        PyErr_NoMemory();
3666
        goto exit;
3667
    }
3668
    wcscpy(wnamebuf, po_wchars);
3669
    if (len > 0) {
3670
        wchar_t wch = wnamebuf[len-1];
3671
        if (wch != SEP && wch != ALTSEP && wch != L':')
3672
            wnamebuf[len++] = SEP;
3673
        wcscpy(wnamebuf + len, L"*.*");
3674
    }
3675
    if ((list = PyList_New(0)) == NULL) {
3676
        goto exit;
3677
    }
3678
    Py_BEGIN_ALLOW_THREADS
3679
    hFindFile = FindFirstFileW(wnamebuf, &wFileData);
3680
    Py_END_ALLOW_THREADS
3681
    if (hFindFile == INVALID_HANDLE_VALUE) {
3682
        int error = GetLastError();
3683
        if (error == ERROR_FILE_NOT_FOUND)
3684
            goto exit;
3685
        Py_DECREF(list);
3686
        list = path_error(path);
3687
        goto exit;
3688
    }
3689
    do {
3690
        /* Skip over . and .. */
3691
        if (wcscmp(wFileData.cFileName, L".") != 0 &&
3692
            wcscmp(wFileData.cFileName, L"..") != 0) {
3693
            v = PyUnicode_FromWideChar(wFileData.cFileName,
3694
                                       wcslen(wFileData.cFileName));
3695
            if (path->narrow && v) {
3696
                Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
3697
            }
3698
            if (v == NULL) {
3699
                Py_DECREF(list);
3700
                list = NULL;
3701
                break;
3702
            }
3703
            if (PyList_Append(list, v) != 0) {
3704
                Py_DECREF(v);
3705
                Py_DECREF(list);
3706
                list = NULL;
3707
                break;
3708
            }
3709
            Py_DECREF(v);
3710
        }
3711
        Py_BEGIN_ALLOW_THREADS
3712
        result = FindNextFileW(hFindFile, &wFileData);
3713
        Py_END_ALLOW_THREADS
3714
        /* FindNextFile sets error to ERROR_NO_MORE_FILES if
3715
           it got to the end of the directory. */
3716
        if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
3717
            Py_DECREF(list);
3718
            list = path_error(path);
3719
            goto exit;
3720
        }
3721
    } while (result == TRUE);
3722
3723
exit:
3724
    if (hFindFile != INVALID_HANDLE_VALUE) {
3725
        if (FindClose(hFindFile) == FALSE) {
3726
            if (list != NULL) {
3727
                Py_DECREF(list);
3728
                list = path_error(path);
3729
            }
3730
        }
3731
    }
3732
    PyMem_Free(wnamebuf);
3733
3734
    return list;
3735
}  /* end of _listdir_windows_no_opendir */
3736
3737
#else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
3738
3739
static PyObject *
3740
_posix_listdir(path_t *path, PyObject *list)
3741
29
{
3742
29
    PyObject *v;
3743
29
    DIR *dirp = NULL;
3744
29
    struct dirent *ep;
3745
29
    int return_str; /* if false, return bytes */
3746
29
#ifdef HAVE_FDOPENDIR
3747
29
    int fd = -1;
3748
29
#endif
3749
3750
29
    errno = 0;
3751
29
#ifdef HAVE_FDOPENDIR
3752
29
    if (path->fd != -1) {
3753
        /* closedir() closes the FD, so we duplicate it */
3754
0
        fd = _Py_dup(path->fd);
3755
0
        if (fd == -1)
3756
0
            return NULL;
3757
3758
0
        return_str = 1;
3759
3760
0
        Py_BEGIN_ALLOW_THREADS
3761
0
        dirp = fdopendir(fd);
3762
0
        Py_END_ALLOW_THREADS
3763
0
    }
3764
29
    else
3765
29
#endif
3766
29
    {
3767
29
        const char *name;
3768
29
        if (path->narrow) {
3769
29
            name = path->narrow;
3770
            /* only return bytes if they specified a bytes-like object */
3771
29
            return_str = !PyObject_CheckBuffer(path->object);
3772
29
        }
3773
0
        else {
3774
0
            name = ".";
3775
0
            return_str = 1;
3776
0
        }
3777
3778
29
        Py_BEGIN_ALLOW_THREADS
3779
29
        dirp = opendir(name);
3780
29
        Py_END_ALLOW_THREADS
3781
29
    }
3782
3783
29
    if (dirp == NULL) {
3784
0
        list = path_error(path);
3785
0
#ifdef HAVE_FDOPENDIR
3786
0
        if (fd != -1) {
3787
0
            Py_BEGIN_ALLOW_THREADS
3788
0
            close(fd);
3789
0
            Py_END_ALLOW_THREADS
3790
0
        }
3791
0
#endif
3792
0
        goto exit;
3793
0
    }
3794
29
    if ((list = PyList_New(0)) == NULL) {
3795
0
        goto exit;
3796
0
    }
3797
4.71k
    for (;;) {
3798
4.71k
        errno = 0;
3799
4.71k
        Py_BEGIN_ALLOW_THREADS
3800
4.71k
        ep = readdir(dirp);
3801
4.71k
        Py_END_ALLOW_THREADS
3802
4.71k
        if (ep == NULL) {
3803
29
            if (errno == 0) {
3804
29
                break;
3805
29
            } else {
3806
0
                Py_DECREF(list);
3807
0
                list = path_error(path);
3808
0
                goto exit;
3809
0
            }
3810
29
        }
3811
4.68k
        if (ep->d_name[0] == '.' &&
3812
4.68k
            (NAMLEN(ep) == 1 ||
3813
58
             (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
3814
58
            continue;
3815
4.62k
        if (return_str)
3816
4.62k
            v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
3817
0
        else
3818
0
            v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
3819
4.62k
        if (v == NULL) {
3820
0
            Py_CLEAR(list);
3821
0
            break;
3822
0
        }
3823
4.62k
        if (PyList_Append(list, v) != 0) {
3824
0
            Py_DECREF(v);
3825
0
            Py_CLEAR(list);
3826
0
            break;
3827
0
        }
3828
4.62k
        Py_DECREF(v);
3829
4.62k
    }
3830
3831
29
exit:
3832
29
    if (dirp != NULL) {
3833
29
        Py_BEGIN_ALLOW_THREADS
3834
29
#ifdef HAVE_FDOPENDIR
3835
29
        if (fd > -1)
3836
0
            rewinddir(dirp);
3837
29
#endif
3838
29
        closedir(dirp);
3839
29
        Py_END_ALLOW_THREADS
3840
29
    }
3841
3842
29
    return list;
3843
29
}  /* end of _posix_listdir */
3844
#endif  /* which OS */
3845
3846
3847
/*[clinic input]
3848
os.listdir
3849
3850
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
3851
3852
Return a list containing the names of the files in the directory.
3853
3854
path can be specified as either str, bytes, or a path-like object.  If path is bytes,
3855
  the filenames returned will also be bytes; in all other circumstances
3856
  the filenames returned will be str.
3857
If path is None, uses the path='.'.
3858
On some platforms, path may also be specified as an open file descriptor;\
3859
  the file descriptor must refer to a directory.
3860
  If this functionality is unavailable, using it raises NotImplementedError.
3861
3862
The list is in arbitrary order.  It does not include the special
3863
entries '.' and '..' even if they are present in the directory.
3864
3865
3866
[clinic start generated code]*/
3867
3868
static PyObject *
3869
os_listdir_impl(PyObject *module, path_t *path)
3870
/*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
3871
29
{
3872
29
    if (PySys_Audit("os.listdir", "O",
3873
29
                    path->object ? path->object : Py_None) < 0) {
3874
0
        return NULL;
3875
0
    }
3876
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
3877
    return _listdir_windows_no_opendir(path, NULL);
3878
#else
3879
29
    return _posix_listdir(path, NULL);
3880
29
#endif
3881
29
}
3882
3883
#ifdef MS_WINDOWS
3884
/* A helper function for abspath on win32 */
3885
/*[clinic input]
3886
os._getfullpathname
3887
3888
    path: path_t
3889
    /
3890
3891
[clinic start generated code]*/
3892
3893
static PyObject *
3894
os__getfullpathname_impl(PyObject *module, path_t *path)
3895
/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
3896
{
3897
    wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
3898
    wchar_t *wtemp;
3899
    DWORD result;
3900
    PyObject *v;
3901
3902
    result = GetFullPathNameW(path->wide,
3903
                              Py_ARRAY_LENGTH(woutbuf),
3904
                              woutbuf, &wtemp);
3905
    if (result > Py_ARRAY_LENGTH(woutbuf)) {
3906
        woutbufp = PyMem_New(wchar_t, result);
3907
        if (!woutbufp)
3908
            return PyErr_NoMemory();
3909
        result = GetFullPathNameW(path->wide, result, woutbufp, &wtemp);
3910
    }
3911
    if (result) {
3912
        v = PyUnicode_FromWideChar(woutbufp, wcslen(woutbufp));
3913
        if (path->narrow)
3914
            Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
3915
    } else
3916
        v = win32_error_object("GetFullPathNameW", path->object);
3917
    if (woutbufp != woutbuf)
3918
        PyMem_Free(woutbufp);
3919
    return v;
3920
}
3921
3922
3923
/*[clinic input]
3924
os._getfinalpathname
3925
3926
    path: path_t
3927
    /
3928
3929
A helper function for samepath on windows.
3930
[clinic start generated code]*/
3931
3932
static PyObject *
3933
os__getfinalpathname_impl(PyObject *module, path_t *path)
3934
/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
3935
{
3936
    HANDLE hFile;
3937
    wchar_t buf[MAXPATHLEN], *target_path = buf;
3938
    int buf_size = Py_ARRAY_LENGTH(buf);
3939
    int result_length;
3940
    PyObject *result;
3941
3942
    Py_BEGIN_ALLOW_THREADS
3943
    hFile = CreateFileW(
3944
        path->wide,
3945
        0, /* desired access */
3946
        0, /* share mode */
3947
        NULL, /* security attributes */
3948
        OPEN_EXISTING,
3949
        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
3950
        FILE_FLAG_BACKUP_SEMANTICS,
3951
        NULL);
3952
    Py_END_ALLOW_THREADS
3953
3954
    if (hFile == INVALID_HANDLE_VALUE) {
3955
        return win32_error_object("CreateFileW", path->object);
3956
    }
3957
3958
    /* We have a good handle to the target, use it to determine the
3959
       target path name. */
3960
    while (1) {
3961
        Py_BEGIN_ALLOW_THREADS
3962
        result_length = GetFinalPathNameByHandleW(hFile, target_path,
3963
                                                  buf_size, VOLUME_NAME_DOS);
3964
        Py_END_ALLOW_THREADS
3965
3966
        if (!result_length) {
3967
            result = win32_error_object("GetFinalPathNameByHandleW",
3968
                                         path->object);
3969
            goto cleanup;
3970
        }
3971
3972
        if (result_length < buf_size) {
3973
            break;
3974
        }
3975
3976
        wchar_t *tmp;
3977
        tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
3978
                            result_length * sizeof(*tmp));
3979
        if (!tmp) {
3980
            result = PyErr_NoMemory();
3981
            goto cleanup;
3982
        }
3983
3984
        buf_size = result_length;
3985
        target_path = tmp;
3986
    }
3987
3988
    result = PyUnicode_FromWideChar(target_path, result_length);
3989
    if (result && path->narrow) {
3990
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
3991
    }
3992
3993
cleanup:
3994
    if (target_path != buf) {
3995
        PyMem_Free(target_path);
3996
    }
3997
    CloseHandle(hFile);
3998
    return result;
3999
}
4000
4001
4002
/*[clinic input]
4003
os._getvolumepathname
4004
4005
    path: path_t
4006
4007
A helper function for ismount on Win32.
4008
[clinic start generated code]*/
4009
4010
static PyObject *
4011
os__getvolumepathname_impl(PyObject *module, path_t *path)
4012
/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
4013
{
4014
    PyObject *result;
4015
    wchar_t *mountpath=NULL;
4016
    size_t buflen;
4017
    BOOL ret;
4018
4019
    /* Volume path should be shorter than entire path */
4020
    buflen = Py_MAX(path->length, MAX_PATH);
4021
4022
    if (buflen > PY_DWORD_MAX) {
4023
        PyErr_SetString(PyExc_OverflowError, "path too long");
4024
        return NULL;
4025
    }
4026
4027
    mountpath = PyMem_New(wchar_t, buflen);
4028
    if (mountpath == NULL)
4029
        return PyErr_NoMemory();
4030
4031
    Py_BEGIN_ALLOW_THREADS
4032
    ret = GetVolumePathNameW(path->wide, mountpath,
4033
                             Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
4034
    Py_END_ALLOW_THREADS
4035
4036
    if (!ret) {
4037
        result = win32_error_object("_getvolumepathname", path->object);
4038
        goto exit;
4039
    }
4040
    result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
4041
    if (path->narrow)
4042
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4043
4044
exit:
4045
    PyMem_Free(mountpath);
4046
    return result;
4047
}
4048
4049
#endif /* MS_WINDOWS */
4050
4051
4052
/*[clinic input]
4053
os.mkdir
4054
4055
    path : path_t
4056
4057
    mode: int = 0o777
4058
4059
    *
4060
4061
    dir_fd : dir_fd(requires='mkdirat') = None
4062
4063
# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
4064
4065
Create a directory.
4066
4067
If dir_fd is not None, it should be a file descriptor open to a directory,
4068
  and path should be relative; path will then be relative to that directory.
4069
dir_fd may not be implemented on your platform.
4070
  If it is unavailable, using it will raise a NotImplementedError.
4071
4072
The mode argument is ignored on Windows.
4073
[clinic start generated code]*/
4074
4075
static PyObject *
4076
os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
4077
/*[clinic end generated code: output=a70446903abe821f input=e965f68377e9b1ce]*/
4078
0
{
4079
0
    int result;
4080
4081
0
    if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
4082
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4083
0
        return NULL;
4084
0
    }
4085
4086
#ifdef MS_WINDOWS
4087
    Py_BEGIN_ALLOW_THREADS
4088
    result = CreateDirectoryW(path->wide, NULL);
4089
    Py_END_ALLOW_THREADS
4090
4091
    if (!result)
4092
        return path_error(path);
4093
#else
4094
0
    Py_BEGIN_ALLOW_THREADS
4095
0
#if HAVE_MKDIRAT
4096
0
    if (dir_fd != DEFAULT_DIR_FD)
4097
0
        result = mkdirat(dir_fd, path->narrow, mode);
4098
0
    else
4099
0
#endif
4100
#if defined(__WATCOMC__) && !defined(__QNX__)
4101
        result = mkdir(path->narrow);
4102
#else
4103
0
        result = mkdir(path->narrow, mode);
4104
0
#endif
4105
0
    Py_END_ALLOW_THREADS
4106
0
    if (result < 0)
4107
0
        return path_error(path);
4108
0
#endif /* MS_WINDOWS */
4109
0
    Py_RETURN_NONE;
4110
0
}
4111
4112
4113
/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
4114
#if defined(HAVE_SYS_RESOURCE_H)
4115
#include <sys/resource.h>
4116
#endif
4117
4118
4119
#ifdef HAVE_NICE
4120
/*[clinic input]
4121
os.nice
4122
4123
    increment: int
4124
    /
4125
4126
Add increment to the priority of process and return the new priority.
4127
[clinic start generated code]*/
4128
4129
static PyObject *
4130
os_nice_impl(PyObject *module, int increment)
4131
/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
4132
0
{
4133
0
    int value;
4134
4135
    /* There are two flavours of 'nice': one that returns the new
4136
       priority (as required by almost all standards out there) and the
4137
       Linux/FreeBSD one, which returns '0' on success and advices
4138
       the use of getpriority() to get the new priority.
4139
4140
       If we are of the nice family that returns the new priority, we
4141
       need to clear errno before the call, and check if errno is filled
4142
       before calling posix_error() on a returnvalue of -1, because the
4143
       -1 may be the actual new priority! */
4144
4145
0
    errno = 0;
4146
0
    value = nice(increment);
4147
#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
4148
    if (value == 0)
4149
        value = getpriority(PRIO_PROCESS, 0);
4150
#endif
4151
0
    if (value == -1 && errno != 0)
4152
        /* either nice() or getpriority() returned an error */
4153
0
        return posix_error();
4154
0
    return PyLong_FromLong((long) value);
4155
0
}
4156
#endif /* HAVE_NICE */
4157
4158
4159
#ifdef HAVE_GETPRIORITY
4160
/*[clinic input]
4161
os.getpriority
4162
4163
    which: int
4164
    who: int
4165
4166
Return program scheduling priority.
4167
[clinic start generated code]*/
4168
4169
static PyObject *
4170
os_getpriority_impl(PyObject *module, int which, int who)
4171
/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
4172
0
{
4173
0
    int retval;
4174
4175
0
    errno = 0;
4176
0
    retval = getpriority(which, who);
4177
0
    if (errno != 0)
4178
0
        return posix_error();
4179
0
    return PyLong_FromLong((long)retval);
4180
0
}
4181
#endif /* HAVE_GETPRIORITY */
4182
4183
4184
#ifdef HAVE_SETPRIORITY
4185
/*[clinic input]
4186
os.setpriority
4187
4188
    which: int
4189
    who: int
4190
    priority: int
4191
4192
Set program scheduling priority.
4193
[clinic start generated code]*/
4194
4195
static PyObject *
4196
os_setpriority_impl(PyObject *module, int which, int who, int priority)
4197
/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
4198
0
{
4199
0
    int retval;
4200
4201
0
    retval = setpriority(which, who, priority);
4202
0
    if (retval == -1)
4203
0
        return posix_error();
4204
0
    Py_RETURN_NONE;
4205
0
}
4206
#endif /* HAVE_SETPRIORITY */
4207
4208
4209
static PyObject *
4210
internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
4211
0
{
4212
0
    const char *function_name = is_replace ? "replace" : "rename";
4213
0
    int dir_fd_specified;
4214
4215
#ifdef MS_WINDOWS
4216
    BOOL result;
4217
    int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
4218
#else
4219
0
    int result;
4220
0
#endif
4221
4222
0
    dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
4223
0
                       (dst_dir_fd != DEFAULT_DIR_FD);
4224
#ifndef HAVE_RENAMEAT
4225
    if (dir_fd_specified) {
4226
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4227
        return NULL;
4228
    }
4229
#endif
4230
4231
0
    if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
4232
0
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4233
0
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4234
0
        return NULL;
4235
0
    }
4236
4237
#ifdef MS_WINDOWS
4238
    Py_BEGIN_ALLOW_THREADS
4239
    result = MoveFileExW(src->wide, dst->wide, flags);
4240
    Py_END_ALLOW_THREADS
4241
4242
    if (!result)
4243
        return path_error2(src, dst);
4244
4245
#else
4246
0
    if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
4247
0
        PyErr_Format(PyExc_ValueError,
4248
0
                     "%s: src and dst must be the same type", function_name);
4249
0
        return NULL;
4250
0
    }
4251
4252
0
    Py_BEGIN_ALLOW_THREADS
4253
0
#ifdef HAVE_RENAMEAT
4254
0
    if (dir_fd_specified)
4255
0
        result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
4256
0
    else
4257
0
#endif
4258
0
    result = rename(src->narrow, dst->narrow);
4259
0
    Py_END_ALLOW_THREADS
4260
4261
0
    if (result)
4262
0
        return path_error2(src, dst);
4263
0
#endif
4264
0
    Py_RETURN_NONE;
4265
0
}
4266
4267
4268
/*[clinic input]
4269
os.rename
4270
4271
    src : path_t
4272
    dst : path_t
4273
    *
4274
    src_dir_fd : dir_fd = None
4275
    dst_dir_fd : dir_fd = None
4276
4277
Rename a file or directory.
4278
4279
If either src_dir_fd or dst_dir_fd is not None, it should be a file
4280
  descriptor open to a directory, and the respective path string (src or dst)
4281
  should be relative; the path will then be relative to that directory.
4282
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4283
  If they are unavailable, using them will raise a NotImplementedError.
4284
[clinic start generated code]*/
4285
4286
static PyObject *
4287
os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4288
               int dst_dir_fd)
4289
/*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
4290
0
{
4291
0
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
4292
0
}
4293
4294
4295
/*[clinic input]
4296
os.replace = os.rename
4297
4298
Rename a file or directory, overwriting the destination.
4299
4300
If either src_dir_fd or dst_dir_fd is not None, it should be a file
4301
  descriptor open to a directory, and the respective path string (src or dst)
4302
  should be relative; the path will then be relative to that directory.
4303
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4304
  If they are unavailable, using them will raise a NotImplementedError.
4305
[clinic start generated code]*/
4306
4307
static PyObject *
4308
os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4309
                int dst_dir_fd)
4310
/*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
4311
0
{
4312
0
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
4313
0
}
4314
4315
4316
/*[clinic input]
4317
os.rmdir
4318
4319
    path: path_t
4320
    *
4321
    dir_fd: dir_fd(requires='unlinkat') = None
4322
4323
Remove a directory.
4324
4325
If dir_fd is not None, it should be a file descriptor open to a directory,
4326
  and path should be relative; path will then be relative to that directory.
4327
dir_fd may not be implemented on your platform.
4328
  If it is unavailable, using it will raise a NotImplementedError.
4329
[clinic start generated code]*/
4330
4331
static PyObject *
4332
os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
4333
/*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
4334
0
{
4335
0
    int result;
4336
4337
0
    if (PySys_Audit("os.rmdir", "Oi", path->object,
4338
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4339
0
        return NULL;
4340
0
    }
4341
4342
0
    Py_BEGIN_ALLOW_THREADS
4343
#ifdef MS_WINDOWS
4344
    /* Windows, success=1, UNIX, success=0 */
4345
    result = !RemoveDirectoryW(path->wide);
4346
#else
4347
0
#ifdef HAVE_UNLINKAT
4348
0
    if (dir_fd != DEFAULT_DIR_FD)
4349
0
        result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
4350
0
    else
4351
0
#endif
4352
0
        result = rmdir(path->narrow);
4353
0
#endif
4354
0
    Py_END_ALLOW_THREADS
4355
4356
0
    if (result)
4357
0
        return path_error(path);
4358
4359
0
    Py_RETURN_NONE;
4360
0
}
4361
4362
4363
#ifdef HAVE_SYSTEM
4364
#ifdef MS_WINDOWS
4365
/*[clinic input]
4366
os.system -> long
4367
4368
    command: Py_UNICODE
4369
4370
Execute the command in a subshell.
4371
[clinic start generated code]*/
4372
4373
static long
4374
os_system_impl(PyObject *module, const Py_UNICODE *command)
4375
/*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/
4376
{
4377
    long result;
4378
4379
    if (PySys_Audit("os.system", "(u)", command) < 0) {
4380
        return -1;
4381
    }
4382
4383
    Py_BEGIN_ALLOW_THREADS
4384
    _Py_BEGIN_SUPPRESS_IPH
4385
    result = _wsystem(command);
4386
    _Py_END_SUPPRESS_IPH
4387
    Py_END_ALLOW_THREADS
4388
    return result;
4389
}
4390
#else /* MS_WINDOWS */
4391
/*[clinic input]
4392
os.system -> long
4393
4394
    command: FSConverter
4395
4396
Execute the command in a subshell.
4397
[clinic start generated code]*/
4398
4399
static long
4400
os_system_impl(PyObject *module, PyObject *command)
4401
/*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
4402
0
{
4403
0
    long result;
4404
0
    const char *bytes = PyBytes_AsString(command);
4405
4406
0
    if (PySys_Audit("os.system", "(O)", command) < 0) {
4407
0
        return -1;
4408
0
    }
4409
4410
0
    Py_BEGIN_ALLOW_THREADS
4411
0
    result = system(bytes);
4412
0
    Py_END_ALLOW_THREADS
4413
0
    return result;
4414
0
}
4415
#endif
4416
#endif /* HAVE_SYSTEM */
4417
4418
4419
/*[clinic input]
4420
os.umask
4421
4422
    mask: int
4423
    /
4424
4425
Set the current numeric umask and return the previous umask.
4426
[clinic start generated code]*/
4427
4428
static PyObject *
4429
os_umask_impl(PyObject *module, int mask)
4430
/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
4431
0
{
4432
0
    int i = (int)umask(mask);
4433
0
    if (i < 0)
4434
0
        return posix_error();
4435
0
    return PyLong_FromLong((long)i);
4436
0
}
4437
4438
#ifdef MS_WINDOWS
4439
4440
/* override the default DeleteFileW behavior so that directory
4441
symlinks can be removed with this function, the same as with
4442
Unix symlinks */
4443
BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
4444
{
4445
    WIN32_FILE_ATTRIBUTE_DATA info;
4446
    WIN32_FIND_DATAW find_data;
4447
    HANDLE find_data_handle;
4448
    int is_directory = 0;
4449
    int is_link = 0;
4450
4451
    if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
4452
        is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
4453
4454
        /* Get WIN32_FIND_DATA structure for the path to determine if
4455
           it is a symlink */
4456
        if(is_directory &&
4457
           info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
4458
            find_data_handle = FindFirstFileW(lpFileName, &find_data);
4459
4460
            if(find_data_handle != INVALID_HANDLE_VALUE) {
4461
                /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
4462
                   IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
4463
                is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
4464
                          find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
4465
                FindClose(find_data_handle);
4466
            }
4467
        }
4468
    }
4469
4470
    if (is_directory && is_link)
4471
        return RemoveDirectoryW(lpFileName);
4472
4473
    return DeleteFileW(lpFileName);
4474
}
4475
#endif /* MS_WINDOWS */
4476
4477
4478
/*[clinic input]
4479
os.unlink
4480
4481
    path: path_t
4482
    *
4483
    dir_fd: dir_fd(requires='unlinkat')=None
4484
4485
Remove a file (same as remove()).
4486
4487
If dir_fd is not None, it should be a file descriptor open to a directory,
4488
  and path should be relative; path will then be relative to that directory.
4489
dir_fd may not be implemented on your platform.
4490
  If it is unavailable, using it will raise a NotImplementedError.
4491
4492
[clinic start generated code]*/
4493
4494
static PyObject *
4495
os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
4496
/*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
4497
0
{
4498
0
    int result;
4499
4500
0
    if (PySys_Audit("os.remove", "Oi", path->object,
4501
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4502
0
        return NULL;
4503
0
    }
4504
4505
0
    Py_BEGIN_ALLOW_THREADS
4506
0
    _Py_BEGIN_SUPPRESS_IPH
4507
#ifdef MS_WINDOWS
4508
    /* Windows, success=1, UNIX, success=0 */
4509
    result = !Py_DeleteFileW(path->wide);
4510
#else
4511
0
#ifdef HAVE_UNLINKAT
4512
0
    if (dir_fd != DEFAULT_DIR_FD)
4513
0
        result = unlinkat(dir_fd, path->narrow, 0);
4514
0
    else
4515
0
#endif /* HAVE_UNLINKAT */
4516
0
        result = unlink(path->narrow);
4517
0
#endif
4518
0
    _Py_END_SUPPRESS_IPH
4519
0
    Py_END_ALLOW_THREADS
4520
4521
0
    if (result)
4522
0
        return path_error(path);
4523
4524
0
    Py_RETURN_NONE;
4525
0
}
4526
4527
4528
/*[clinic input]
4529
os.remove = os.unlink
4530
4531
Remove a file (same as unlink()).
4532
4533
If dir_fd is not None, it should be a file descriptor open to a directory,
4534
  and path should be relative; path will then be relative to that directory.
4535
dir_fd may not be implemented on your platform.
4536
  If it is unavailable, using it will raise a NotImplementedError.
4537
[clinic start generated code]*/
4538
4539
static PyObject *
4540
os_remove_impl(PyObject *module, path_t *path, int dir_fd)
4541
/*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
4542
0
{
4543
0
    return os_unlink_impl(module, path, dir_fd);
4544
0
}
4545
4546
4547
static PyStructSequence_Field uname_result_fields[] = {
4548
    {"sysname",    "operating system name"},
4549
    {"nodename",   "name of machine on network (implementation-defined)"},
4550
    {"release",    "operating system release"},
4551
    {"version",    "operating system version"},
4552
    {"machine",    "hardware identifier"},
4553
    {NULL}
4554
};
4555
4556
PyDoc_STRVAR(uname_result__doc__,
4557
"uname_result: Result from os.uname().\n\n\
4558
This object may be accessed either as a tuple of\n\
4559
  (sysname, nodename, release, version, machine),\n\
4560
or via the attributes sysname, nodename, release, version, and machine.\n\
4561
\n\
4562
See os.uname for more information.");
4563
4564
static PyStructSequence_Desc uname_result_desc = {
4565
    "uname_result", /* name */
4566
    uname_result__doc__, /* doc */
4567
    uname_result_fields,
4568
    5
4569
};
4570
4571
static PyTypeObject* UnameResultType;
4572
4573
4574
#ifdef HAVE_UNAME
4575
/*[clinic input]
4576
os.uname
4577
4578
Return an object identifying the current operating system.
4579
4580
The object behaves like a named tuple with the following fields:
4581
  (sysname, nodename, release, version, machine)
4582
4583
[clinic start generated code]*/
4584
4585
static PyObject *
4586
os_uname_impl(PyObject *module)
4587
/*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
4588
0
{
4589
0
    struct utsname u;
4590
0
    int res;
4591
0
    PyObject *value;
4592
4593
0
    Py_BEGIN_ALLOW_THREADS
4594
0
    res = uname(&u);
4595
0
    Py_END_ALLOW_THREADS
4596
0
    if (res < 0)
4597
0
        return posix_error();
4598
4599
0
    value = PyStructSequence_New(UnameResultType);
4600
0
    if (value == NULL)
4601
0
        return NULL;
4602
4603
0
#define SET(i, field) \
4604
0
    { \
4605
0
    PyObject *o = PyUnicode_DecodeFSDefault(field); \
4606
0
    if (!o) { \
4607
0
        Py_DECREF(value); \
4608
0
        return NULL; \
4609
0
    } \
4610
0
    PyStructSequence_SET_ITEM(value, i, o); \
4611
0
    } \
4612
0
4613
0
    SET(0, u.sysname);
4614
0
    SET(1, u.nodename);
4615
0
    SET(2, u.release);
4616
0
    SET(3, u.version);
4617
0
    SET(4, u.machine);
4618
4619
0
#undef SET
4620
4621
0
    return value;
4622
0
}
4623
#endif /* HAVE_UNAME */
4624
4625
4626
4627
typedef struct {
4628
    int    now;
4629
    time_t atime_s;
4630
    long   atime_ns;
4631
    time_t mtime_s;
4632
    long   mtime_ns;
4633
} utime_t;
4634
4635
/*
4636
 * these macros assume that "ut" is a pointer to a utime_t
4637
 * they also intentionally leak the declaration of a pointer named "time"
4638
 */
4639
#define UTIME_TO_TIMESPEC \
4640
0
    struct timespec ts[2]; \
4641
0
    struct timespec *time; \
4642
0
    if (ut->now) \
4643
0
        time = NULL; \
4644
0
    else { \
4645
0
        ts[0].tv_sec = ut->atime_s; \
4646
0
        ts[0].tv_nsec = ut->atime_ns; \
4647
0
        ts[1].tv_sec = ut->mtime_s; \
4648
0
        ts[1].tv_nsec = ut->mtime_ns; \
4649
0
        time = ts; \
4650
0
    } \
4651
4652
#define UTIME_TO_TIMEVAL \
4653
    struct timeval tv[2]; \
4654
    struct timeval *time; \
4655
    if (ut->now) \
4656
        time = NULL; \
4657
    else { \
4658
        tv[0].tv_sec = ut->atime_s; \
4659
        tv[0].tv_usec = ut->atime_ns / 1000; \
4660
        tv[1].tv_sec = ut->mtime_s; \
4661
        tv[1].tv_usec = ut->mtime_ns / 1000; \
4662
        time = tv; \
4663
    } \
4664
4665
#define UTIME_TO_UTIMBUF \
4666
    struct utimbuf u; \
4667
    struct utimbuf *time; \
4668
    if (ut->now) \
4669
        time = NULL; \
4670
    else { \
4671
        u.actime = ut->atime_s; \
4672
        u.modtime = ut->mtime_s; \
4673
        time = &u; \
4674
    }
4675
4676
#define UTIME_TO_TIME_T \
4677
    time_t timet[2]; \
4678
    time_t *time; \
4679
    if (ut->now) \
4680
        time = NULL; \
4681
    else { \
4682
        timet[0] = ut->atime_s; \
4683
        timet[1] = ut->mtime_s; \
4684
        time = timet; \
4685
    } \
4686
4687
4688
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
4689
4690
static int
4691
utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
4692
0
{
4693
0
#ifdef HAVE_UTIMENSAT
4694
0
    int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
4695
0
    UTIME_TO_TIMESPEC;
4696
0
    return utimensat(dir_fd, path, time, flags);
4697
#elif defined(HAVE_FUTIMESAT)
4698
    UTIME_TO_TIMEVAL;
4699
    /*
4700
     * follow_symlinks will never be false here;
4701
     * we only allow !follow_symlinks and dir_fd together
4702
     * if we have utimensat()
4703
     */
4704
    assert(follow_symlinks);
4705
    return futimesat(dir_fd, path, time);
4706
#endif
4707
0
}
4708
4709
0
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
4710
#else
4711
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
4712
#endif
4713
4714
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
4715
4716
static int
4717
utime_fd(utime_t *ut, int fd)
4718
0
{
4719
0
#ifdef HAVE_FUTIMENS
4720
0
    UTIME_TO_TIMESPEC;
4721
0
    return futimens(fd, time);
4722
#else
4723
    UTIME_TO_TIMEVAL;
4724
    return futimes(fd, time);
4725
#endif
4726
0
}
4727
4728
    #define PATH_UTIME_HAVE_FD 1
4729
#else
4730
    #define PATH_UTIME_HAVE_FD 0
4731
#endif
4732
4733
#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
4734
#  define UTIME_HAVE_NOFOLLOW_SYMLINKS
4735
#endif
4736
4737
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
4738
4739
static int
4740
utime_nofollow_symlinks(utime_t *ut, const char *path)
4741
0
{
4742
0
#ifdef HAVE_UTIMENSAT
4743
0
    UTIME_TO_TIMESPEC;
4744
0
    return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
4745
#else
4746
    UTIME_TO_TIMEVAL;
4747
    return lutimes(path, time);
4748
#endif
4749
0
}
4750
4751
#endif
4752
4753
#ifndef MS_WINDOWS
4754
4755
static int
4756
utime_default(utime_t *ut, const char *path)
4757
0
{
4758
0
#ifdef HAVE_UTIMENSAT
4759
0
    UTIME_TO_TIMESPEC;
4760
0
    return utimensat(DEFAULT_DIR_FD, path, time, 0);
4761
#elif defined(HAVE_UTIMES)
4762
    UTIME_TO_TIMEVAL;
4763
    return utimes(path, time);
4764
#elif defined(HAVE_UTIME_H)
4765
    UTIME_TO_UTIMBUF;
4766
    return utime(path, time);
4767
#else
4768
    UTIME_TO_TIME_T;
4769
    return utime(path, time);
4770
#endif
4771
0
}
4772
4773
#endif
4774
4775
static int
4776
split_py_long_to_s_and_ns(PyObject *py_long, time_t *s, long *ns)
4777
0
{
4778
0
    int result = 0;
4779
0
    PyObject *divmod;
4780
0
    divmod = PyNumber_Divmod(py_long, billion);
4781
0
    if (!divmod)
4782
0
        goto exit;
4783
0
    if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
4784
0
        PyErr_Format(PyExc_TypeError,
4785
0
                     "%.200s.__divmod__() must return a 2-tuple, not %.200s",
4786
0
                     Py_TYPE(py_long)->tp_name, Py_TYPE(divmod)->tp_name);
4787
0
        goto exit;
4788
0
    }
4789
0
    *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
4790
0
    if ((*s == -1) && PyErr_Occurred())
4791
0
        goto exit;
4792
0
    *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
4793
0
    if ((*ns == -1) && PyErr_Occurred())
4794
0
        goto exit;
4795
4796
0
    result = 1;
4797
0
exit:
4798
0
    Py_XDECREF(divmod);
4799
0
    return result;
4800
0
}
4801
4802
4803
/*[clinic input]
4804
os.utime
4805
4806
    path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
4807
    times: object = None
4808
    *
4809
    ns: object = NULL
4810
    dir_fd: dir_fd(requires='futimensat') = None
4811
    follow_symlinks: bool=True
4812
4813
# "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
4814
4815
Set the access and modified time of path.
4816
4817
path may always be specified as a string.
4818
On some platforms, path may also be specified as an open file descriptor.
4819
  If this functionality is unavailable, using it raises an exception.
4820
4821
If times is not None, it must be a tuple (atime, mtime);
4822
    atime and mtime should be expressed as float seconds since the epoch.
4823
If ns is specified, it must be a tuple (atime_ns, mtime_ns);
4824
    atime_ns and mtime_ns should be expressed as integer nanoseconds
4825
    since the epoch.
4826
If times is None and ns is unspecified, utime uses the current time.
4827
Specifying tuples for both times and ns is an error.
4828
4829
If dir_fd is not None, it should be a file descriptor open to a directory,
4830
  and path should be relative; path will then be relative to that directory.
4831
If follow_symlinks is False, and the last element of the path is a symbolic
4832
  link, utime will modify the symbolic link itself instead of the file the
4833
  link points to.
4834
It is an error to use dir_fd or follow_symlinks when specifying path
4835
  as an open file descriptor.
4836
dir_fd and follow_symlinks may not be available on your platform.
4837
  If they are unavailable, using them will raise a NotImplementedError.
4838
4839
[clinic start generated code]*/
4840
4841
static PyObject *
4842
os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
4843
              int dir_fd, int follow_symlinks)
4844
/*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
4845
0
{
4846
#ifdef MS_WINDOWS
4847
    HANDLE hFile;
4848
    FILETIME atime, mtime;
4849
#else
4850
0
    int result;
4851
0
#endif
4852
4853
0
    utime_t utime;
4854
4855
0
    memset(&utime, 0, sizeof(utime_t));
4856
4857
0
    if (times != Py_None && ns) {
4858
0
        PyErr_SetString(PyExc_ValueError,
4859
0
                     "utime: you may specify either 'times'"
4860
0
                     " or 'ns' but not both");
4861
0
        return NULL;
4862
0
    }
4863
4864
0
    if (times != Py_None) {
4865
0
        time_t a_sec, m_sec;
4866
0
        long a_nsec, m_nsec;
4867
0
        if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
4868
0
            PyErr_SetString(PyExc_TypeError,
4869
0
                         "utime: 'times' must be either"
4870
0
                         " a tuple of two ints or None");
4871
0
            return NULL;
4872
0
        }
4873
0
        utime.now = 0;
4874
0
        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
4875
0
                                     &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
4876
0
            _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
4877
0
                                     &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
4878
0
            return NULL;
4879
0
        }
4880
0
        utime.atime_s = a_sec;
4881
0
        utime.atime_ns = a_nsec;
4882
0
        utime.mtime_s = m_sec;
4883
0
        utime.mtime_ns = m_nsec;
4884
0
    }
4885
0
    else if (ns) {
4886
0
        if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
4887
0
            PyErr_SetString(PyExc_TypeError,
4888
0
                         "utime: 'ns' must be a tuple of two ints");
4889
0
            return NULL;
4890
0
        }
4891
0
        utime.now = 0;
4892
0
        if (!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 0),
4893
0
                                      &utime.atime_s, &utime.atime_ns) ||
4894
0
            !split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 1),
4895
0
                                       &utime.mtime_s, &utime.mtime_ns)) {
4896
0
            return NULL;
4897
0
        }
4898
0
    }
4899
0
    else {
4900
        /* times and ns are both None/unspecified. use "now". */
4901
0
        utime.now = 1;
4902
0
    }
4903
4904
#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
4905
    if (follow_symlinks_specified("utime", follow_symlinks))
4906
        return NULL;
4907
#endif
4908
4909
0
    if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
4910
0
        dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
4911
0
        fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
4912
0
        return NULL;
4913
4914
#if !defined(HAVE_UTIMENSAT)
4915
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
4916
        PyErr_SetString(PyExc_ValueError,
4917
                     "utime: cannot use dir_fd and follow_symlinks "
4918
                     "together on this platform");
4919
        return NULL;
4920
    }
4921
#endif
4922
4923
0
    if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
4924
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4925
0
        return NULL;
4926
0
    }
4927
4928
#ifdef MS_WINDOWS
4929
    Py_BEGIN_ALLOW_THREADS
4930
    hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
4931
                        NULL, OPEN_EXISTING,
4932
                        FILE_FLAG_BACKUP_SEMANTICS, NULL);
4933
    Py_END_ALLOW_THREADS
4934
    if (hFile == INVALID_HANDLE_VALUE) {
4935
        path_error(path);
4936
        return NULL;
4937
    }
4938
4939
    if (utime.now) {
4940
        GetSystemTimeAsFileTime(&mtime);
4941
        atime = mtime;
4942
    }
4943
    else {
4944
        _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
4945
        _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
4946
    }
4947
    if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
4948
        /* Avoid putting the file name into the error here,
4949
           as that may confuse the user into believing that
4950
           something is wrong with the file, when it also
4951
           could be the time stamp that gives a problem. */
4952
        PyErr_SetFromWindowsErr(0);
4953
        CloseHandle(hFile);
4954
        return NULL;
4955
    }
4956
    CloseHandle(hFile);
4957
#else /* MS_WINDOWS */
4958
0
    Py_BEGIN_ALLOW_THREADS
4959
4960
0
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
4961
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4962
0
        result = utime_nofollow_symlinks(&utime, path->narrow);
4963
0
    else
4964
0
#endif
4965
4966
0
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
4967
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))
4968
0
        result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
4969
0
    else
4970
0
#endif
4971
4972
0
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
4973
0
    if (path->fd != -1)
4974
0
        result = utime_fd(&utime, path->fd);
4975
0
    else
4976
0
#endif
4977
4978
0
    result = utime_default(&utime, path->narrow);
4979
4980
0
    Py_END_ALLOW_THREADS
4981
4982
0
    if (result < 0) {
4983
        /* see previous comment about not putting filename in error here */
4984
0
        posix_error();
4985
0
        return NULL;
4986
0
    }
4987
4988
0
#endif /* MS_WINDOWS */
4989
4990
0
    Py_RETURN_NONE;
4991
0
}
4992
4993
/* Process operations */
4994
4995
4996
/*[clinic input]
4997
os._exit
4998
4999
    status: int
5000
5001
Exit to the system with specified status, without normal exit processing.
5002
[clinic start generated code]*/
5003
5004
static PyObject *
5005
os__exit_impl(PyObject *module, int status)
5006
/*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
5007
0
{
5008
0
    _exit(status);
5009
0
    return NULL; /* Make gcc -Wall happy */
5010
0
}
5011
5012
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5013
#define EXECV_CHAR wchar_t
5014
#else
5015
0
#define EXECV_CHAR char
5016
#endif
5017
5018
#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
5019
static void
5020
free_string_array(EXECV_CHAR **array, Py_ssize_t count)
5021
0
{
5022
0
    Py_ssize_t i;
5023
0
    for (i = 0; i < count; i++)
5024
0
        PyMem_Free(array[i]);
5025
0
    PyMem_DEL(array);
5026
0
}
5027
5028
static int
5029
fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
5030
0
{
5031
0
    Py_ssize_t size;
5032
0
    PyObject *ub;
5033
0
    int result = 0;
5034
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5035
    if (!PyUnicode_FSDecoder(o, &ub))
5036
        return 0;
5037
    *out = PyUnicode_AsWideCharString(ub, &size);
5038
    if (*out)
5039
        result = 1;
5040
#else
5041
0
    if (!PyUnicode_FSConverter(o, &ub))
5042
0
        return 0;
5043
0
    size = PyBytes_GET_SIZE(ub);
5044
0
    *out = PyMem_Malloc(size + 1);
5045
0
    if (*out) {
5046
0
        memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
5047
0
        result = 1;
5048
0
    } else
5049
0
        PyErr_NoMemory();
5050
0
#endif
5051
0
    Py_DECREF(ub);
5052
0
    return result;
5053
0
}
5054
#endif
5055
5056
#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
5057
static EXECV_CHAR**
5058
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
5059
0
{
5060
0
    Py_ssize_t i, pos, envc;
5061
0
    PyObject *keys=NULL, *vals=NULL;
5062
0
    PyObject *key, *val, *key2, *val2, *keyval;
5063
0
    EXECV_CHAR **envlist;
5064
5065
0
    i = PyMapping_Size(env);
5066
0
    if (i < 0)
5067
0
        return NULL;
5068
0
    envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
5069
0
    if (envlist == NULL) {
5070
0
        PyErr_NoMemory();
5071
0
        return NULL;
5072
0
    }
5073
0
    envc = 0;
5074
0
    keys = PyMapping_Keys(env);
5075
0
    if (!keys)
5076
0
        goto error;
5077
0
    vals = PyMapping_Values(env);
5078
0
    if (!vals)
5079
0
        goto error;
5080
0
    if (!PyList_Check(keys) || !PyList_Check(vals)) {
5081
0
        PyErr_Format(PyExc_TypeError,
5082
0
                     "env.keys() or env.values() is not a list");
5083
0
        goto error;
5084
0
    }
5085
5086
0
    for (pos = 0; pos < i; pos++) {
5087
0
        key = PyList_GetItem(keys, pos);
5088
0
        val = PyList_GetItem(vals, pos);
5089
0
        if (!key || !val)
5090
0
            goto error;
5091
5092
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5093
        if (!PyUnicode_FSDecoder(key, &key2))
5094
            goto error;
5095
        if (!PyUnicode_FSDecoder(val, &val2)) {
5096
            Py_DECREF(key2);
5097
            goto error;
5098
        }
5099
        /* Search from index 1 because on Windows starting '=' is allowed for
5100
           defining hidden environment variables. */
5101
        if (PyUnicode_GET_LENGTH(key2) == 0 ||
5102
            PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
5103
        {
5104
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5105
            Py_DECREF(key2);
5106
            Py_DECREF(val2);
5107
            goto error;
5108
        }
5109
        keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
5110
#else
5111
0
        if (!PyUnicode_FSConverter(key, &key2))
5112
0
            goto error;
5113
0
        if (!PyUnicode_FSConverter(val, &val2)) {
5114
0
            Py_DECREF(key2);
5115
0
            goto error;
5116
0
        }
5117
0
        if (PyBytes_GET_SIZE(key2) == 0 ||
5118
0
            strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
5119
0
        {
5120
0
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5121
0
            Py_DECREF(key2);
5122
0
            Py_DECREF(val2);
5123
0
            goto error;
5124
0
        }
5125
0
        keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
5126
0
                                             PyBytes_AS_STRING(val2));
5127
0
#endif
5128
0
        Py_DECREF(key2);
5129
0
        Py_DECREF(val2);
5130
0
        if (!keyval)
5131
0
            goto error;
5132
5133
0
        if (!fsconvert_strdup(keyval, &envlist[envc++])) {
5134
0
            Py_DECREF(keyval);
5135
0
            goto error;
5136
0
        }
5137
5138
0
        Py_DECREF(keyval);
5139
0
    }
5140
0
    Py_DECREF(vals);
5141
0
    Py_DECREF(keys);
5142
5143
0
    envlist[envc] = 0;
5144
0
    *envc_ptr = envc;
5145
0
    return envlist;
5146
5147
0
error:
5148
0
    Py_XDECREF(keys);
5149
0
    Py_XDECREF(vals);
5150
0
    free_string_array(envlist, envc);
5151
0
    return NULL;
5152
0
}
5153
5154
static EXECV_CHAR**
5155
parse_arglist(PyObject* argv, Py_ssize_t *argc)
5156
0
{
5157
0
    int i;
5158
0
    EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
5159
0
    if (argvlist == NULL) {
5160
0
        PyErr_NoMemory();
5161
0
        return NULL;
5162
0
    }
5163
0
    for (i = 0; i < *argc; i++) {
5164
0
        PyObject* item = PySequence_ITEM(argv, i);
5165
0
        if (item == NULL)
5166
0
            goto fail;
5167
0
        if (!fsconvert_strdup(item, &argvlist[i])) {
5168
0
            Py_DECREF(item);
5169
0
            goto fail;
5170
0
        }
5171
0
        Py_DECREF(item);
5172
0
    }
5173
0
    argvlist[*argc] = NULL;
5174
0
    return argvlist;
5175
0
fail:
5176
0
    *argc = i;
5177
0
    free_string_array(argvlist, *argc);
5178
0
    return NULL;
5179
0
}
5180
5181
#endif
5182
5183
5184
#ifdef HAVE_EXECV
5185
/*[clinic input]
5186
os.execv
5187
5188
    path: path_t
5189
        Path of executable file.
5190
    argv: object
5191
        Tuple or list of strings.
5192
    /
5193
5194
Execute an executable path with arguments, replacing current process.
5195
[clinic start generated code]*/
5196
5197
static PyObject *
5198
os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
5199
/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
5200
0
{
5201
0
    EXECV_CHAR **argvlist;
5202
0
    Py_ssize_t argc;
5203
5204
    /* execv has two arguments: (path, argv), where
5205
       argv is a list or tuple of strings. */
5206
5207
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5208
0
        PyErr_SetString(PyExc_TypeError,
5209
0
                        "execv() arg 2 must be a tuple or list");
5210
0
        return NULL;
5211
0
    }
5212
0
    argc = PySequence_Size(argv);
5213
0
    if (argc < 1) {
5214
0
        PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
5215
0
        return NULL;
5216
0
    }
5217
5218
0
    argvlist = parse_arglist(argv, &argc);
5219
0
    if (argvlist == NULL) {
5220
0
        return NULL;
5221
0
    }
5222
0
    if (!argvlist[0][0]) {
5223
0
        PyErr_SetString(PyExc_ValueError,
5224
0
            "execv() arg 2 first element cannot be empty");
5225
0
        free_string_array(argvlist, argc);
5226
0
        return NULL;
5227
0
    }
5228
5229
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
5230
0
        free_string_array(argvlist, argc);
5231
0
        return NULL;
5232
0
    }
5233
5234
0
    _Py_BEGIN_SUPPRESS_IPH
5235
#ifdef HAVE_WEXECV
5236
    _wexecv(path->wide, argvlist);
5237
#else
5238
0
    execv(path->narrow, argvlist);
5239
0
#endif
5240
0
    _Py_END_SUPPRESS_IPH
5241
5242
    /* If we get here it's definitely an error */
5243
5244
0
    free_string_array(argvlist, argc);
5245
0
    return posix_error();
5246
0
}
5247
5248
5249
/*[clinic input]
5250
os.execve
5251
5252
    path: path_t(allow_fd='PATH_HAVE_FEXECVE')
5253
        Path of executable file.
5254
    argv: object
5255
        Tuple or list of strings.
5256
    env: object
5257
        Dictionary of strings mapping to strings.
5258
5259
Execute an executable path with arguments, replacing current process.
5260
[clinic start generated code]*/
5261
5262
static PyObject *
5263
os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
5264
/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
5265
0
{
5266
0
    EXECV_CHAR **argvlist = NULL;
5267
0
    EXECV_CHAR **envlist;
5268
0
    Py_ssize_t argc, envc;
5269
5270
    /* execve has three arguments: (path, argv, env), where
5271
       argv is a list or tuple of strings and env is a dictionary
5272
       like posix.environ. */
5273
5274
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5275
0
        PyErr_SetString(PyExc_TypeError,
5276
0
                        "execve: argv must be a tuple or list");
5277
0
        goto fail_0;
5278
0
    }
5279
0
    argc = PySequence_Size(argv);
5280
0
    if (argc < 1) {
5281
0
        PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
5282
0
        return NULL;
5283
0
    }
5284
5285
0
    if (!PyMapping_Check(env)) {
5286
0
        PyErr_SetString(PyExc_TypeError,
5287
0
                        "execve: environment must be a mapping object");
5288
0
        goto fail_0;
5289
0
    }
5290
5291
0
    argvlist = parse_arglist(argv, &argc);
5292
0
    if (argvlist == NULL) {
5293
0
        goto fail_0;
5294
0
    }
5295
0
    if (!argvlist[0][0]) {
5296
0
        PyErr_SetString(PyExc_ValueError,
5297
0
            "execve: argv first element cannot be empty");
5298
0
        goto fail_0;
5299
0
    }
5300
5301
0
    envlist = parse_envlist(env, &envc);
5302
0
    if (envlist == NULL)
5303
0
        goto fail_0;
5304
5305
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
5306
0
        goto fail_1;
5307
0
    }
5308
5309
0
    _Py_BEGIN_SUPPRESS_IPH
5310
0
#ifdef HAVE_FEXECVE
5311
0
    if (path->fd > -1)
5312
0
        fexecve(path->fd, argvlist, envlist);
5313
0
    else
5314
0
#endif
5315
#ifdef HAVE_WEXECV
5316
        _wexecve(path->wide, argvlist, envlist);
5317
#else
5318
0
        execve(path->narrow, argvlist, envlist);
5319
0
#endif
5320
0
    _Py_END_SUPPRESS_IPH
5321
5322
    /* If we get here it's definitely an error */
5323
5324
0
    posix_path_error(path);
5325
0
  fail_1:
5326
0
    free_string_array(envlist, envc);
5327
0
  fail_0:
5328
0
    if (argvlist)
5329
0
        free_string_array(argvlist, argc);
5330
0
    return NULL;
5331
0
}
5332
5333
#endif /* HAVE_EXECV */
5334
5335
#ifdef HAVE_POSIX_SPAWN
5336
5337
enum posix_spawn_file_actions_identifier {
5338
    POSIX_SPAWN_OPEN,
5339
    POSIX_SPAWN_CLOSE,
5340
    POSIX_SPAWN_DUP2
5341
};
5342
5343
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
5344
static int
5345
convert_sched_param(PyObject *param, struct sched_param *res);
5346
#endif
5347
5348
static int
5349
parse_posix_spawn_flags(const char *func_name, PyObject *setpgroup,
5350
                        int resetids, int setsid, PyObject *setsigmask,
5351
                        PyObject *setsigdef, PyObject *scheduler,
5352
                        posix_spawnattr_t *attrp)
5353
0
{
5354
0
    long all_flags = 0;
5355
5356
0
    errno = posix_spawnattr_init(attrp);
5357
0
    if (errno) {
5358
0
        posix_error();
5359
0
        return -1;
5360
0
    }
5361
5362
0
    if (setpgroup) {
5363
0
        pid_t pgid = PyLong_AsPid(setpgroup);
5364
0
        if (pgid == (pid_t)-1 && PyErr_Occurred()) {
5365
0
            goto fail;
5366
0
        }
5367
0
        errno = posix_spawnattr_setpgroup(attrp, pgid);
5368
0
        if (errno) {
5369
0
            posix_error();
5370
0
            goto fail;
5371
0
        }
5372
0
        all_flags |= POSIX_SPAWN_SETPGROUP;
5373
0
    }
5374
5375
0
    if (resetids) {
5376
0
        all_flags |= POSIX_SPAWN_RESETIDS;
5377
0
    }
5378
5379
0
    if (setsid) {
5380
0
#ifdef POSIX_SPAWN_SETSID
5381
0
        all_flags |= POSIX_SPAWN_SETSID;
5382
#elif defined(POSIX_SPAWN_SETSID_NP)
5383
        all_flags |= POSIX_SPAWN_SETSID_NP;
5384
#else
5385
        argument_unavailable_error(func_name, "setsid");
5386
        return -1;
5387
#endif
5388
0
    }
5389
5390
0
   if (setsigmask) {
5391
0
        sigset_t set;
5392
0
        if (!_Py_Sigset_Converter(setsigmask, &set)) {
5393
0
            goto fail;
5394
0
        }
5395
0
        errno = posix_spawnattr_setsigmask(attrp, &set);
5396
0
        if (errno) {
5397
0
            posix_error();
5398
0
            goto fail;
5399
0
        }
5400
0
        all_flags |= POSIX_SPAWN_SETSIGMASK;
5401
0
    }
5402
5403
0
    if (setsigdef) {
5404
0
        sigset_t set;
5405
0
        if (!_Py_Sigset_Converter(setsigdef, &set)) {
5406
0
            goto fail;
5407
0
        }
5408
0
        errno = posix_spawnattr_setsigdefault(attrp, &set);
5409
0
        if (errno) {
5410
0
            posix_error();
5411
0
            goto fail;
5412
0
        }
5413
0
        all_flags |= POSIX_SPAWN_SETSIGDEF;
5414
0
    }
5415
5416
0
    if (scheduler) {
5417
0
#ifdef POSIX_SPAWN_SETSCHEDULER
5418
0
        PyObject *py_schedpolicy;
5419
0
        struct sched_param schedparam;
5420
5421
0
        if (!PyArg_ParseTuple(scheduler, "OO&"
5422
0
                        ";A scheduler tuple must have two elements",
5423
0
                        &py_schedpolicy, convert_sched_param, &schedparam)) {
5424
0
            goto fail;
5425
0
        }
5426
0
        if (py_schedpolicy != Py_None) {
5427
0
            int schedpolicy = _PyLong_AsInt(py_schedpolicy);
5428
5429
0
            if (schedpolicy == -1 && PyErr_Occurred()) {
5430
0
                goto fail;
5431
0
            }
5432
0
            errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
5433
0
            if (errno) {
5434
0
                posix_error();
5435
0
                goto fail;
5436
0
            }
5437
0
            all_flags |= POSIX_SPAWN_SETSCHEDULER;
5438
0
        }
5439
0
        errno = posix_spawnattr_setschedparam(attrp, &schedparam);
5440
0
        if (errno) {
5441
0
            posix_error();
5442
0
            goto fail;
5443
0
        }
5444
0
        all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
5445
#else
5446
        PyErr_SetString(PyExc_NotImplementedError,
5447
                "The scheduler option is not supported in this system.");
5448
        goto fail;
5449
#endif
5450
0
    }
5451
5452
0
    errno = posix_spawnattr_setflags(attrp, all_flags);
5453
0
    if (errno) {
5454
0
        posix_error();
5455
0
        goto fail;
5456
0
    }
5457
5458
0
    return 0;
5459
5460
0
fail:
5461
0
    (void)posix_spawnattr_destroy(attrp);
5462
0
    return -1;
5463
0
}
5464
5465
static int
5466
parse_file_actions(PyObject *file_actions,
5467
                   posix_spawn_file_actions_t *file_actionsp,
5468
                   PyObject *temp_buffer)
5469
0
{
5470
0
    PyObject *seq;
5471
0
    PyObject *file_action = NULL;
5472
0
    PyObject *tag_obj;
5473
5474
0
    seq = PySequence_Fast(file_actions,
5475
0
                          "file_actions must be a sequence or None");
5476
0
    if (seq == NULL) {
5477
0
        return -1;
5478
0
    }
5479
5480
0
    errno = posix_spawn_file_actions_init(file_actionsp);
5481
0
    if (errno) {
5482
0
        posix_error();
5483
0
        Py_DECREF(seq);
5484
0
        return -1;
5485
0
    }
5486
5487
0
    for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
5488
0
        file_action = PySequence_Fast_GET_ITEM(seq, i);
5489
0
        Py_INCREF(file_action);
5490
0
        if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
5491
0
            PyErr_SetString(PyExc_TypeError,
5492
0
                "Each file_actions element must be a non-empty tuple");
5493
0
            goto fail;
5494
0
        }
5495
0
        long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
5496
0
        if (tag == -1 && PyErr_Occurred()) {
5497
0
            goto fail;
5498
0
        }
5499
5500
        /* Populate the file_actions object */
5501
0
        switch (tag) {
5502
0
            case POSIX_SPAWN_OPEN: {
5503
0
                int fd, oflag;
5504
0
                PyObject *path;
5505
0
                unsigned long mode;
5506
0
                if (!PyArg_ParseTuple(file_action, "OiO&ik"
5507
0
                        ";A open file_action tuple must have 5 elements",
5508
0
                        &tag_obj, &fd, PyUnicode_FSConverter, &path,
5509
0
                        &oflag, &mode))
5510
0
                {
5511
0
                    goto fail;
5512
0
                }
5513
0
                if (PyList_Append(temp_buffer, path)) {
5514
0
                    Py_DECREF(path);
5515
0
                    goto fail;
5516
0
                }
5517
0
                errno = posix_spawn_file_actions_addopen(file_actionsp,
5518
0
                        fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
5519
0
                Py_DECREF(path);
5520
0
                if (errno) {
5521
0
                    posix_error();
5522
0
                    goto fail;
5523
0
                }
5524
0
                break;
5525
0
            }
5526
0
            case POSIX_SPAWN_CLOSE: {
5527
0
                int fd;
5528
0
                if (!PyArg_ParseTuple(file_action, "Oi"
5529
0
                        ";A close file_action tuple must have 2 elements",
5530
0
                        &tag_obj, &fd))
5531
0
                {
5532
0
                    goto fail;
5533
0
                }
5534
0
                errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
5535
0
                if (errno) {
5536
0
                    posix_error();
5537
0
                    goto fail;
5538
0
                }
5539
0
                break;
5540
0
            }
5541
0
            case POSIX_SPAWN_DUP2: {
5542
0
                int fd1, fd2;
5543
0
                if (!PyArg_ParseTuple(file_action, "Oii"
5544
0
                        ";A dup2 file_action tuple must have 3 elements",
5545
0
                        &tag_obj, &fd1, &fd2))
5546
0
                {
5547
0
                    goto fail;
5548
0
                }
5549
0
                errno = posix_spawn_file_actions_adddup2(file_actionsp,
5550
0
                                                         fd1, fd2);
5551
0
                if (errno) {
5552
0
                    posix_error();
5553
0
                    goto fail;
5554
0
                }
5555
0
                break;
5556
0
            }
5557
0
            default: {
5558
0
                PyErr_SetString(PyExc_TypeError,
5559
0
                                "Unknown file_actions identifier");
5560
0
                goto fail;
5561
0
            }
5562
0
        }
5563
0
        Py_DECREF(file_action);
5564
0
    }
5565
5566
0
    Py_DECREF(seq);
5567
0
    return 0;
5568
5569
0
fail:
5570
0
    Py_DECREF(seq);
5571
0
    Py_DECREF(file_action);
5572
0
    (void)posix_spawn_file_actions_destroy(file_actionsp);
5573
0
    return -1;
5574
0
}
5575
5576
5577
static PyObject *
5578
py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
5579
               PyObject *env, PyObject *file_actions,
5580
               PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
5581
               PyObject *setsigdef, PyObject *scheduler)
5582
0
{
5583
0
    const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
5584
0
    EXECV_CHAR **argvlist = NULL;
5585
0
    EXECV_CHAR **envlist = NULL;
5586
0
    posix_spawn_file_actions_t file_actions_buf;
5587
0
    posix_spawn_file_actions_t *file_actionsp = NULL;
5588
0
    posix_spawnattr_t attr;
5589
0
    posix_spawnattr_t *attrp = NULL;
5590
0
    Py_ssize_t argc, envc;
5591
0
    PyObject *result = NULL;
5592
0
    PyObject *temp_buffer = NULL;
5593
0
    pid_t pid;
5594
0
    int err_code;
5595
5596
    /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
5597
       argv is a list or tuple of strings and env is a dictionary
5598
       like posix.environ. */
5599
5600
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5601
0
        PyErr_Format(PyExc_TypeError,
5602
0
                     "%s: argv must be a tuple or list", func_name);
5603
0
        goto exit;
5604
0
    }
5605
0
    argc = PySequence_Size(argv);
5606
0
    if (argc < 1) {
5607
0
        PyErr_Format(PyExc_ValueError,
5608
0
                     "%s: argv must not be empty", func_name);
5609
0
        return NULL;
5610
0
    }
5611
5612
0
    if (!PyMapping_Check(env)) {
5613
0
        PyErr_Format(PyExc_TypeError,
5614
0
                     "%s: environment must be a mapping object", func_name);
5615
0
        goto exit;
5616
0
    }
5617
5618
0
    argvlist = parse_arglist(argv, &argc);
5619
0
    if (argvlist == NULL) {
5620
0
        goto exit;
5621
0
    }
5622
0
    if (!argvlist[0][0]) {
5623
0
        PyErr_Format(PyExc_ValueError,
5624
0
                     "%s: argv first element cannot be empty", func_name);
5625
0
        goto exit;
5626
0
    }
5627
5628
0
    envlist = parse_envlist(env, &envc);
5629
0
    if (envlist == NULL) {
5630
0
        goto exit;
5631
0
    }
5632
5633
0
    if (file_actions != NULL && file_actions != Py_None) {
5634
        /* There is a bug in old versions of glibc that makes some of the
5635
         * helper functions for manipulating file actions not copy the provided
5636
         * buffers. The problem is that posix_spawn_file_actions_addopen does not
5637
         * copy the value of path for some old versions of glibc (<2.20).
5638
         * The use of temp_buffer here is a workaround that keeps the
5639
         * python objects that own the buffers alive until posix_spawn gets called.
5640
         * Check https://bugs.python.org/issue33630 and
5641
         * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
5642
0
        temp_buffer = PyList_New(0);
5643
0
        if (!temp_buffer) {
5644
0
            goto exit;
5645
0
        }
5646
0
        if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
5647
0
            goto exit;
5648
0
        }
5649
0
        file_actionsp = &file_actions_buf;
5650
0
    }
5651
5652
0
    if (parse_posix_spawn_flags(func_name, setpgroup, resetids, setsid,
5653
0
                                setsigmask, setsigdef, scheduler, &attr)) {
5654
0
        goto exit;
5655
0
    }
5656
0
    attrp = &attr;
5657
5658
0
    if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
5659
0
        goto exit;
5660
0
    }
5661
5662
0
    _Py_BEGIN_SUPPRESS_IPH
5663
0
#ifdef HAVE_POSIX_SPAWNP
5664
0
    if (use_posix_spawnp) {
5665
0
        err_code = posix_spawnp(&pid, path->narrow,
5666
0
                                file_actionsp, attrp, argvlist, envlist);
5667
0
    }
5668
0
    else
5669
0
#endif /* HAVE_POSIX_SPAWNP */
5670
0
    {
5671
0
        err_code = posix_spawn(&pid, path->narrow,
5672
0
                               file_actionsp, attrp, argvlist, envlist);
5673
0
    }
5674
0
    _Py_END_SUPPRESS_IPH
5675
5676
0
    if (err_code) {
5677
0
        errno = err_code;
5678
0
        PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
5679
0
        goto exit;
5680
0
    }
5681
#ifdef _Py_MEMORY_SANITIZER
5682
    __msan_unpoison(&pid, sizeof(pid));
5683
#endif
5684
0
    result = PyLong_FromPid(pid);
5685
5686
0
exit:
5687
0
    if (file_actionsp) {
5688
0
        (void)posix_spawn_file_actions_destroy(file_actionsp);
5689
0
    }
5690
0
    if (attrp) {
5691
0
        (void)posix_spawnattr_destroy(attrp);
5692
0
    }
5693
0
    if (envlist) {
5694
0
        free_string_array(envlist, envc);
5695
0
    }
5696
0
    if (argvlist) {
5697
0
        free_string_array(argvlist, argc);
5698
0
    }
5699
0
    Py_XDECREF(temp_buffer);
5700
0
    return result;
5701
0
}
5702
5703
5704
/*[clinic input]
5705
5706
os.posix_spawn
5707
    path: path_t
5708
        Path of executable file.
5709
    argv: object
5710
        Tuple or list of strings.
5711
    env: object
5712
        Dictionary of strings mapping to strings.
5713
    /
5714
    *
5715
    file_actions: object(c_default='NULL') = ()
5716
        A sequence of file action tuples.
5717
    setpgroup: object = NULL
5718
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
5719
    resetids: bool(accept={int}) = False
5720
        If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
5721
    setsid: bool(accept={int}) = False
5722
        If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
5723
    setsigmask: object(c_default='NULL') = ()
5724
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
5725
    setsigdef: object(c_default='NULL') = ()
5726
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
5727
    scheduler: object = NULL
5728
        A tuple with the scheduler policy (optional) and parameters.
5729
5730
Execute the program specified by path in a new process.
5731
[clinic start generated code]*/
5732
5733
static PyObject *
5734
os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
5735
                    PyObject *env, PyObject *file_actions,
5736
                    PyObject *setpgroup, int resetids, int setsid,
5737
                    PyObject *setsigmask, PyObject *setsigdef,
5738
                    PyObject *scheduler)
5739
/*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/
5740
0
{
5741
0
    return py_posix_spawn(0, module, path, argv, env, file_actions,
5742
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
5743
0
                          scheduler);
5744
0
}
5745
 #endif /* HAVE_POSIX_SPAWN */
5746
5747
5748
5749
#ifdef HAVE_POSIX_SPAWNP
5750
/*[clinic input]
5751
5752
os.posix_spawnp
5753
    path: path_t
5754
        Path of executable file.
5755
    argv: object
5756
        Tuple or list of strings.
5757
    env: object
5758
        Dictionary of strings mapping to strings.
5759
    /
5760
    *
5761
    file_actions: object(c_default='NULL') = ()
5762
        A sequence of file action tuples.
5763
    setpgroup: object = NULL
5764
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
5765
    resetids: bool(accept={int}) = False
5766
        If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
5767
    setsid: bool(accept={int}) = False
5768
        If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
5769
    setsigmask: object(c_default='NULL') = ()
5770
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
5771
    setsigdef: object(c_default='NULL') = ()
5772
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
5773
    scheduler: object = NULL
5774
        A tuple with the scheduler policy (optional) and parameters.
5775
5776
Execute the program specified by path in a new process.
5777
[clinic start generated code]*/
5778
5779
static PyObject *
5780
os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
5781
                     PyObject *env, PyObject *file_actions,
5782
                     PyObject *setpgroup, int resetids, int setsid,
5783
                     PyObject *setsigmask, PyObject *setsigdef,
5784
                     PyObject *scheduler)
5785
/*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/
5786
0
{
5787
0
    return py_posix_spawn(1, module, path, argv, env, file_actions,
5788
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
5789
0
                          scheduler);
5790
0
}
5791
#endif /* HAVE_POSIX_SPAWNP */
5792
5793
#ifdef HAVE_RTPSPAWN
5794
static intptr_t
5795
_rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
5796
               const char  *envp[])
5797
{
5798
     RTP_ID rtpid;
5799
     int status;
5800
     pid_t res;
5801
     int async_err = 0;
5802
5803
     /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
5804
        uStackSize=0 cannot be used, the default stack size is too small for
5805
        Python. */
5806
     if (envp) {
5807
         rtpid = rtpSpawn(rtpFileName, argv, envp,
5808
                          100, 0x1000000, 0, VX_FP_TASK);
5809
     }
5810
     else {
5811
         rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
5812
                          100, 0x1000000, 0, VX_FP_TASK);
5813
     }
5814
     if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
5815
         do {
5816
             res = waitpid((pid_t)rtpid, &status, 0);
5817
         } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
5818
5819
         if (res < 0)
5820
             return RTP_ID_ERROR;
5821
         return ((intptr_t)status);
5822
     }
5823
     return ((intptr_t)rtpid);
5824
}
5825
#endif
5826
5827
#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
5828
/*[clinic input]
5829
os.spawnv
5830
5831
    mode: int
5832
        Mode of process creation.
5833
    path: path_t
5834
        Path of executable file.
5835
    argv: object
5836
        Tuple or list of strings.
5837
    /
5838
5839
Execute the program specified by path in a new process.
5840
[clinic start generated code]*/
5841
5842
static PyObject *
5843
os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
5844
/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
5845
{
5846
    EXECV_CHAR **argvlist;
5847
    int i;
5848
    Py_ssize_t argc;
5849
    intptr_t spawnval;
5850
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
5851
5852
    /* spawnv has three arguments: (mode, path, argv), where
5853
       argv is a list or tuple of strings. */
5854
5855
    if (PyList_Check(argv)) {
5856
        argc = PyList_Size(argv);
5857
        getitem = PyList_GetItem;
5858
    }
5859
    else if (PyTuple_Check(argv)) {
5860
        argc = PyTuple_Size(argv);
5861
        getitem = PyTuple_GetItem;
5862
    }
5863
    else {
5864
        PyErr_SetString(PyExc_TypeError,
5865
                        "spawnv() arg 2 must be a tuple or list");
5866
        return NULL;
5867
    }
5868
    if (argc == 0) {
5869
        PyErr_SetString(PyExc_ValueError,
5870
            "spawnv() arg 2 cannot be empty");
5871
        return NULL;
5872
    }
5873
5874
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
5875
    if (argvlist == NULL) {
5876
        return PyErr_NoMemory();
5877
    }
5878
    for (i = 0; i < argc; i++) {
5879
        if (!fsconvert_strdup((*getitem)(argv, i),
5880
                              &argvlist[i])) {
5881
            free_string_array(argvlist, i);
5882
            PyErr_SetString(
5883
                PyExc_TypeError,
5884
                "spawnv() arg 2 must contain only strings");
5885
            return NULL;
5886
        }
5887
        if (i == 0 && !argvlist[0][0]) {
5888
            free_string_array(argvlist, i + 1);
5889
            PyErr_SetString(
5890
                PyExc_ValueError,
5891
                "spawnv() arg 2 first element cannot be empty");
5892
            return NULL;
5893
        }
5894
    }
5895
    argvlist[argc] = NULL;
5896
5897
#if !defined(HAVE_RTPSPAWN)
5898
    if (mode == _OLD_P_OVERLAY)
5899
        mode = _P_OVERLAY;
5900
#endif
5901
5902
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
5903
                    Py_None) < 0) {
5904
        free_string_array(argvlist, argc);
5905
        return NULL;
5906
    }
5907
5908
    Py_BEGIN_ALLOW_THREADS
5909
    _Py_BEGIN_SUPPRESS_IPH
5910
#ifdef HAVE_WSPAWNV
5911
    spawnval = _wspawnv(mode, path->wide, argvlist);
5912
#elif defined(HAVE_RTPSPAWN)
5913
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
5914
#else
5915
    spawnval = _spawnv(mode, path->narrow, argvlist);
5916
#endif
5917
    _Py_END_SUPPRESS_IPH
5918
    Py_END_ALLOW_THREADS
5919
5920
    free_string_array(argvlist, argc);
5921
5922
    if (spawnval == -1)
5923
        return posix_error();
5924
    else
5925
        return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
5926
}
5927
5928
/*[clinic input]
5929
os.spawnve
5930
5931
    mode: int
5932
        Mode of process creation.
5933
    path: path_t
5934
        Path of executable file.
5935
    argv: object
5936
        Tuple or list of strings.
5937
    env: object
5938
        Dictionary of strings mapping to strings.
5939
    /
5940
5941
Execute the program specified by path in a new process.
5942
[clinic start generated code]*/
5943
5944
static PyObject *
5945
os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
5946
                PyObject *env)
5947
/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
5948
{
5949
    EXECV_CHAR **argvlist;
5950
    EXECV_CHAR **envlist;
5951
    PyObject *res = NULL;
5952
    Py_ssize_t argc, i, envc;
5953
    intptr_t spawnval;
5954
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
5955
    Py_ssize_t lastarg = 0;
5956
5957
    /* spawnve has four arguments: (mode, path, argv, env), where
5958
       argv is a list or tuple of strings and env is a dictionary
5959
       like posix.environ. */
5960
5961
    if (PyList_Check(argv)) {
5962
        argc = PyList_Size(argv);
5963
        getitem = PyList_GetItem;
5964
    }
5965
    else if (PyTuple_Check(argv)) {
5966
        argc = PyTuple_Size(argv);
5967
        getitem = PyTuple_GetItem;
5968
    }
5969
    else {
5970
        PyErr_SetString(PyExc_TypeError,
5971
                        "spawnve() arg 2 must be a tuple or list");
5972
        goto fail_0;
5973
    }
5974
    if (argc == 0) {
5975
        PyErr_SetString(PyExc_ValueError,
5976
            "spawnve() arg 2 cannot be empty");
5977
        goto fail_0;
5978
    }
5979
    if (!PyMapping_Check(env)) {
5980
        PyErr_SetString(PyExc_TypeError,
5981
                        "spawnve() arg 3 must be a mapping object");
5982
        goto fail_0;
5983
    }
5984
5985
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
5986
    if (argvlist == NULL) {
5987
        PyErr_NoMemory();
5988
        goto fail_0;
5989
    }
5990
    for (i = 0; i < argc; i++) {
5991
        if (!fsconvert_strdup((*getitem)(argv, i),
5992
                              &argvlist[i]))
5993
        {
5994
            lastarg = i;
5995
            goto fail_1;
5996
        }
5997
        if (i == 0 && !argvlist[0][0]) {
5998
            lastarg = i + 1;
5999
            PyErr_SetString(
6000
                PyExc_ValueError,
6001
                "spawnv() arg 2 first element cannot be empty");
6002
            goto fail_1;
6003
        }
6004
    }
6005
    lastarg = argc;
6006
    argvlist[argc] = NULL;
6007
6008
    envlist = parse_envlist(env, &envc);
6009
    if (envlist == NULL)
6010
        goto fail_1;
6011
6012
#if !defined(HAVE_RTPSPAWN)
6013
    if (mode == _OLD_P_OVERLAY)
6014
        mode = _P_OVERLAY;
6015
#endif
6016
6017
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
6018
        goto fail_2;
6019
    }
6020
6021
    Py_BEGIN_ALLOW_THREADS
6022
    _Py_BEGIN_SUPPRESS_IPH
6023
#ifdef HAVE_WSPAWNV
6024
    spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
6025
#elif defined(HAVE_RTPSPAWN)
6026
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
6027
                           (const char **)envlist);
6028
#else
6029
    spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
6030
#endif
6031
    _Py_END_SUPPRESS_IPH
6032
    Py_END_ALLOW_THREADS
6033
6034
    if (spawnval == -1)
6035
        (void) posix_error();
6036
    else
6037
        res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6038
6039
  fail_2:
6040
    while (--envc >= 0)
6041
        PyMem_DEL(envlist[envc]);
6042
    PyMem_DEL(envlist);
6043
  fail_1:
6044
    free_string_array(argvlist, lastarg);
6045
  fail_0:
6046
    return res;
6047
}
6048
6049
#endif /* HAVE_SPAWNV */
6050
6051
6052
#ifdef HAVE_FORK
6053
6054
/* Helper function to validate arguments.
6055
   Returns 0 on success.  non-zero on failure with a TypeError raised.
6056
   If obj is non-NULL it must be callable.  */
6057
static int
6058
check_null_or_callable(PyObject *obj, const char* obj_name)
6059
6
{
6060
6
    if (obj && !PyCallable_Check(obj)) {
6061
0
        PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
6062
0
                     obj_name, Py_TYPE(obj)->tp_name);
6063
0
        return -1;
6064
0
    }
6065
6
    return 0;
6066
6
}
6067
6068
/*[clinic input]
6069
os.register_at_fork
6070
6071
    *
6072
    before: object=NULL
6073
        A callable to be called in the parent before the fork() syscall.
6074
    after_in_child: object=NULL
6075
        A callable to be called in the child after fork().
6076
    after_in_parent: object=NULL
6077
        A callable to be called in the parent after fork().
6078
6079
Register callables to be called when forking a new process.
6080
6081
'before' callbacks are called in reverse order.
6082
'after_in_child' and 'after_in_parent' callbacks are called in order.
6083
6084
[clinic start generated code]*/
6085
6086
static PyObject *
6087
os_register_at_fork_impl(PyObject *module, PyObject *before,
6088
                         PyObject *after_in_child, PyObject *after_in_parent)
6089
/*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
6090
2
{
6091
2
    PyInterpreterState *interp;
6092
6093
2
    if (!before && !after_in_child && !after_in_parent) {
6094
0
        PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
6095
0
        return NULL;
6096
0
    }
6097
2
    if (check_null_or_callable(before, "before") ||
6098
2
        check_null_or_callable(after_in_child, "after_in_child") ||
6099
2
        check_null_or_callable(after_in_parent, "after_in_parent")) {
6100
0
        return NULL;
6101
0
    }
6102
2
    interp = _PyInterpreterState_Get();
6103
6104
2
    if (register_at_forker(&interp->before_forkers, before)) {
6105
0
        return NULL;
6106
0
    }
6107
2
    if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
6108
0
        return NULL;
6109
0
    }
6110
2
    if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
6111
0
        return NULL;
6112
0
    }
6113
2
    Py_RETURN_NONE;
6114
2
}
6115
#endif /* HAVE_FORK */
6116
6117
6118
#ifdef HAVE_FORK1
6119
/*[clinic input]
6120
os.fork1
6121
6122
Fork a child process with a single multiplexed (i.e., not bound) thread.
6123
6124
Return 0 to child process and PID of child to parent process.
6125
[clinic start generated code]*/
6126
6127
static PyObject *
6128
os_fork1_impl(PyObject *module)
6129
/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
6130
{
6131
    pid_t pid;
6132
6133
    if (_PyInterpreterState_Get() != PyInterpreterState_Main()) {
6134
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6135
        return NULL;
6136
    }
6137
    PyOS_BeforeFork();
6138
    pid = fork1();
6139
    if (pid == 0) {
6140
        /* child: this clobbers and resets the import lock. */
6141
        PyOS_AfterFork_Child();
6142
    } else {
6143
        /* parent: release the import lock. */
6144
        PyOS_AfterFork_Parent();
6145
    }
6146
    if (pid == -1)
6147
        return posix_error();
6148
    return PyLong_FromPid(pid);
6149
}
6150
#endif /* HAVE_FORK1 */
6151
6152
6153
#ifdef HAVE_FORK
6154
/*[clinic input]
6155
os.fork
6156
6157
Fork a child process.
6158
6159
Return 0 to child process and PID of child to parent process.
6160
[clinic start generated code]*/
6161
6162
static PyObject *
6163
os_fork_impl(PyObject *module)
6164
/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
6165
0
{
6166
0
    pid_t pid;
6167
6168
0
    if (_PyInterpreterState_Get() != PyInterpreterState_Main()) {
6169
0
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6170
0
        return NULL;
6171
0
    }
6172
0
    if (PySys_Audit("os.fork", NULL) < 0) {
6173
0
        return NULL;
6174
0
    }
6175
0
    PyOS_BeforeFork();
6176
0
    pid = fork();
6177
0
    if (pid == 0) {
6178
        /* child: this clobbers and resets the import lock. */
6179
0
        PyOS_AfterFork_Child();
6180
0
    } else {
6181
        /* parent: release the import lock. */
6182
0
        PyOS_AfterFork_Parent();
6183
0
    }
6184
0
    if (pid == -1)
6185
0
        return posix_error();
6186
0
    return PyLong_FromPid(pid);
6187
0
}
6188
#endif /* HAVE_FORK */
6189
6190
6191
#ifdef HAVE_SCHED_H
6192
#ifdef HAVE_SCHED_GET_PRIORITY_MAX
6193
/*[clinic input]
6194
os.sched_get_priority_max
6195
6196
    policy: int
6197
6198
Get the maximum scheduling priority for policy.
6199
[clinic start generated code]*/
6200
6201
static PyObject *
6202
os_sched_get_priority_max_impl(PyObject *module, int policy)
6203
/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
6204
0
{
6205
0
    int max;
6206
6207
0
    max = sched_get_priority_max(policy);
6208
0
    if (max < 0)
6209
0
        return posix_error();
6210
0
    return PyLong_FromLong(max);
6211
0
}
6212
6213
6214
/*[clinic input]
6215
os.sched_get_priority_min
6216
6217
    policy: int
6218
6219
Get the minimum scheduling priority for policy.
6220
[clinic start generated code]*/
6221
6222
static PyObject *
6223
os_sched_get_priority_min_impl(PyObject *module, int policy)
6224
/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
6225
0
{
6226
0
    int min = sched_get_priority_min(policy);
6227
0
    if (min < 0)
6228
0
        return posix_error();
6229
0
    return PyLong_FromLong(min);
6230
0
}
6231
#endif /* HAVE_SCHED_GET_PRIORITY_MAX */
6232
6233
6234
#ifdef HAVE_SCHED_SETSCHEDULER
6235
/*[clinic input]
6236
os.sched_getscheduler
6237
    pid: pid_t
6238
    /
6239
6240
Get the scheduling policy for the process identifiedy by pid.
6241
6242
Passing 0 for pid returns the scheduling policy for the calling process.
6243
[clinic start generated code]*/
6244
6245
static PyObject *
6246
os_sched_getscheduler_impl(PyObject *module, pid_t pid)
6247
/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=5f14cfd1f189e1a0]*/
6248
0
{
6249
0
    int policy;
6250
6251
0
    policy = sched_getscheduler(pid);
6252
0
    if (policy < 0)
6253
0
        return posix_error();
6254
0
    return PyLong_FromLong(policy);
6255
0
}
6256
#endif /* HAVE_SCHED_SETSCHEDULER */
6257
6258
6259
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
6260
/*[clinic input]
6261
class os.sched_param "PyObject *" "SchedParamType"
6262
6263
@classmethod
6264
os.sched_param.__new__
6265
6266
    sched_priority: object
6267
        A scheduling parameter.
6268
6269
Current has only one field: sched_priority");
6270
[clinic start generated code]*/
6271
6272
static PyObject *
6273
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
6274
/*[clinic end generated code: output=48f4067d60f48c13 input=ab4de35a9a7811f2]*/
6275
0
{
6276
0
    PyObject *res;
6277
6278
0
    res = PyStructSequence_New(type);
6279
0
    if (!res)
6280
0
        return NULL;
6281
0
    Py_INCREF(sched_priority);
6282
0
    PyStructSequence_SET_ITEM(res, 0, sched_priority);
6283
0
    return res;
6284
0
}
6285
6286
6287
PyDoc_VAR(os_sched_param__doc__);
6288
6289
static PyStructSequence_Field sched_param_fields[] = {
6290
    {"sched_priority", "the scheduling priority"},
6291
    {0}
6292
};
6293
6294
static PyStructSequence_Desc sched_param_desc = {
6295
    "sched_param", /* name */
6296
    os_sched_param__doc__, /* doc */
6297
    sched_param_fields,
6298
    1
6299
};
6300
6301
static int
6302
convert_sched_param(PyObject *param, struct sched_param *res)
6303
0
{
6304
0
    long priority;
6305
6306
0
    if (Py_TYPE(param) != SchedParamType) {
6307
0
        PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
6308
0
        return 0;
6309
0
    }
6310
0
    priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
6311
0
    if (priority == -1 && PyErr_Occurred())
6312
0
        return 0;
6313
0
    if (priority > INT_MAX || priority < INT_MIN) {
6314
0
        PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
6315
0
        return 0;
6316
0
    }
6317
0
    res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
6318
0
    return 1;
6319
0
}
6320
#endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
6321
6322
6323
#ifdef HAVE_SCHED_SETSCHEDULER
6324
/*[clinic input]
6325
os.sched_setscheduler
6326
6327
    pid: pid_t
6328
    policy: int
6329
    param: sched_param
6330
    /
6331
6332
Set the scheduling policy for the process identified by pid.
6333
6334
If pid is 0, the calling process is changed.
6335
param is an instance of sched_param.
6336
[clinic start generated code]*/
6337
6338
static PyObject *
6339
os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
6340
                           struct sched_param *param)
6341
/*[clinic end generated code: output=b0ac0a70d3b1d705 input=c581f9469a5327dd]*/
6342
0
{
6343
    /*
6344
    ** sched_setscheduler() returns 0 in Linux, but the previous
6345
    ** scheduling policy under Solaris/Illumos, and others.
6346
    ** On error, -1 is returned in all Operating Systems.
6347
    */
6348
0
    if (sched_setscheduler(pid, policy, param) == -1)
6349
0
        return posix_error();
6350
0
    Py_RETURN_NONE;
6351
0
}
6352
#endif  /* HAVE_SCHED_SETSCHEDULER*/
6353
6354
6355
#ifdef HAVE_SCHED_SETPARAM
6356
/*[clinic input]
6357
os.sched_getparam
6358
    pid: pid_t
6359
    /
6360
6361
Returns scheduling parameters for the process identified by pid.
6362
6363
If pid is 0, returns parameters for the calling process.
6364
Return value is an instance of sched_param.
6365
[clinic start generated code]*/
6366
6367
static PyObject *
6368
os_sched_getparam_impl(PyObject *module, pid_t pid)
6369
/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
6370
0
{
6371
0
    struct sched_param param;
6372
0
    PyObject *result;
6373
0
    PyObject *priority;
6374
6375
0
    if (sched_getparam(pid, &param))
6376
0
        return posix_error();
6377
0
    result = PyStructSequence_New(SchedParamType);
6378
0
    if (!result)
6379
0
        return NULL;
6380
0
    priority = PyLong_FromLong(param.sched_priority);
6381
0
    if (!priority) {
6382
0
        Py_DECREF(result);
6383
0
        return NULL;
6384
0
    }
6385
0
    PyStructSequence_SET_ITEM(result, 0, priority);
6386
0
    return result;
6387
0
}
6388
6389
6390
/*[clinic input]
6391
os.sched_setparam
6392
    pid: pid_t
6393
    param: sched_param
6394
    /
6395
6396
Set scheduling parameters for the process identified by pid.
6397
6398
If pid is 0, sets parameters for the calling process.
6399
param should be an instance of sched_param.
6400
[clinic start generated code]*/
6401
6402
static PyObject *
6403
os_sched_setparam_impl(PyObject *module, pid_t pid,
6404
                       struct sched_param *param)
6405
/*[clinic end generated code: output=8af013f78a32b591 input=6b8d6dfcecdc21bd]*/
6406
0
{
6407
0
    if (sched_setparam(pid, param))
6408
0
        return posix_error();
6409
0
    Py_RETURN_NONE;
6410
0
}
6411
#endif /* HAVE_SCHED_SETPARAM */
6412
6413
6414
#ifdef HAVE_SCHED_RR_GET_INTERVAL
6415
/*[clinic input]
6416
os.sched_rr_get_interval -> double
6417
    pid: pid_t
6418
    /
6419
6420
Return the round-robin quantum for the process identified by pid, in seconds.
6421
6422
Value returned is a float.
6423
[clinic start generated code]*/
6424
6425
static double
6426
os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
6427
/*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
6428
0
{
6429
0
    struct timespec interval;
6430
0
    if (sched_rr_get_interval(pid, &interval)) {
6431
0
        posix_error();
6432
0
        return -1.0;
6433
0
    }
6434
#ifdef _Py_MEMORY_SANITIZER
6435
    __msan_unpoison(&interval, sizeof(interval));
6436
#endif
6437
0
    return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
6438
0
}
6439
#endif /* HAVE_SCHED_RR_GET_INTERVAL */
6440
6441
6442
/*[clinic input]
6443
os.sched_yield
6444
6445
Voluntarily relinquish the CPU.
6446
[clinic start generated code]*/
6447
6448
static PyObject *
6449
os_sched_yield_impl(PyObject *module)
6450
/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
6451
0
{
6452
0
    if (sched_yield())
6453
0
        return posix_error();
6454
0
    Py_RETURN_NONE;
6455
0
}
6456
6457
#ifdef HAVE_SCHED_SETAFFINITY
6458
/* The minimum number of CPUs allocated in a cpu_set_t */
6459
static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
6460
6461
/*[clinic input]
6462
os.sched_setaffinity
6463
    pid: pid_t
6464
    mask : object
6465
    /
6466
6467
Set the CPU affinity of the process identified by pid to mask.
6468
6469
mask should be an iterable of integers identifying CPUs.
6470
[clinic start generated code]*/
6471
6472
static PyObject *
6473
os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
6474
/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
6475
0
{
6476
0
    int ncpus;
6477
0
    size_t setsize;
6478
0
    cpu_set_t *cpu_set = NULL;
6479
0
    PyObject *iterator = NULL, *item;
6480
6481
0
    iterator = PyObject_GetIter(mask);
6482
0
    if (iterator == NULL)
6483
0
        return NULL;
6484
6485
0
    ncpus = NCPUS_START;
6486
0
    setsize = CPU_ALLOC_SIZE(ncpus);
6487
0
    cpu_set = CPU_ALLOC(ncpus);
6488
0
    if (cpu_set == NULL) {
6489
0
        PyErr_NoMemory();
6490
0
        goto error;
6491
0
    }
6492
0
    CPU_ZERO_S(setsize, cpu_set);
6493
6494
0
    while ((item = PyIter_Next(iterator))) {
6495
0
        long cpu;
6496
0
        if (!PyLong_Check(item)) {
6497
0
            PyErr_Format(PyExc_TypeError,
6498
0
                        "expected an iterator of ints, "
6499
0
                        "but iterator yielded %R",
6500
0
                        Py_TYPE(item));
6501
0
            Py_DECREF(item);
6502
0
            goto error;
6503
0
        }
6504
0
        cpu = PyLong_AsLong(item);
6505
0
        Py_DECREF(item);
6506
0
        if (cpu < 0) {
6507
0
            if (!PyErr_Occurred())
6508
0
                PyErr_SetString(PyExc_ValueError, "negative CPU number");
6509
0
            goto error;
6510
0
        }
6511
0
        if (cpu > INT_MAX - 1) {
6512
0
            PyErr_SetString(PyExc_OverflowError, "CPU number too large");
6513
0
            goto error;
6514
0
        }
6515
0
        if (cpu >= ncpus) {
6516
            /* Grow CPU mask to fit the CPU number */
6517
0
            int newncpus = ncpus;
6518
0
            cpu_set_t *newmask;
6519
0
            size_t newsetsize;
6520
0
            while (newncpus <= cpu) {
6521
0
                if (newncpus > INT_MAX / 2)
6522
0
                    newncpus = cpu + 1;
6523
0
                else
6524
0
                    newncpus = newncpus * 2;
6525
0
            }
6526
0
            newmask = CPU_ALLOC(newncpus);
6527
0
            if (newmask == NULL) {
6528
0
                PyErr_NoMemory();
6529
0
                goto error;
6530
0
            }
6531
0
            newsetsize = CPU_ALLOC_SIZE(newncpus);
6532
0
            CPU_ZERO_S(newsetsize, newmask);
6533
0
            memcpy(newmask, cpu_set, setsize);
6534
0
            CPU_FREE(cpu_set);
6535
0
            setsize = newsetsize;
6536
0
            cpu_set = newmask;
6537
0
            ncpus = newncpus;
6538
0
        }
6539
0
        CPU_SET_S(cpu, setsize, cpu_set);
6540
0
    }
6541
0
    if (PyErr_Occurred()) {
6542
0
        goto error;
6543
0
    }
6544
0
    Py_CLEAR(iterator);
6545
6546
0
    if (sched_setaffinity(pid, setsize, cpu_set)) {
6547
0
        posix_error();
6548
0
        goto error;
6549
0
    }
6550
0
    CPU_FREE(cpu_set);
6551
0
    Py_RETURN_NONE;
6552
6553
0
error:
6554
0
    if (cpu_set)
6555
0
        CPU_FREE(cpu_set);
6556
0
    Py_XDECREF(iterator);
6557
0
    return NULL;
6558
0
}
6559
6560
6561
/*[clinic input]
6562
os.sched_getaffinity
6563
    pid: pid_t
6564
    /
6565
6566
Return the affinity of the process identified by pid (or the current process if zero).
6567
6568
The affinity is returned as a set of CPU identifiers.
6569
[clinic start generated code]*/
6570
6571
static PyObject *
6572
os_sched_getaffinity_impl(PyObject *module, pid_t pid)
6573
/*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
6574
0
{
6575
0
    int cpu, ncpus, count;
6576
0
    size_t setsize;
6577
0
    cpu_set_t *mask = NULL;
6578
0
    PyObject *res = NULL;
6579
6580
0
    ncpus = NCPUS_START;
6581
0
    while (1) {
6582
0
        setsize = CPU_ALLOC_SIZE(ncpus);
6583
0
        mask = CPU_ALLOC(ncpus);
6584
0
        if (mask == NULL)
6585
0
            return PyErr_NoMemory();
6586
0
        if (sched_getaffinity(pid, setsize, mask) == 0)
6587
0
            break;
6588
0
        CPU_FREE(mask);
6589
0
        if (errno != EINVAL)
6590
0
            return posix_error();
6591
0
        if (ncpus > INT_MAX / 2) {
6592
0
            PyErr_SetString(PyExc_OverflowError, "could not allocate "
6593
0
                            "a large enough CPU set");
6594
0
            return NULL;
6595
0
        }
6596
0
        ncpus = ncpus * 2;
6597
0
    }
6598
6599
0
    res = PySet_New(NULL);
6600
0
    if (res == NULL)
6601
0
        goto error;
6602
0
    for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
6603
0
        if (CPU_ISSET_S(cpu, setsize, mask)) {
6604
0
            PyObject *cpu_num = PyLong_FromLong(cpu);
6605
0
            --count;
6606
0
            if (cpu_num == NULL)
6607
0
                goto error;
6608
0
            if (PySet_Add(res, cpu_num)) {
6609
0
                Py_DECREF(cpu_num);
6610
0
                goto error;
6611
0
            }
6612
0
            Py_DECREF(cpu_num);
6613
0
        }
6614
0
    }
6615
0
    CPU_FREE(mask);
6616
0
    return res;
6617
6618
0
error:
6619
0
    if (mask)
6620
0
        CPU_FREE(mask);
6621
0
    Py_XDECREF(res);
6622
0
    return NULL;
6623
0
}
6624
6625
#endif /* HAVE_SCHED_SETAFFINITY */
6626
6627
#endif /* HAVE_SCHED_H */
6628
6629
6630
/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
6631
/* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
6632
#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
6633
#define DEV_PTY_FILE "/dev/ptc"
6634
#define HAVE_DEV_PTMX
6635
#else
6636
#define DEV_PTY_FILE "/dev/ptmx"
6637
#endif
6638
6639
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
6640
#ifdef HAVE_PTY_H
6641
#include <pty.h>
6642
#else
6643
#ifdef HAVE_LIBUTIL_H
6644
#include <libutil.h>
6645
#else
6646
#ifdef HAVE_UTIL_H
6647
#include <util.h>
6648
#endif /* HAVE_UTIL_H */
6649
#endif /* HAVE_LIBUTIL_H */
6650
#endif /* HAVE_PTY_H */
6651
#ifdef HAVE_STROPTS_H
6652
#include <stropts.h>
6653
#endif
6654
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) */
6655
6656
6657
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
6658
/*[clinic input]
6659
os.openpty
6660
6661
Open a pseudo-terminal.
6662
6663
Return a tuple of (master_fd, slave_fd) containing open file descriptors
6664
for both the master and slave ends.
6665
[clinic start generated code]*/
6666
6667
static PyObject *
6668
os_openpty_impl(PyObject *module)
6669
/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
6670
0
{
6671
0
    int master_fd = -1, slave_fd = -1;
6672
#ifndef HAVE_OPENPTY
6673
    char * slave_name;
6674
#endif
6675
#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
6676
    PyOS_sighandler_t sig_saved;
6677
#if defined(__sun) && defined(__SVR4)
6678
    extern char *ptsname(int fildes);
6679
#endif
6680
#endif
6681
6682
0
#ifdef HAVE_OPENPTY
6683
0
    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
6684
0
        goto posix_error;
6685
6686
0
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
6687
0
        goto error;
6688
0
    if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
6689
0
        goto error;
6690
6691
#elif defined(HAVE__GETPTY)
6692
    slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
6693
    if (slave_name == NULL)
6694
        goto posix_error;
6695
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
6696
        goto error;
6697
6698
    slave_fd = _Py_open(slave_name, O_RDWR);
6699
    if (slave_fd < 0)
6700
        goto error;
6701
6702
#else
6703
    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
6704
    if (master_fd < 0)
6705
        goto posix_error;
6706
6707
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
6708
6709
    /* change permission of slave */
6710
    if (grantpt(master_fd) < 0) {
6711
        PyOS_setsig(SIGCHLD, sig_saved);
6712
        goto posix_error;
6713
    }
6714
6715
    /* unlock slave */
6716
    if (unlockpt(master_fd) < 0) {
6717
        PyOS_setsig(SIGCHLD, sig_saved);
6718
        goto posix_error;
6719
    }
6720
6721
    PyOS_setsig(SIGCHLD, sig_saved);
6722
6723
    slave_name = ptsname(master_fd); /* get name of slave */
6724
    if (slave_name == NULL)
6725
        goto posix_error;
6726
6727
    slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
6728
    if (slave_fd == -1)
6729
        goto error;
6730
6731
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
6732
        goto posix_error;
6733
6734
#if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
6735
    ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
6736
    ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
6737
#ifndef __hpux
6738
    ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
6739
#endif /* __hpux */
6740
#endif /* HAVE_CYGWIN */
6741
#endif /* HAVE_OPENPTY */
6742
6743
0
    return Py_BuildValue("(ii)", master_fd, slave_fd);
6744
6745
0
posix_error:
6746
0
    posix_error();
6747
0
error:
6748
0
    if (master_fd != -1)
6749
0
        close(master_fd);
6750
0
    if (slave_fd != -1)
6751
0
        close(slave_fd);
6752
0
    return NULL;
6753
0
}
6754
#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
6755
6756
6757
#ifdef HAVE_FORKPTY
6758
/*[clinic input]
6759
os.forkpty
6760
6761
Fork a new process with a new pseudo-terminal as controlling tty.
6762
6763
Returns a tuple of (pid, master_fd).
6764
Like fork(), return pid of 0 to the child process,
6765
and pid of child to the parent process.
6766
To both, return fd of newly opened pseudo-terminal.
6767
[clinic start generated code]*/
6768
6769
static PyObject *
6770
os_forkpty_impl(PyObject *module)
6771
/*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
6772
0
{
6773
0
    int master_fd = -1;
6774
0
    pid_t pid;
6775
6776
0
    if (_PyInterpreterState_Get() != PyInterpreterState_Main()) {
6777
0
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6778
0
        return NULL;
6779
0
    }
6780
0
    if (PySys_Audit("os.forkpty", NULL) < 0) {
6781
0
        return NULL;
6782
0
    }
6783
0
    PyOS_BeforeFork();
6784
0
    pid = forkpty(&master_fd, NULL, NULL, NULL);
6785
0
    if (pid == 0) {
6786
        /* child: this clobbers and resets the import lock. */
6787
0
        PyOS_AfterFork_Child();
6788
0
    } else {
6789
        /* parent: release the import lock. */
6790
0
        PyOS_AfterFork_Parent();
6791
0
    }
6792
0
    if (pid == -1)
6793
0
        return posix_error();
6794
0
    return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
6795
0
}
6796
#endif /* HAVE_FORKPTY */
6797
6798
6799
#ifdef HAVE_GETEGID
6800
/*[clinic input]
6801
os.getegid
6802
6803
Return the current process's effective group id.
6804
[clinic start generated code]*/
6805
6806
static PyObject *
6807
os_getegid_impl(PyObject *module)
6808
/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
6809
0
{
6810
0
    return _PyLong_FromGid(getegid());
6811
0
}
6812
#endif /* HAVE_GETEGID */
6813
6814
6815
#ifdef HAVE_GETEUID
6816
/*[clinic input]
6817
os.geteuid
6818
6819
Return the current process's effective user id.
6820
[clinic start generated code]*/
6821
6822
static PyObject *
6823
os_geteuid_impl(PyObject *module)
6824
/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
6825
0
{
6826
0
    return _PyLong_FromUid(geteuid());
6827
0
}
6828
#endif /* HAVE_GETEUID */
6829
6830
6831
#ifdef HAVE_GETGID
6832
/*[clinic input]
6833
os.getgid
6834
6835
Return the current process's group id.
6836
[clinic start generated code]*/
6837
6838
static PyObject *
6839
os_getgid_impl(PyObject *module)
6840
/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
6841
0
{
6842
0
    return _PyLong_FromGid(getgid());
6843
0
}
6844
#endif /* HAVE_GETGID */
6845
6846
6847
#ifdef HAVE_GETPID
6848
/*[clinic input]
6849
os.getpid
6850
6851
Return the current process id.
6852
[clinic start generated code]*/
6853
6854
static PyObject *
6855
os_getpid_impl(PyObject *module)
6856
/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
6857
14
{
6858
14
    return PyLong_FromPid(getpid());
6859
14
}
6860
#endif /* HAVE_GETPID */
6861
6862
#ifdef NGROUPS_MAX
6863
0
#define MAX_GROUPS NGROUPS_MAX
6864
#else
6865
    /* defined to be 16 on Solaris7, so this should be a small number */
6866
#define MAX_GROUPS 64
6867
#endif
6868
6869
#ifdef HAVE_GETGROUPLIST
6870
6871
/* AC 3.5: funny apple logic below */
6872
PyDoc_STRVAR(posix_getgrouplist__doc__,
6873
"getgrouplist(user, group) -> list of groups to which a user belongs\n\n\
6874
Returns a list of groups to which a user belongs.\n\n\
6875
    user: username to lookup\n\
6876
    group: base group id of the user");
6877
6878
static PyObject *
6879
posix_getgrouplist(PyObject *self, PyObject *args)
6880
0
{
6881
0
    const char *user;
6882
0
    int i, ngroups;
6883
0
    PyObject *list;
6884
#ifdef __APPLE__
6885
    int *groups, basegid;
6886
#else
6887
0
    gid_t *groups, basegid;
6888
0
#endif
6889
6890
    /*
6891
     * NGROUPS_MAX is defined by POSIX.1 as the maximum
6892
     * number of supplimental groups a users can belong to.
6893
     * We have to increment it by one because
6894
     * getgrouplist() returns both the supplemental groups
6895
     * and the primary group, i.e. all of the groups the
6896
     * user belongs to.
6897
     */
6898
0
    ngroups = 1 + MAX_GROUPS;
6899
6900
#ifdef __APPLE__
6901
    if (!PyArg_ParseTuple(args, "si:getgrouplist", &user, &basegid))
6902
        return NULL;
6903
#else
6904
0
    if (!PyArg_ParseTuple(args, "sO&:getgrouplist", &user,
6905
0
                          _Py_Gid_Converter, &basegid))
6906
0
        return NULL;
6907
0
#endif
6908
6909
0
    while (1) {
6910
#ifdef __APPLE__
6911
        groups = PyMem_New(int, ngroups);
6912
#else
6913
0
        groups = PyMem_New(gid_t, ngroups);
6914
0
#endif
6915
0
        if (groups == NULL) {
6916
0
            return PyErr_NoMemory();
6917
0
        }
6918
6919
0
        int old_ngroups = ngroups;
6920
0
        if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
6921
            /* Success */
6922
0
            break;
6923
0
        }
6924
6925
        /* getgrouplist() fails if the group list is too small */
6926
0
        PyMem_Free(groups);
6927
6928
0
        if (ngroups > old_ngroups) {
6929
            /* If the group list is too small, the glibc implementation of
6930
               getgrouplist() sets ngroups to the total number of groups and
6931
               returns -1. */
6932
0
        }
6933
0
        else {
6934
            /* Double the group list size */
6935
0
            if (ngroups > INT_MAX / 2) {
6936
0
                return PyErr_NoMemory();
6937
0
            }
6938
0
            ngroups *= 2;
6939
0
        }
6940
6941
        /* Retry getgrouplist() with a larger group list */
6942
0
    }
6943
6944
#ifdef _Py_MEMORY_SANITIZER
6945
    /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
6946
    __msan_unpoison(&ngroups, sizeof(ngroups));
6947
    __msan_unpoison(groups, ngroups*sizeof(*groups));
6948
#endif
6949
6950
0
    list = PyList_New(ngroups);
6951
0
    if (list == NULL) {
6952
0
        PyMem_Del(groups);
6953
0
        return NULL;
6954
0
    }
6955
6956
0
    for (i = 0; i < ngroups; i++) {
6957
#ifdef __APPLE__
6958
        PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
6959
#else
6960
0
        PyObject *o = _PyLong_FromGid(groups[i]);
6961
0
#endif
6962
0
        if (o == NULL) {
6963
0
            Py_DECREF(list);
6964
0
            PyMem_Del(groups);
6965
0
            return NULL;
6966
0
        }
6967
0
        PyList_SET_ITEM(list, i, o);
6968
0
    }
6969
6970
0
    PyMem_Del(groups);
6971
6972
0
    return list;
6973
0
}
6974
#endif /* HAVE_GETGROUPLIST */
6975
6976
6977
#ifdef HAVE_GETGROUPS
6978
/*[clinic input]
6979
os.getgroups
6980
6981
Return list of supplemental group IDs for the process.
6982
[clinic start generated code]*/
6983
6984
static PyObject *
6985
os_getgroups_impl(PyObject *module)
6986
/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
6987
0
{
6988
0
    PyObject *result = NULL;
6989
0
    gid_t grouplist[MAX_GROUPS];
6990
6991
    /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
6992
     * This is a helper variable to store the intermediate result when
6993
     * that happens.
6994
     *
6995
     * To keep the code readable the OSX behaviour is unconditional,
6996
     * according to the POSIX spec this should be safe on all unix-y
6997
     * systems.
6998
     */
6999
0
    gid_t* alt_grouplist = grouplist;
7000
0
    int n;
7001
7002
#ifdef __APPLE__
7003
    /* Issue #17557: As of OS X 10.8, getgroups(2) no longer raises EINVAL if
7004
     * there are more groups than can fit in grouplist.  Therefore, on OS X
7005
     * always first call getgroups with length 0 to get the actual number
7006
     * of groups.
7007
     */
7008
    n = getgroups(0, NULL);
7009
    if (n < 0) {
7010
        return posix_error();
7011
    } else if (n <= MAX_GROUPS) {
7012
        /* groups will fit in existing array */
7013
        alt_grouplist = grouplist;
7014
    } else {
7015
        alt_grouplist = PyMem_New(gid_t, n);
7016
        if (alt_grouplist == NULL) {
7017
            return PyErr_NoMemory();
7018
        }
7019
    }
7020
7021
    n = getgroups(n, alt_grouplist);
7022
    if (n == -1) {
7023
        if (alt_grouplist != grouplist) {
7024
            PyMem_Free(alt_grouplist);
7025
        }
7026
        return posix_error();
7027
    }
7028
#else
7029
0
    n = getgroups(MAX_GROUPS, grouplist);
7030
0
    if (n < 0) {
7031
0
        if (errno == EINVAL) {
7032
0
            n = getgroups(0, NULL);
7033
0
            if (n == -1) {
7034
0
                return posix_error();
7035
0
            }
7036
0
            if (n == 0) {
7037
                /* Avoid malloc(0) */
7038
0
                alt_grouplist = grouplist;
7039
0
            } else {
7040
0
                alt_grouplist = PyMem_New(gid_t, n);
7041
0
                if (alt_grouplist == NULL) {
7042
0
                    return PyErr_NoMemory();
7043
0
                }
7044
0
                n = getgroups(n, alt_grouplist);
7045
0
                if (n == -1) {
7046
0
                    PyMem_Free(alt_grouplist);
7047
0
                    return posix_error();
7048
0
                }
7049
0
            }
7050
0
        } else {
7051
0
            return posix_error();
7052
0
        }
7053
0
    }
7054
0
#endif
7055
7056
0
    result = PyList_New(n);
7057
0
    if (result != NULL) {
7058
0
        int i;
7059
0
        for (i = 0; i < n; ++i) {
7060
0
            PyObject *o = _PyLong_FromGid(alt_grouplist[i]);
7061
0
            if (o == NULL) {
7062
0
                Py_DECREF(result);
7063
0
                result = NULL;
7064
0
                break;
7065
0
            }
7066
0
            PyList_SET_ITEM(result, i, o);
7067
0
        }
7068
0
    }
7069
7070
0
    if (alt_grouplist != grouplist) {
7071
0
        PyMem_Free(alt_grouplist);
7072
0
    }
7073
7074
0
    return result;
7075
0
}
7076
#endif /* HAVE_GETGROUPS */
7077
7078
#ifdef HAVE_INITGROUPS
7079
PyDoc_STRVAR(posix_initgroups__doc__,
7080
"initgroups(username, gid) -> None\n\n\
7081
Call the system initgroups() to initialize the group access list with all of\n\
7082
the groups of which the specified username is a member, plus the specified\n\
7083
group id.");
7084
7085
/* AC 3.5: funny apple logic */
7086
static PyObject *
7087
posix_initgroups(PyObject *self, PyObject *args)
7088
0
{
7089
0
    PyObject *oname;
7090
0
    const char *username;
7091
0
    int res;
7092
#ifdef __APPLE__
7093
    int gid;
7094
#else
7095
0
    gid_t gid;
7096
0
#endif
7097
7098
#ifdef __APPLE__
7099
    if (!PyArg_ParseTuple(args, "O&i:initgroups",
7100
                          PyUnicode_FSConverter, &oname,
7101
                          &gid))
7102
#else
7103
0
    if (!PyArg_ParseTuple(args, "O&O&:initgroups",
7104
0
                          PyUnicode_FSConverter, &oname,
7105
0
                          _Py_Gid_Converter, &gid))
7106
0
#endif
7107
0
        return NULL;
7108
0
    username = PyBytes_AS_STRING(oname);
7109
7110
0
    res = initgroups(username, gid);
7111
0
    Py_DECREF(oname);
7112
0
    if (res == -1)
7113
0
        return PyErr_SetFromErrno(PyExc_OSError);
7114
7115
0
    Py_RETURN_NONE;
7116
0
}
7117
#endif /* HAVE_INITGROUPS */
7118
7119
7120
#ifdef HAVE_GETPGID
7121
/*[clinic input]
7122
os.getpgid
7123
7124
    pid: pid_t
7125
7126
Call the system call getpgid(), and return the result.
7127
[clinic start generated code]*/
7128
7129
static PyObject *
7130
os_getpgid_impl(PyObject *module, pid_t pid)
7131
/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
7132
0
{
7133
0
    pid_t pgid = getpgid(pid);
7134
0
    if (pgid < 0)
7135
0
        return posix_error();
7136
0
    return PyLong_FromPid(pgid);
7137
0
}
7138
#endif /* HAVE_GETPGID */
7139
7140
7141
#ifdef HAVE_GETPGRP
7142
/*[clinic input]
7143
os.getpgrp
7144
7145
Return the current process group id.
7146
[clinic start generated code]*/
7147
7148
static PyObject *
7149
os_getpgrp_impl(PyObject *module)
7150
/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
7151
0
{
7152
#ifdef GETPGRP_HAVE_ARG
7153
    return PyLong_FromPid(getpgrp(0));
7154
#else /* GETPGRP_HAVE_ARG */
7155
0
    return PyLong_FromPid(getpgrp());
7156
0
#endif /* GETPGRP_HAVE_ARG */
7157
0
}
7158
#endif /* HAVE_GETPGRP */
7159
7160
7161
#ifdef HAVE_SETPGRP
7162
/*[clinic input]
7163
os.setpgrp
7164
7165
Make the current process the leader of its process group.
7166
[clinic start generated code]*/
7167
7168
static PyObject *
7169
os_setpgrp_impl(PyObject *module)
7170
/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
7171
0
{
7172
#ifdef SETPGRP_HAVE_ARG
7173
    if (setpgrp(0, 0) < 0)
7174
#else /* SETPGRP_HAVE_ARG */
7175
0
    if (setpgrp() < 0)
7176
0
#endif /* SETPGRP_HAVE_ARG */
7177
0
        return posix_error();
7178
0
    Py_RETURN_NONE;
7179
0
}
7180
#endif /* HAVE_SETPGRP */
7181
7182
#ifdef HAVE_GETPPID
7183
7184
#ifdef MS_WINDOWS
7185
#include <tlhelp32.h>
7186
7187
static PyObject*
7188
win32_getppid()
7189
{
7190
    HANDLE snapshot;
7191
    pid_t mypid;
7192
    PyObject* result = NULL;
7193
    BOOL have_record;
7194
    PROCESSENTRY32 pe;
7195
7196
    mypid = getpid(); /* This function never fails */
7197
7198
    snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
7199
    if (snapshot == INVALID_HANDLE_VALUE)
7200
        return PyErr_SetFromWindowsErr(GetLastError());
7201
7202
    pe.dwSize = sizeof(pe);
7203
    have_record = Process32First(snapshot, &pe);
7204
    while (have_record) {
7205
        if (mypid == (pid_t)pe.th32ProcessID) {
7206
            /* We could cache the ulong value in a static variable. */
7207
            result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
7208
            break;
7209
        }
7210
7211
        have_record = Process32Next(snapshot, &pe);
7212
    }
7213
7214
    /* If our loop exits and our pid was not found (result will be NULL)
7215
     * then GetLastError will return ERROR_NO_MORE_FILES. This is an
7216
     * error anyway, so let's raise it. */
7217
    if (!result)
7218
        result = PyErr_SetFromWindowsErr(GetLastError());
7219
7220
    CloseHandle(snapshot);
7221
7222
    return result;
7223
}
7224
#endif /*MS_WINDOWS*/
7225
7226
7227
/*[clinic input]
7228
os.getppid
7229
7230
Return the parent's process id.
7231
7232
If the parent process has already exited, Windows machines will still
7233
return its id; others systems will return the id of the 'init' process (1).
7234
[clinic start generated code]*/
7235
7236
static PyObject *
7237
os_getppid_impl(PyObject *module)
7238
/*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
7239
0
{
7240
#ifdef MS_WINDOWS
7241
    return win32_getppid();
7242
#else
7243
0
    return PyLong_FromPid(getppid());
7244
0
#endif
7245
0
}
7246
#endif /* HAVE_GETPPID */
7247
7248
7249
#ifdef HAVE_GETLOGIN
7250
/*[clinic input]
7251
os.getlogin
7252
7253
Return the actual login name.
7254
[clinic start generated code]*/
7255
7256
static PyObject *
7257
os_getlogin_impl(PyObject *module)
7258
/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
7259
0
{
7260
0
    PyObject *result = NULL;
7261
#ifdef MS_WINDOWS
7262
    wchar_t user_name[UNLEN + 1];
7263
    DWORD num_chars = Py_ARRAY_LENGTH(user_name);
7264
7265
    if (GetUserNameW(user_name, &num_chars)) {
7266
        /* num_chars is the number of unicode chars plus null terminator */
7267
        result = PyUnicode_FromWideChar(user_name, num_chars - 1);
7268
    }
7269
    else
7270
        result = PyErr_SetFromWindowsErr(GetLastError());
7271
#else
7272
0
    char *name;
7273
0
    int old_errno = errno;
7274
7275
0
    errno = 0;
7276
0
    name = getlogin();
7277
0
    if (name == NULL) {
7278
0
        if (errno)
7279
0
            posix_error();
7280
0
        else
7281
0
            PyErr_SetString(PyExc_OSError, "unable to determine login name");
7282
0
    }
7283
0
    else
7284
0
        result = PyUnicode_DecodeFSDefault(name);
7285
0
    errno = old_errno;
7286
0
#endif
7287
0
    return result;
7288
0
}
7289
#endif /* HAVE_GETLOGIN */
7290
7291
7292
#ifdef HAVE_GETUID
7293
/*[clinic input]
7294
os.getuid
7295
7296
Return the current process's user id.
7297
[clinic start generated code]*/
7298
7299
static PyObject *
7300
os_getuid_impl(PyObject *module)
7301
/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
7302
0
{
7303
0
    return _PyLong_FromUid(getuid());
7304
0
}
7305
#endif /* HAVE_GETUID */
7306
7307
7308
#ifdef MS_WINDOWS
7309
#define HAVE_KILL
7310
#endif /* MS_WINDOWS */
7311
7312
#ifdef HAVE_KILL
7313
/*[clinic input]
7314
os.kill
7315
7316
    pid: pid_t
7317
    signal: Py_ssize_t
7318
    /
7319
7320
Kill a process with a signal.
7321
[clinic start generated code]*/
7322
7323
static PyObject *
7324
os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
7325
/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
7326
0
{
7327
0
    if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
7328
0
        return NULL;
7329
0
    }
7330
0
#ifndef MS_WINDOWS
7331
0
    if (kill(pid, (int)signal) == -1)
7332
0
        return posix_error();
7333
0
    Py_RETURN_NONE;
7334
#else /* !MS_WINDOWS */
7335
    PyObject *result;
7336
    DWORD sig = (DWORD)signal;
7337
    DWORD err;
7338
    HANDLE handle;
7339
7340
    /* Console processes which share a common console can be sent CTRL+C or
7341
       CTRL+BREAK events, provided they handle said events. */
7342
    if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
7343
        if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
7344
            err = GetLastError();
7345
            PyErr_SetFromWindowsErr(err);
7346
        }
7347
        else
7348
            Py_RETURN_NONE;
7349
    }
7350
7351
    /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
7352
       attempt to open and terminate the process. */
7353
    handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
7354
    if (handle == NULL) {
7355
        err = GetLastError();
7356
        return PyErr_SetFromWindowsErr(err);
7357
    }
7358
7359
    if (TerminateProcess(handle, sig) == 0) {
7360
        err = GetLastError();
7361
        result = PyErr_SetFromWindowsErr(err);
7362
    } else {
7363
        Py_INCREF(Py_None);
7364
        result = Py_None;
7365
    }
7366
7367
    CloseHandle(handle);
7368
    return result;
7369
#endif /* !MS_WINDOWS */
7370
0
}
7371
#endif /* HAVE_KILL */
7372
7373
7374
#ifdef HAVE_KILLPG
7375
/*[clinic input]
7376
os.killpg
7377
7378
    pgid: pid_t
7379
    signal: int
7380
    /
7381
7382
Kill a process group with a signal.
7383
[clinic start generated code]*/
7384
7385
static PyObject *
7386
os_killpg_impl(PyObject *module, pid_t pgid, int signal)
7387
/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
7388
0
{
7389
0
    if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
7390
0
        return NULL;
7391
0
    }
7392
    /* XXX some man pages make the `pgid` parameter an int, others
7393
       a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
7394
       take the same type. Moreover, pid_t is always at least as wide as
7395
       int (else compilation of this module fails), which is safe. */
7396
0
    if (killpg(pgid, signal) == -1)
7397
0
        return posix_error();
7398
0
    Py_RETURN_NONE;
7399
0
}
7400
#endif /* HAVE_KILLPG */
7401
7402
7403
#ifdef HAVE_PLOCK
7404
#ifdef HAVE_SYS_LOCK_H
7405
#include <sys/lock.h>
7406
#endif
7407
7408
/*[clinic input]
7409
os.plock
7410
    op: int
7411
    /
7412
7413
Lock program segments into memory.");
7414
[clinic start generated code]*/
7415
7416
static PyObject *
7417
os_plock_impl(PyObject *module, int op)
7418
/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
7419
{
7420
    if (plock(op) == -1)
7421
        return posix_error();
7422
    Py_RETURN_NONE;
7423
}
7424
#endif /* HAVE_PLOCK */
7425
7426
7427
#ifdef HAVE_SETUID
7428
/*[clinic input]
7429
os.setuid
7430
7431
    uid: uid_t
7432
    /
7433
7434
Set the current process's user id.
7435
[clinic start generated code]*/
7436
7437
static PyObject *
7438
os_setuid_impl(PyObject *module, uid_t uid)
7439
/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
7440
0
{
7441
0
    if (setuid(uid) < 0)
7442
0
        return posix_error();
7443
0
    Py_RETURN_NONE;
7444
0
}
7445
#endif /* HAVE_SETUID */
7446
7447
7448
#ifdef HAVE_SETEUID
7449
/*[clinic input]
7450
os.seteuid
7451
7452
    euid: uid_t
7453
    /
7454
7455
Set the current process's effective user id.
7456
[clinic start generated code]*/
7457
7458
static PyObject *
7459
os_seteuid_impl(PyObject *module, uid_t euid)
7460
/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
7461
0
{
7462
0
    if (seteuid(euid) < 0)
7463
0
        return posix_error();
7464
0
    Py_RETURN_NONE;
7465
0
}
7466
#endif /* HAVE_SETEUID */
7467
7468
7469
#ifdef HAVE_SETEGID
7470
/*[clinic input]
7471
os.setegid
7472
7473
    egid: gid_t
7474
    /
7475
7476
Set the current process's effective group id.
7477
[clinic start generated code]*/
7478
7479
static PyObject *
7480
os_setegid_impl(PyObject *module, gid_t egid)
7481
/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
7482
0
{
7483
0
    if (setegid(egid) < 0)
7484
0
        return posix_error();
7485
0
    Py_RETURN_NONE;
7486
0
}
7487
#endif /* HAVE_SETEGID */
7488
7489
7490
#ifdef HAVE_SETREUID
7491
/*[clinic input]
7492
os.setreuid
7493
7494
    ruid: uid_t
7495
    euid: uid_t
7496
    /
7497
7498
Set the current process's real and effective user ids.
7499
[clinic start generated code]*/
7500
7501
static PyObject *
7502
os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
7503
/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
7504
0
{
7505
0
    if (setreuid(ruid, euid) < 0) {
7506
0
        return posix_error();
7507
0
    } else {
7508
0
        Py_RETURN_NONE;
7509
0
    }
7510
0
}
7511
#endif /* HAVE_SETREUID */
7512
7513
7514
#ifdef HAVE_SETREGID
7515
/*[clinic input]
7516
os.setregid
7517
7518
    rgid: gid_t
7519
    egid: gid_t
7520
    /
7521
7522
Set the current process's real and effective group ids.
7523
[clinic start generated code]*/
7524
7525
static PyObject *
7526
os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
7527
/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
7528
0
{
7529
0
    if (setregid(rgid, egid) < 0)
7530
0
        return posix_error();
7531
0
    Py_RETURN_NONE;
7532
0
}
7533
#endif /* HAVE_SETREGID */
7534
7535
7536
#ifdef HAVE_SETGID
7537
/*[clinic input]
7538
os.setgid
7539
    gid: gid_t
7540
    /
7541
7542
Set the current process's group id.
7543
[clinic start generated code]*/
7544
7545
static PyObject *
7546
os_setgid_impl(PyObject *module, gid_t gid)
7547
/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
7548
0
{
7549
0
    if (setgid(gid) < 0)
7550
0
        return posix_error();
7551
0
    Py_RETURN_NONE;
7552
0
}
7553
#endif /* HAVE_SETGID */
7554
7555
7556
#ifdef HAVE_SETGROUPS
7557
/*[clinic input]
7558
os.setgroups
7559
7560
    groups: object
7561
    /
7562
7563
Set the groups of the current process to list.
7564
[clinic start generated code]*/
7565
7566
static PyObject *
7567
os_setgroups(PyObject *module, PyObject *groups)
7568
/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
7569
0
{
7570
0
    Py_ssize_t i, len;
7571
0
    gid_t grouplist[MAX_GROUPS];
7572
7573
0
    if (!PySequence_Check(groups)) {
7574
0
        PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
7575
0
        return NULL;
7576
0
    }
7577
0
    len = PySequence_Size(groups);
7578
0
    if (len < 0) {
7579
0
        return NULL;
7580
0
    }
7581
0
    if (len > MAX_GROUPS) {
7582
0
        PyErr_SetString(PyExc_ValueError, "too many groups");
7583
0
        return NULL;
7584
0
    }
7585
0
    for(i = 0; i < len; i++) {
7586
0
        PyObject *elem;
7587
0
        elem = PySequence_GetItem(groups, i);
7588
0
        if (!elem)
7589
0
            return NULL;
7590
0
        if (!PyLong_Check(elem)) {
7591
0
            PyErr_SetString(PyExc_TypeError,
7592
0
                            "groups must be integers");
7593
0
            Py_DECREF(elem);
7594
0
            return NULL;
7595
0
        } else {
7596
0
            if (!_Py_Gid_Converter(elem, &grouplist[i])) {
7597
0
                Py_DECREF(elem);
7598
0
                return NULL;
7599
0
            }
7600
0
        }
7601
0
        Py_DECREF(elem);
7602
0
    }
7603
7604
0
    if (setgroups(len, grouplist) < 0)
7605
0
        return posix_error();
7606
0
    Py_RETURN_NONE;
7607
0
}
7608
#endif /* HAVE_SETGROUPS */
7609
7610
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
7611
static PyObject *
7612
wait_helper(pid_t pid, int status, struct rusage *ru)
7613
0
{
7614
0
    PyObject *result;
7615
0
    static PyObject *struct_rusage;
7616
0
    _Py_IDENTIFIER(struct_rusage);
7617
7618
0
    if (pid == -1)
7619
0
        return posix_error();
7620
7621
0
    if (struct_rusage == NULL) {
7622
0
        PyObject *m = PyImport_ImportModuleNoBlock("resource");
7623
0
        if (m == NULL)
7624
0
            return NULL;
7625
0
        struct_rusage = _PyObject_GetAttrId(m, &PyId_struct_rusage);
7626
0
        Py_DECREF(m);
7627
0
        if (struct_rusage == NULL)
7628
0
            return NULL;
7629
0
    }
7630
7631
    /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
7632
0
    result = PyStructSequence_New((PyTypeObject*) struct_rusage);
7633
0
    if (!result)
7634
0
        return NULL;
7635
7636
0
#ifndef doubletime
7637
0
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
7638
0
#endif
7639
7640
0
    PyStructSequence_SET_ITEM(result, 0,
7641
0
                              PyFloat_FromDouble(doubletime(ru->ru_utime)));
7642
0
    PyStructSequence_SET_ITEM(result, 1,
7643
0
                              PyFloat_FromDouble(doubletime(ru->ru_stime)));
7644
0
#define SET_INT(result, index, value)\
7645
0
        PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
7646
0
    SET_INT(result, 2, ru->ru_maxrss);
7647
0
    SET_INT(result, 3, ru->ru_ixrss);
7648
0
    SET_INT(result, 4, ru->ru_idrss);
7649
0
    SET_INT(result, 5, ru->ru_isrss);
7650
0
    SET_INT(result, 6, ru->ru_minflt);
7651
0
    SET_INT(result, 7, ru->ru_majflt);
7652
0
    SET_INT(result, 8, ru->ru_nswap);
7653
0
    SET_INT(result, 9, ru->ru_inblock);
7654
0
    SET_INT(result, 10, ru->ru_oublock);
7655
0
    SET_INT(result, 11, ru->ru_msgsnd);
7656
0
    SET_INT(result, 12, ru->ru_msgrcv);
7657
0
    SET_INT(result, 13, ru->ru_nsignals);
7658
0
    SET_INT(result, 14, ru->ru_nvcsw);
7659
0
    SET_INT(result, 15, ru->ru_nivcsw);
7660
0
#undef SET_INT
7661
7662
0
    if (PyErr_Occurred()) {
7663
0
        Py_DECREF(result);
7664
0
        return NULL;
7665
0
    }
7666
7667
0
    return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
7668
0
}
7669
#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
7670
7671
7672
#ifdef HAVE_WAIT3
7673
/*[clinic input]
7674
os.wait3
7675
7676
    options: int
7677
Wait for completion of a child process.
7678
7679
Returns a tuple of information about the child process:
7680
  (pid, status, rusage)
7681
[clinic start generated code]*/
7682
7683
static PyObject *
7684
os_wait3_impl(PyObject *module, int options)
7685
/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
7686
0
{
7687
0
    pid_t pid;
7688
0
    struct rusage ru;
7689
0
    int async_err = 0;
7690
0
    WAIT_TYPE status;
7691
0
    WAIT_STATUS_INT(status) = 0;
7692
7693
0
    do {
7694
0
        Py_BEGIN_ALLOW_THREADS
7695
0
        pid = wait3(&status, options, &ru);
7696
0
        Py_END_ALLOW_THREADS
7697
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7698
0
    if (pid < 0)
7699
0
        return (!async_err) ? posix_error() : NULL;
7700
7701
0
    return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
7702
0
}
7703
#endif /* HAVE_WAIT3 */
7704
7705
7706
#ifdef HAVE_WAIT4
7707
/*[clinic input]
7708
7709
os.wait4
7710
7711
    pid: pid_t
7712
    options: int
7713
7714
Wait for completion of a specific child process.
7715
7716
Returns a tuple of information about the child process:
7717
  (pid, status, rusage)
7718
[clinic start generated code]*/
7719
7720
static PyObject *
7721
os_wait4_impl(PyObject *module, pid_t pid, int options)
7722
/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
7723
0
{
7724
0
    pid_t res;
7725
0
    struct rusage ru;
7726
0
    int async_err = 0;
7727
0
    WAIT_TYPE status;
7728
0
    WAIT_STATUS_INT(status) = 0;
7729
7730
0
    do {
7731
0
        Py_BEGIN_ALLOW_THREADS
7732
0
        res = wait4(pid, &status, options, &ru);
7733
0
        Py_END_ALLOW_THREADS
7734
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7735
0
    if (res < 0)
7736
0
        return (!async_err) ? posix_error() : NULL;
7737
7738
0
    return wait_helper(res, WAIT_STATUS_INT(status), &ru);
7739
0
}
7740
#endif /* HAVE_WAIT4 */
7741
7742
7743
#if defined(HAVE_WAITID) && !defined(__APPLE__)
7744
/*[clinic input]
7745
os.waitid
7746
7747
    idtype: idtype_t
7748
        Must be one of be P_PID, P_PGID or P_ALL.
7749
    id: id_t
7750
        The id to wait on.
7751
    options: int
7752
        Constructed from the ORing of one or more of WEXITED, WSTOPPED
7753
        or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
7754
    /
7755
7756
Returns the result of waiting for a process or processes.
7757
7758
Returns either waitid_result or None if WNOHANG is specified and there are
7759
no children in a waitable state.
7760
[clinic start generated code]*/
7761
7762
static PyObject *
7763
os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
7764
/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
7765
0
{
7766
0
    PyObject *result;
7767
0
    int res;
7768
0
    int async_err = 0;
7769
0
    siginfo_t si;
7770
0
    si.si_pid = 0;
7771
7772
0
    do {
7773
0
        Py_BEGIN_ALLOW_THREADS
7774
0
        res = waitid(idtype, id, &si, options);
7775
0
        Py_END_ALLOW_THREADS
7776
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7777
0
    if (res < 0)
7778
0
        return (!async_err) ? posix_error() : NULL;
7779
7780
0
    if (si.si_pid == 0)
7781
0
        Py_RETURN_NONE;
7782
7783
0
    result = PyStructSequence_New(WaitidResultType);
7784
0
    if (!result)
7785
0
        return NULL;
7786
7787
0
    PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
7788
0
    PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
7789
0
    PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
7790
0
    PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
7791
0
    PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
7792
0
    if (PyErr_Occurred()) {
7793
0
        Py_DECREF(result);
7794
0
        return NULL;
7795
0
    }
7796
7797
0
    return result;
7798
0
}
7799
#endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
7800
7801
7802
#if defined(HAVE_WAITPID)
7803
/*[clinic input]
7804
os.waitpid
7805
    pid: pid_t
7806
    options: int
7807
    /
7808
7809
Wait for completion of a given child process.
7810
7811
Returns a tuple of information regarding the child process:
7812
    (pid, status)
7813
7814
The options argument is ignored on Windows.
7815
[clinic start generated code]*/
7816
7817
static PyObject *
7818
os_waitpid_impl(PyObject *module, pid_t pid, int options)
7819
/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
7820
0
{
7821
0
    pid_t res;
7822
0
    int async_err = 0;
7823
0
    WAIT_TYPE status;
7824
0
    WAIT_STATUS_INT(status) = 0;
7825
7826
0
    do {
7827
0
        Py_BEGIN_ALLOW_THREADS
7828
0
        res = waitpid(pid, &status, options);
7829
0
        Py_END_ALLOW_THREADS
7830
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7831
0
    if (res < 0)
7832
0
        return (!async_err) ? posix_error() : NULL;
7833
7834
0
    return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
7835
0
}
7836
#elif defined(HAVE_CWAIT)
7837
/* MS C has a variant of waitpid() that's usable for most purposes. */
7838
/*[clinic input]
7839
os.waitpid
7840
    pid: intptr_t
7841
    options: int
7842
    /
7843
7844
Wait for completion of a given process.
7845
7846
Returns a tuple of information regarding the process:
7847
    (pid, status << 8)
7848
7849
The options argument is ignored on Windows.
7850
[clinic start generated code]*/
7851
7852
static PyObject *
7853
os_waitpid_impl(PyObject *module, intptr_t pid, int options)
7854
/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
7855
{
7856
    int status;
7857
    intptr_t res;
7858
    int async_err = 0;
7859
7860
    do {
7861
        Py_BEGIN_ALLOW_THREADS
7862
        _Py_BEGIN_SUPPRESS_IPH
7863
        res = _cwait(&status, pid, options);
7864
        _Py_END_SUPPRESS_IPH
7865
        Py_END_ALLOW_THREADS
7866
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7867
    if (res < 0)
7868
        return (!async_err) ? posix_error() : NULL;
7869
7870
    unsigned long long ustatus = (unsigned int)status;
7871
7872
    /* shift the status left a byte so this is more like the POSIX waitpid */
7873
    return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
7874
}
7875
#endif
7876
7877
7878
#ifdef HAVE_WAIT
7879
/*[clinic input]
7880
os.wait
7881
7882
Wait for completion of a child process.
7883
7884
Returns a tuple of information about the child process:
7885
    (pid, status)
7886
[clinic start generated code]*/
7887
7888
static PyObject *
7889
os_wait_impl(PyObject *module)
7890
/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
7891
0
{
7892
0
    pid_t pid;
7893
0
    int async_err = 0;
7894
0
    WAIT_TYPE status;
7895
0
    WAIT_STATUS_INT(status) = 0;
7896
7897
0
    do {
7898
0
        Py_BEGIN_ALLOW_THREADS
7899
0
        pid = wait(&status);
7900
0
        Py_END_ALLOW_THREADS
7901
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7902
0
    if (pid < 0)
7903
0
        return (!async_err) ? posix_error() : NULL;
7904
7905
0
    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
7906
0
}
7907
#endif /* HAVE_WAIT */
7908
7909
7910
#if defined(HAVE_READLINK) || defined(MS_WINDOWS)
7911
/*[clinic input]
7912
os.readlink
7913
7914
    path: path_t
7915
    *
7916
    dir_fd: dir_fd(requires='readlinkat') = None
7917
7918
Return a string representing the path to which the symbolic link points.
7919
7920
If dir_fd is not None, it should be a file descriptor open to a directory,
7921
and path should be relative; path will then be relative to that directory.
7922
7923
dir_fd may not be implemented on your platform.  If it is unavailable,
7924
using it will raise a NotImplementedError.
7925
[clinic start generated code]*/
7926
7927
static PyObject *
7928
os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
7929
/*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
7930
0
{
7931
0
#if defined(HAVE_READLINK)
7932
0
    char buffer[MAXPATHLEN+1];
7933
0
    ssize_t length;
7934
7935
0
    Py_BEGIN_ALLOW_THREADS
7936
0
#ifdef HAVE_READLINKAT
7937
0
    if (dir_fd != DEFAULT_DIR_FD)
7938
0
        length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
7939
0
    else
7940
0
#endif
7941
0
        length = readlink(path->narrow, buffer, MAXPATHLEN);
7942
0
    Py_END_ALLOW_THREADS
7943
7944
0
    if (length < 0) {
7945
0
        return path_error(path);
7946
0
    }
7947
0
    buffer[length] = '\0';
7948
7949
0
    if (PyUnicode_Check(path->object))
7950
0
        return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
7951
0
    else
7952
0
        return PyBytes_FromStringAndSize(buffer, length);
7953
#elif defined(MS_WINDOWS)
7954
    DWORD n_bytes_returned;
7955
    DWORD io_result = 0;
7956
    HANDLE reparse_point_handle;
7957
    char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
7958
    _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
7959
    PyObject *result = NULL;
7960
7961
    /* First get a handle to the reparse point */
7962
    Py_BEGIN_ALLOW_THREADS
7963
    reparse_point_handle = CreateFileW(
7964
        path->wide,
7965
        0,
7966
        0,
7967
        0,
7968
        OPEN_EXISTING,
7969
        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
7970
        0);
7971
    if (reparse_point_handle != INVALID_HANDLE_VALUE) {
7972
        /* New call DeviceIoControl to read the reparse point */
7973
        io_result = DeviceIoControl(
7974
            reparse_point_handle,
7975
            FSCTL_GET_REPARSE_POINT,
7976
            0, 0, /* in buffer */
7977
            target_buffer, sizeof(target_buffer),
7978
            &n_bytes_returned,
7979
            0 /* we're not using OVERLAPPED_IO */
7980
            );
7981
        CloseHandle(reparse_point_handle);
7982
    }
7983
    Py_END_ALLOW_THREADS
7984
7985
    if (io_result == 0) {
7986
        return path_error(path);
7987
    }
7988
7989
    wchar_t *name = NULL;
7990
    Py_ssize_t nameLen = 0;
7991
    if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
7992
    {
7993
        name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
7994
                           rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
7995
        nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
7996
    }
7997
    else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
7998
    {
7999
        name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
8000
                           rdb->MountPointReparseBuffer.SubstituteNameOffset);
8001
        nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8002
    }
8003
    else
8004
    {
8005
        PyErr_SetString(PyExc_ValueError, "not a symbolic link");
8006
    }
8007
    if (name) {
8008
        if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
8009
            /* Our buffer is mutable, so this is okay */
8010
            name[1] = L'\\';
8011
        }
8012
        result = PyUnicode_FromWideChar(name, nameLen);
8013
        if (result && path->narrow) {
8014
            Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
8015
        }
8016
    }
8017
    return result;
8018
#endif
8019
0
}
8020
#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
8021
8022
#ifdef HAVE_SYMLINK
8023
8024
#if defined(MS_WINDOWS)
8025
8026
/* Remove the last portion of the path - return 0 on success */
8027
static int
8028
_dirnameW(WCHAR *path)
8029
{
8030
    WCHAR *ptr;
8031
    size_t length = wcsnlen_s(path, MAX_PATH);
8032
    if (length == MAX_PATH) {
8033
        return -1;
8034
    }
8035
8036
    /* walk the path from the end until a backslash is encountered */
8037
    for(ptr = path + length; ptr != path; ptr--) {
8038
        if (*ptr == L'\\' || *ptr == L'/') {
8039
            break;
8040
        }
8041
    }
8042
    *ptr = 0;
8043
    return 0;
8044
}
8045
8046
/* Is this path absolute? */
8047
static int
8048
_is_absW(const WCHAR *path)
8049
{
8050
    return path[0] == L'\\' || path[0] == L'/' ||
8051
        (path[0] && path[1] == L':');
8052
}
8053
8054
/* join root and rest with a backslash - return 0 on success */
8055
static int
8056
_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
8057
{
8058
    if (_is_absW(rest)) {
8059
        return wcscpy_s(dest_path, MAX_PATH, rest);
8060
    }
8061
8062
    if (wcscpy_s(dest_path, MAX_PATH, root)) {
8063
        return -1;
8064
    }
8065
8066
    if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
8067
        return -1;
8068
    }
8069
8070
    return wcscat_s(dest_path, MAX_PATH, rest);
8071
}
8072
8073
/* Return True if the path at src relative to dest is a directory */
8074
static int
8075
_check_dirW(LPCWSTR src, LPCWSTR dest)
8076
{
8077
    WIN32_FILE_ATTRIBUTE_DATA src_info;
8078
    WCHAR dest_parent[MAX_PATH];
8079
    WCHAR src_resolved[MAX_PATH] = L"";
8080
8081
    /* dest_parent = os.path.dirname(dest) */
8082
    if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
8083
        _dirnameW(dest_parent)) {
8084
        return 0;
8085
    }
8086
    /* src_resolved = os.path.join(dest_parent, src) */
8087
    if (_joinW(src_resolved, dest_parent, src)) {
8088
        return 0;
8089
    }
8090
    return (
8091
        GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
8092
        && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
8093
    );
8094
}
8095
#endif
8096
8097
8098
/*[clinic input]
8099
os.symlink
8100
    src: path_t
8101
    dst: path_t
8102
    target_is_directory: bool = False
8103
    *
8104
    dir_fd: dir_fd(requires='symlinkat')=None
8105
8106
# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
8107
8108
Create a symbolic link pointing to src named dst.
8109
8110
target_is_directory is required on Windows if the target is to be
8111
  interpreted as a directory.  (On Windows, symlink requires
8112
  Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
8113
  target_is_directory is ignored on non-Windows platforms.
8114
8115
If dir_fd is not None, it should be a file descriptor open to a directory,
8116
  and path should be relative; path will then be relative to that directory.
8117
dir_fd may not be implemented on your platform.
8118
  If it is unavailable, using it will raise a NotImplementedError.
8119
8120
[clinic start generated code]*/
8121
8122
static PyObject *
8123
os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
8124
                int target_is_directory, int dir_fd)
8125
/*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
8126
0
{
8127
#ifdef MS_WINDOWS
8128
    DWORD result;
8129
    DWORD flags = 0;
8130
8131
    /* Assumed true, set to false if detected to not be available. */
8132
    static int windows_has_symlink_unprivileged_flag = TRUE;
8133
#else
8134
0
    int result;
8135
0
#endif
8136
8137
0
    if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
8138
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
8139
0
        return NULL;
8140
0
    }
8141
8142
#ifdef MS_WINDOWS
8143
8144
    if (windows_has_symlink_unprivileged_flag) {
8145
        /* Allow non-admin symlinks if system allows it. */
8146
        flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
8147
    }
8148
8149
    Py_BEGIN_ALLOW_THREADS
8150
    _Py_BEGIN_SUPPRESS_IPH
8151
    /* if src is a directory, ensure flags==1 (target_is_directory bit) */
8152
    if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
8153
        flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
8154
    }
8155
8156
    result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8157
    _Py_END_SUPPRESS_IPH
8158
    Py_END_ALLOW_THREADS
8159
8160
    if (windows_has_symlink_unprivileged_flag && !result &&
8161
        ERROR_INVALID_PARAMETER == GetLastError()) {
8162
8163
        Py_BEGIN_ALLOW_THREADS
8164
        _Py_BEGIN_SUPPRESS_IPH
8165
        /* This error might be caused by
8166
        SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
8167
        Try again, and update windows_has_symlink_unprivileged_flag if we
8168
        are successful this time.
8169
8170
        NOTE: There is a risk of a race condition here if there are other
8171
        conditions than the flag causing ERROR_INVALID_PARAMETER, and
8172
        another process (or thread) changes that condition in between our
8173
        calls to CreateSymbolicLink.
8174
        */
8175
        flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
8176
        result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8177
        _Py_END_SUPPRESS_IPH
8178
        Py_END_ALLOW_THREADS
8179
8180
        if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
8181
            windows_has_symlink_unprivileged_flag = FALSE;
8182
        }
8183
    }
8184
8185
    if (!result)
8186
        return path_error2(src, dst);
8187
8188
#else
8189
8190
0
    if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
8191
0
        PyErr_SetString(PyExc_ValueError,
8192
0
            "symlink: src and dst must be the same type");
8193
0
        return NULL;
8194
0
    }
8195
8196
0
    Py_BEGIN_ALLOW_THREADS
8197
0
#if HAVE_SYMLINKAT
8198
0
    if (dir_fd != DEFAULT_DIR_FD)
8199
0
        result = symlinkat(src->narrow, dir_fd, dst->narrow);
8200
0
    else
8201
0
#endif
8202
0
        result = symlink(src->narrow, dst->narrow);
8203
0
    Py_END_ALLOW_THREADS
8204
8205
0
    if (result)
8206
0
        return path_error2(src, dst);
8207
0
#endif
8208
8209
0
    Py_RETURN_NONE;
8210
0
}
8211
#endif /* HAVE_SYMLINK */
8212
8213
8214
8215
8216
static PyStructSequence_Field times_result_fields[] = {
8217
    {"user",    "user time"},
8218
    {"system",   "system time"},
8219
    {"children_user",    "user time of children"},
8220
    {"children_system",    "system time of children"},
8221
    {"elapsed",    "elapsed time since an arbitrary point in the past"},
8222
    {NULL}
8223
};
8224
8225
PyDoc_STRVAR(times_result__doc__,
8226
"times_result: Result from os.times().\n\n\
8227
This object may be accessed either as a tuple of\n\
8228
  (user, system, children_user, children_system, elapsed),\n\
8229
or via the attributes user, system, children_user, children_system,\n\
8230
and elapsed.\n\
8231
\n\
8232
See os.times for more information.");
8233
8234
static PyStructSequence_Desc times_result_desc = {
8235
    "times_result", /* name */
8236
    times_result__doc__, /* doc */
8237
    times_result_fields,
8238
    5
8239
};
8240
8241
static PyTypeObject* TimesResultType;
8242
8243
#ifdef MS_WINDOWS
8244
#define HAVE_TIMES  /* mandatory, for the method table */
8245
#endif
8246
8247
#ifdef HAVE_TIMES
8248
8249
static PyObject *
8250
build_times_result(double user, double system,
8251
    double children_user, double children_system,
8252
    double elapsed)
8253
0
{
8254
0
    PyObject *value = PyStructSequence_New(TimesResultType);
8255
0
    if (value == NULL)
8256
0
        return NULL;
8257
8258
0
#define SET(i, field) \
8259
0
    { \
8260
0
    PyObject *o = PyFloat_FromDouble(field); \
8261
0
    if (!o) { \
8262
0
        Py_DECREF(value); \
8263
0
        return NULL; \
8264
0
    } \
8265
0
    PyStructSequence_SET_ITEM(value, i, o); \
8266
0
    } \
8267
0
8268
0
    SET(0, user);
8269
0
    SET(1, system);
8270
0
    SET(2, children_user);
8271
0
    SET(3, children_system);
8272
0
    SET(4, elapsed);
8273
8274
0
#undef SET
8275
8276
0
    return value;
8277
0
}
8278
8279
8280
#ifndef MS_WINDOWS
8281
#define NEED_TICKS_PER_SECOND
8282
static long ticks_per_second = -1;
8283
#endif /* MS_WINDOWS */
8284
8285
/*[clinic input]
8286
os.times
8287
8288
Return a collection containing process timing information.
8289
8290
The object returned behaves like a named tuple with these fields:
8291
  (utime, stime, cutime, cstime, elapsed_time)
8292
All fields are floating point numbers.
8293
[clinic start generated code]*/
8294
8295
static PyObject *
8296
os_times_impl(PyObject *module)
8297
/*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
8298
#ifdef MS_WINDOWS
8299
{
8300
    FILETIME create, exit, kernel, user;
8301
    HANDLE hProc;
8302
    hProc = GetCurrentProcess();
8303
    GetProcessTimes(hProc, &create, &exit, &kernel, &user);
8304
    /* The fields of a FILETIME structure are the hi and lo part
8305
       of a 64-bit value expressed in 100 nanosecond units.
8306
       1e7 is one second in such units; 1e-7 the inverse.
8307
       429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
8308
    */
8309
    return build_times_result(
8310
        (double)(user.dwHighDateTime*429.4967296 +
8311
                 user.dwLowDateTime*1e-7),
8312
        (double)(kernel.dwHighDateTime*429.4967296 +
8313
                 kernel.dwLowDateTime*1e-7),
8314
        (double)0,
8315
        (double)0,
8316
        (double)0);
8317
}
8318
#else /* MS_WINDOWS */
8319
0
{
8320
8321
8322
0
    struct tms t;
8323
0
    clock_t c;
8324
0
    errno = 0;
8325
0
    c = times(&t);
8326
0
    if (c == (clock_t) -1)
8327
0
        return posix_error();
8328
0
    return build_times_result(
8329
0
                         (double)t.tms_utime / ticks_per_second,
8330
0
                         (double)t.tms_stime / ticks_per_second,
8331
0
                         (double)t.tms_cutime / ticks_per_second,
8332
0
                         (double)t.tms_cstime / ticks_per_second,
8333
0
                         (double)c / ticks_per_second);
8334
0
}
8335
#endif /* MS_WINDOWS */
8336
#endif /* HAVE_TIMES */
8337
8338
8339
#ifdef HAVE_GETSID
8340
/*[clinic input]
8341
os.getsid
8342
8343
    pid: pid_t
8344
    /
8345
8346
Call the system call getsid(pid) and return the result.
8347
[clinic start generated code]*/
8348
8349
static PyObject *
8350
os_getsid_impl(PyObject *module, pid_t pid)
8351
/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
8352
0
{
8353
0
    int sid;
8354
0
    sid = getsid(pid);
8355
0
    if (sid < 0)
8356
0
        return posix_error();
8357
0
    return PyLong_FromLong((long)sid);
8358
0
}
8359
#endif /* HAVE_GETSID */
8360
8361
8362
#ifdef HAVE_SETSID
8363
/*[clinic input]
8364
os.setsid
8365
8366
Call the system call setsid().
8367
[clinic start generated code]*/
8368
8369
static PyObject *
8370
os_setsid_impl(PyObject *module)
8371
/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
8372
0
{
8373
0
    if (setsid() < 0)
8374
0
        return posix_error();
8375
0
    Py_RETURN_NONE;
8376
0
}
8377
#endif /* HAVE_SETSID */
8378
8379
8380
#ifdef HAVE_SETPGID
8381
/*[clinic input]
8382
os.setpgid
8383
8384
    pid: pid_t
8385
    pgrp: pid_t
8386
    /
8387
8388
Call the system call setpgid(pid, pgrp).
8389
[clinic start generated code]*/
8390
8391
static PyObject *
8392
os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
8393
/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
8394
0
{
8395
0
    if (setpgid(pid, pgrp) < 0)
8396
0
        return posix_error();
8397
0
    Py_RETURN_NONE;
8398
0
}
8399
#endif /* HAVE_SETPGID */
8400
8401
8402
#ifdef HAVE_TCGETPGRP
8403
/*[clinic input]
8404
os.tcgetpgrp
8405
8406
    fd: int
8407
    /
8408
8409
Return the process group associated with the terminal specified by fd.
8410
[clinic start generated code]*/
8411
8412
static PyObject *
8413
os_tcgetpgrp_impl(PyObject *module, int fd)
8414
/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
8415
0
{
8416
0
    pid_t pgid = tcgetpgrp(fd);
8417
0
    if (pgid < 0)
8418
0
        return posix_error();
8419
0
    return PyLong_FromPid(pgid);
8420
0
}
8421
#endif /* HAVE_TCGETPGRP */
8422
8423
8424
#ifdef HAVE_TCSETPGRP
8425
/*[clinic input]
8426
os.tcsetpgrp
8427
8428
    fd: int
8429
    pgid: pid_t
8430
    /
8431
8432
Set the process group associated with the terminal specified by fd.
8433
[clinic start generated code]*/
8434
8435
static PyObject *
8436
os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
8437
/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
8438
0
{
8439
0
    if (tcsetpgrp(fd, pgid) < 0)
8440
0
        return posix_error();
8441
0
    Py_RETURN_NONE;
8442
0
}
8443
#endif /* HAVE_TCSETPGRP */
8444
8445
/* Functions acting on file descriptors */
8446
8447
#ifdef O_CLOEXEC
8448
extern int _Py_open_cloexec_works;
8449
#endif
8450
8451
8452
/*[clinic input]
8453
os.open -> int
8454
    path: path_t
8455
    flags: int
8456
    mode: int = 0o777
8457
    *
8458
    dir_fd: dir_fd(requires='openat') = None
8459
8460
# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
8461
8462
Open a file for low level IO.  Returns a file descriptor (integer).
8463
8464
If dir_fd is not None, it should be a file descriptor open to a directory,
8465
  and path should be relative; path will then be relative to that directory.
8466
dir_fd may not be implemented on your platform.
8467
  If it is unavailable, using it will raise a NotImplementedError.
8468
[clinic start generated code]*/
8469
8470
static int
8471
os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
8472
/*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
8473
0
{
8474
0
    int fd;
8475
0
    int async_err = 0;
8476
8477
0
#ifdef O_CLOEXEC
8478
0
    int *atomic_flag_works = &_Py_open_cloexec_works;
8479
#elif !defined(MS_WINDOWS)
8480
    int *atomic_flag_works = NULL;
8481
#endif
8482
8483
#ifdef MS_WINDOWS
8484
    flags |= O_NOINHERIT;
8485
#elif defined(O_CLOEXEC)
8486
    flags |= O_CLOEXEC;
8487
0
#endif
8488
8489
0
    if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
8490
0
        return -1;
8491
0
    }
8492
8493
0
    _Py_BEGIN_SUPPRESS_IPH
8494
0
    do {
8495
0
        Py_BEGIN_ALLOW_THREADS
8496
#ifdef MS_WINDOWS
8497
        fd = _wopen(path->wide, flags, mode);
8498
#else
8499
0
#ifdef HAVE_OPENAT
8500
0
        if (dir_fd != DEFAULT_DIR_FD)
8501
0
            fd = openat(dir_fd, path->narrow, flags, mode);
8502
0
        else
8503
0
#endif /* HAVE_OPENAT */
8504
0
            fd = open(path->narrow, flags, mode);
8505
0
#endif /* !MS_WINDOWS */
8506
0
        Py_END_ALLOW_THREADS
8507
0
    } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8508
0
    _Py_END_SUPPRESS_IPH
8509
8510
0
    if (fd < 0) {
8511
0
        if (!async_err)
8512
0
            PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
8513
0
        return -1;
8514
0
    }
8515
8516
0
#ifndef MS_WINDOWS
8517
0
    if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
8518
0
        close(fd);
8519
0
        return -1;
8520
0
    }
8521
0
#endif
8522
8523
0
    return fd;
8524
0
}
8525
8526
8527
/*[clinic input]
8528
os.close
8529
8530
    fd: int
8531
8532
Close a file descriptor.
8533
[clinic start generated code]*/
8534
8535
static PyObject *
8536
os_close_impl(PyObject *module, int fd)
8537
/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
8538
0
{
8539
0
    int res;
8540
    /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
8541
     * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
8542
     * for more details.
8543
     */
8544
0
    Py_BEGIN_ALLOW_THREADS
8545
0
    _Py_BEGIN_SUPPRESS_IPH
8546
0
    res = close(fd);
8547
0
    _Py_END_SUPPRESS_IPH
8548
0
    Py_END_ALLOW_THREADS
8549
0
    if (res < 0)
8550
0
        return posix_error();
8551
0
    Py_RETURN_NONE;
8552
0
}
8553
8554
8555
#ifdef HAVE_FDWALK
8556
static int
8557
_fdwalk_close_func(void *lohi, int fd)
8558
{
8559
    int lo = ((int *)lohi)[0];
8560
    int hi = ((int *)lohi)[1];
8561
8562
    if (fd >= hi)
8563
        return 1;
8564
    else if (fd >= lo)
8565
        close(fd);
8566
    return 0;
8567
}
8568
#endif /* HAVE_FDWALK */
8569
8570
/*[clinic input]
8571
os.closerange
8572
8573
    fd_low: int
8574
    fd_high: int
8575
    /
8576
8577
Closes all file descriptors in [fd_low, fd_high), ignoring errors.
8578
[clinic start generated code]*/
8579
8580
static PyObject *
8581
os_closerange_impl(PyObject *module, int fd_low, int fd_high)
8582
/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
8583
0
{
8584
#ifdef HAVE_FDWALK
8585
    int lohi[2];
8586
#else
8587
0
    int i;
8588
0
#endif
8589
0
    Py_BEGIN_ALLOW_THREADS
8590
0
    _Py_BEGIN_SUPPRESS_IPH
8591
#ifdef HAVE_FDWALK
8592
    lohi[0] = Py_MAX(fd_low, 0);
8593
    lohi[1] = fd_high;
8594
    fdwalk(_fdwalk_close_func, lohi);
8595
#else
8596
0
    for (i = Py_MAX(fd_low, 0); i < fd_high; i++)
8597
0
        close(i);
8598
0
#endif
8599
0
    _Py_END_SUPPRESS_IPH
8600
0
    Py_END_ALLOW_THREADS
8601
0
    Py_RETURN_NONE;
8602
0
}
8603
8604
8605
/*[clinic input]
8606
os.dup -> int
8607
8608
    fd: int
8609
    /
8610
8611
Return a duplicate of a file descriptor.
8612
[clinic start generated code]*/
8613
8614
static int
8615
os_dup_impl(PyObject *module, int fd)
8616
/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
8617
0
{
8618
0
    return _Py_dup(fd);
8619
0
}
8620
8621
8622
/*[clinic input]
8623
os.dup2 -> int
8624
    fd: int
8625
    fd2: int
8626
    inheritable: bool=True
8627
8628
Duplicate file descriptor.
8629
[clinic start generated code]*/
8630
8631
static int
8632
os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
8633
/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
8634
0
{
8635
0
    int res = 0;
8636
0
#if defined(HAVE_DUP3) && \
8637
0
    !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
8638
    /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
8639
0
    static int dup3_works = -1;
8640
0
#endif
8641
8642
0
    if (fd < 0 || fd2 < 0) {
8643
0
        posix_error();
8644
0
        return -1;
8645
0
    }
8646
8647
    /* dup2() can fail with EINTR if the target FD is already open, because it
8648
     * then has to be closed. See os_close_impl() for why we don't handle EINTR
8649
     * upon close(), and therefore below.
8650
     */
8651
#ifdef MS_WINDOWS
8652
    Py_BEGIN_ALLOW_THREADS
8653
    _Py_BEGIN_SUPPRESS_IPH
8654
    res = dup2(fd, fd2);
8655
    _Py_END_SUPPRESS_IPH
8656
    Py_END_ALLOW_THREADS
8657
    if (res < 0) {
8658
        posix_error();
8659
        return -1;
8660
    }
8661
    res = fd2; // msvcrt dup2 returns 0 on success.
8662
8663
    /* Character files like console cannot be make non-inheritable */
8664
    if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
8665
        close(fd2);
8666
        return -1;
8667
    }
8668
8669
#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
8670
    Py_BEGIN_ALLOW_THREADS
8671
    if (!inheritable)
8672
        res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
8673
    else
8674
        res = dup2(fd, fd2);
8675
    Py_END_ALLOW_THREADS
8676
    if (res < 0) {
8677
        posix_error();
8678
        return -1;
8679
    }
8680
8681
#else
8682
8683
0
#ifdef HAVE_DUP3
8684
0
    if (!inheritable && dup3_works != 0) {
8685
0
        Py_BEGIN_ALLOW_THREADS
8686
0
        res = dup3(fd, fd2, O_CLOEXEC);
8687
0
        Py_END_ALLOW_THREADS
8688
0
        if (res < 0) {
8689
0
            if (dup3_works == -1)
8690
0
                dup3_works = (errno != ENOSYS);
8691
0
            if (dup3_works) {
8692
0
                posix_error();
8693
0
                return -1;
8694
0
            }
8695
0
        }
8696
0
    }
8697
8698
0
    if (inheritable || dup3_works == 0)
8699
0
    {
8700
0
#endif
8701
0
        Py_BEGIN_ALLOW_THREADS
8702
0
        res = dup2(fd, fd2);
8703
0
        Py_END_ALLOW_THREADS
8704
0
        if (res < 0) {
8705
0
            posix_error();
8706
0
            return -1;
8707
0
        }
8708
8709
0
        if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
8710
0
            close(fd2);
8711
0
            return -1;
8712
0
        }
8713
0
#ifdef HAVE_DUP3
8714
0
    }
8715
0
#endif
8716
8717
0
#endif
8718
8719
0
    return res;
8720
0
}
8721
8722
8723
#ifdef HAVE_LOCKF
8724
/*[clinic input]
8725
os.lockf
8726
8727
    fd: int
8728
        An open file descriptor.
8729
    command: int
8730
        One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
8731
    length: Py_off_t
8732
        The number of bytes to lock, starting at the current position.
8733
    /
8734
8735
Apply, test or remove a POSIX lock on an open file descriptor.
8736
8737
[clinic start generated code]*/
8738
8739
static PyObject *
8740
os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
8741
/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
8742
0
{
8743
0
    int res;
8744
8745
0
    if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
8746
0
        return NULL;
8747
0
    }
8748
8749
0
    Py_BEGIN_ALLOW_THREADS
8750
0
    res = lockf(fd, command, length);
8751
0
    Py_END_ALLOW_THREADS
8752
8753
0
    if (res < 0)
8754
0
        return posix_error();
8755
8756
0
    Py_RETURN_NONE;
8757
0
}
8758
#endif /* HAVE_LOCKF */
8759
8760
8761
/*[clinic input]
8762
os.lseek -> Py_off_t
8763
8764
    fd: int
8765
    position: Py_off_t
8766
    how: int
8767
    /
8768
8769
Set the position of a file descriptor.  Return the new position.
8770
8771
Return the new cursor position in number of bytes
8772
relative to the beginning of the file.
8773
[clinic start generated code]*/
8774
8775
static Py_off_t
8776
os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
8777
/*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
8778
0
{
8779
0
    Py_off_t result;
8780
8781
0
#ifdef SEEK_SET
8782
    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
8783
0
    switch (how) {
8784
0
        case 0: how = SEEK_SET; break;
8785
0
        case 1: how = SEEK_CUR; break;
8786
0
        case 2: how = SEEK_END; break;
8787
0
    }
8788
0
#endif /* SEEK_END */
8789
8790
0
    Py_BEGIN_ALLOW_THREADS
8791
0
    _Py_BEGIN_SUPPRESS_IPH
8792
#ifdef MS_WINDOWS
8793
    result = _lseeki64(fd, position, how);
8794
#else
8795
0
    result = lseek(fd, position, how);
8796
0
#endif
8797
0
    _Py_END_SUPPRESS_IPH
8798
0
    Py_END_ALLOW_THREADS
8799
0
    if (result < 0)
8800
0
        posix_error();
8801
8802
0
    return result;
8803
0
}
8804
8805
8806
/*[clinic input]
8807
os.read
8808
    fd: int
8809
    length: Py_ssize_t
8810
    /
8811
8812
Read from a file descriptor.  Returns a bytes object.
8813
[clinic start generated code]*/
8814
8815
static PyObject *
8816
os_read_impl(PyObject *module, int fd, Py_ssize_t length)
8817
/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
8818
0
{
8819
0
    Py_ssize_t n;
8820
0
    PyObject *buffer;
8821
8822
0
    if (length < 0) {
8823
0
        errno = EINVAL;
8824
0
        return posix_error();
8825
0
    }
8826
8827
0
    length = Py_MIN(length, _PY_READ_MAX);
8828
8829
0
    buffer = PyBytes_FromStringAndSize((char *)NULL, length);
8830
0
    if (buffer == NULL)
8831
0
        return NULL;
8832
8833
0
    n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
8834
0
    if (n == -1) {
8835
0
        Py_DECREF(buffer);
8836
0
        return NULL;
8837
0
    }
8838
8839
0
    if (n != length)
8840
0
        _PyBytes_Resize(&buffer, n);
8841
8842
0
    return buffer;
8843
0
}
8844
8845
#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
8846
                                || defined(__APPLE__))) \
8847
    || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
8848
    || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
8849
static int
8850
iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
8851
0
{
8852
0
    Py_ssize_t i, j;
8853
8854
0
    *iov = PyMem_New(struct iovec, cnt);
8855
0
    if (*iov == NULL) {
8856
0
        PyErr_NoMemory();
8857
0
        return -1;
8858
0
    }
8859
8860
0
    *buf = PyMem_New(Py_buffer, cnt);
8861
0
    if (*buf == NULL) {
8862
0
        PyMem_Del(*iov);
8863
0
        PyErr_NoMemory();
8864
0
        return -1;
8865
0
    }
8866
8867
0
    for (i = 0; i < cnt; i++) {
8868
0
        PyObject *item = PySequence_GetItem(seq, i);
8869
0
        if (item == NULL)
8870
0
            goto fail;
8871
0
        if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
8872
0
            Py_DECREF(item);
8873
0
            goto fail;
8874
0
        }
8875
0
        Py_DECREF(item);
8876
0
        (*iov)[i].iov_base = (*buf)[i].buf;
8877
0
        (*iov)[i].iov_len = (*buf)[i].len;
8878
0
    }
8879
0
    return 0;
8880
8881
0
fail:
8882
0
    PyMem_Del(*iov);
8883
0
    for (j = 0; j < i; j++) {
8884
0
        PyBuffer_Release(&(*buf)[j]);
8885
0
    }
8886
0
    PyMem_Del(*buf);
8887
0
    return -1;
8888
0
}
8889
8890
static void
8891
iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
8892
0
{
8893
0
    int i;
8894
0
    PyMem_Del(iov);
8895
0
    for (i = 0; i < cnt; i++) {
8896
0
        PyBuffer_Release(&buf[i]);
8897
0
    }
8898
0
    PyMem_Del(buf);
8899
0
}
8900
#endif
8901
8902
8903
#ifdef HAVE_READV
8904
/*[clinic input]
8905
os.readv -> Py_ssize_t
8906
8907
    fd: int
8908
    buffers: object
8909
    /
8910
8911
Read from a file descriptor fd into an iterable of buffers.
8912
8913
The buffers should be mutable buffers accepting bytes.
8914
readv will transfer data into each buffer until it is full
8915
and then move on to the next buffer in the sequence to hold
8916
the rest of the data.
8917
8918
readv returns the total number of bytes read,
8919
which may be less than the total capacity of all the buffers.
8920
[clinic start generated code]*/
8921
8922
static Py_ssize_t
8923
os_readv_impl(PyObject *module, int fd, PyObject *buffers)
8924
/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
8925
0
{
8926
0
    Py_ssize_t cnt, n;
8927
0
    int async_err = 0;
8928
0
    struct iovec *iov;
8929
0
    Py_buffer *buf;
8930
8931
0
    if (!PySequence_Check(buffers)) {
8932
0
        PyErr_SetString(PyExc_TypeError,
8933
0
            "readv() arg 2 must be a sequence");
8934
0
        return -1;
8935
0
    }
8936
8937
0
    cnt = PySequence_Size(buffers);
8938
0
    if (cnt < 0)
8939
0
        return -1;
8940
8941
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
8942
0
        return -1;
8943
8944
0
    do {
8945
0
        Py_BEGIN_ALLOW_THREADS
8946
0
        n = readv(fd, iov, cnt);
8947
0
        Py_END_ALLOW_THREADS
8948
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8949
8950
0
    iov_cleanup(iov, buf, cnt);
8951
0
    if (n < 0) {
8952
0
        if (!async_err)
8953
0
            posix_error();
8954
0
        return -1;
8955
0
    }
8956
8957
0
    return n;
8958
0
}
8959
#endif /* HAVE_READV */
8960
8961
8962
#ifdef HAVE_PREAD
8963
/*[clinic input]
8964
# TODO length should be size_t!  but Python doesn't support parsing size_t yet.
8965
os.pread
8966
8967
    fd: int
8968
    length: int
8969
    offset: Py_off_t
8970
    /
8971
8972
Read a number of bytes from a file descriptor starting at a particular offset.
8973
8974
Read length bytes from file descriptor fd, starting at offset bytes from
8975
the beginning of the file.  The file offset remains unchanged.
8976
[clinic start generated code]*/
8977
8978
static PyObject *
8979
os_pread_impl(PyObject *module, int fd, int length, Py_off_t offset)
8980
/*[clinic end generated code: output=435b29ee32b54a78 input=084948dcbaa35d4c]*/
8981
0
{
8982
0
    Py_ssize_t n;
8983
0
    int async_err = 0;
8984
0
    PyObject *buffer;
8985
8986
0
    if (length < 0) {
8987
0
        errno = EINVAL;
8988
0
        return posix_error();
8989
0
    }
8990
0
    buffer = PyBytes_FromStringAndSize((char *)NULL, length);
8991
0
    if (buffer == NULL)
8992
0
        return NULL;
8993
8994
0
    do {
8995
0
        Py_BEGIN_ALLOW_THREADS
8996
0
        _Py_BEGIN_SUPPRESS_IPH
8997
0
        n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
8998
0
        _Py_END_SUPPRESS_IPH
8999
0
        Py_END_ALLOW_THREADS
9000
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9001
9002
0
    if (n < 0) {
9003
0
        Py_DECREF(buffer);
9004
0
        return (!async_err) ? posix_error() : NULL;
9005
0
    }
9006
0
    if (n != length)
9007
0
        _PyBytes_Resize(&buffer, n);
9008
0
    return buffer;
9009
0
}
9010
#endif /* HAVE_PREAD */
9011
9012
#if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
9013
/*[clinic input]
9014
os.preadv -> Py_ssize_t
9015
9016
    fd: int
9017
    buffers: object
9018
    offset: Py_off_t
9019
    flags: int = 0
9020
    /
9021
9022
Reads from a file descriptor into a number of mutable bytes-like objects.
9023
9024
Combines the functionality of readv() and pread(). As readv(), it will
9025
transfer data into each buffer until it is full and then move on to the next
9026
buffer in the sequence to hold the rest of the data. Its fourth argument,
9027
specifies the file offset at which the input operation is to be performed. It
9028
will return the total number of bytes read (which can be less than the total
9029
capacity of all the objects).
9030
9031
The flags argument contains a bitwise OR of zero or more of the following flags:
9032
9033
- RWF_HIPRI
9034
- RWF_NOWAIT
9035
9036
Using non-zero flags requires Linux 4.6 or newer.
9037
[clinic start generated code]*/
9038
9039
static Py_ssize_t
9040
os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9041
               int flags)
9042
/*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
9043
0
{
9044
0
    Py_ssize_t cnt, n;
9045
0
    int async_err = 0;
9046
0
    struct iovec *iov;
9047
0
    Py_buffer *buf;
9048
9049
0
    if (!PySequence_Check(buffers)) {
9050
0
        PyErr_SetString(PyExc_TypeError,
9051
0
            "preadv2() arg 2 must be a sequence");
9052
0
        return -1;
9053
0
    }
9054
9055
0
    cnt = PySequence_Size(buffers);
9056
0
    if (cnt < 0) {
9057
0
        return -1;
9058
0
    }
9059
9060
#ifndef HAVE_PREADV2
9061
    if(flags != 0) {
9062
        argument_unavailable_error("preadv2", "flags");
9063
        return -1;
9064
    }
9065
#endif
9066
9067
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
9068
0
        return -1;
9069
0
    }
9070
0
#ifdef HAVE_PREADV2
9071
0
    do {
9072
0
        Py_BEGIN_ALLOW_THREADS
9073
0
        _Py_BEGIN_SUPPRESS_IPH
9074
0
        n = preadv2(fd, iov, cnt, offset, flags);
9075
0
        _Py_END_SUPPRESS_IPH
9076
0
        Py_END_ALLOW_THREADS
9077
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9078
#else
9079
    do {
9080
        Py_BEGIN_ALLOW_THREADS
9081
        _Py_BEGIN_SUPPRESS_IPH
9082
        n = preadv(fd, iov, cnt, offset);
9083
        _Py_END_SUPPRESS_IPH
9084
        Py_END_ALLOW_THREADS
9085
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9086
#endif
9087
9088
0
    iov_cleanup(iov, buf, cnt);
9089
0
    if (n < 0) {
9090
0
        if (!async_err) {
9091
0
            posix_error();
9092
0
        }
9093
0
        return -1;
9094
0
    }
9095
9096
0
    return n;
9097
0
}
9098
#endif /* HAVE_PREADV */
9099
9100
9101
/*[clinic input]
9102
os.write -> Py_ssize_t
9103
9104
    fd: int
9105
    data: Py_buffer
9106
    /
9107
9108
Write a bytes object to a file descriptor.
9109
[clinic start generated code]*/
9110
9111
static Py_ssize_t
9112
os_write_impl(PyObject *module, int fd, Py_buffer *data)
9113
/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
9114
0
{
9115
0
    return _Py_write(fd, data->buf, data->len);
9116
0
}
9117
9118
#ifdef HAVE_SENDFILE
9119
PyDoc_STRVAR(posix_sendfile__doc__,
9120
"sendfile(out, in, offset, count) -> byteswritten\n\
9121
sendfile(out, in, offset, count[, headers][, trailers], flags=0)\n\
9122
            -> byteswritten\n\
9123
Copy count bytes from file descriptor in to file descriptor out.");
9124
9125
/* AC 3.5: don't bother converting, has optional group*/
9126
static PyObject *
9127
posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
9128
0
{
9129
0
    int in, out;
9130
0
    Py_ssize_t ret;
9131
0
    int async_err = 0;
9132
0
    off_t offset;
9133
9134
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
9135
#ifndef __APPLE__
9136
    Py_ssize_t len;
9137
#endif
9138
    PyObject *headers = NULL, *trailers = NULL;
9139
    Py_buffer *hbuf, *tbuf;
9140
    off_t sbytes;
9141
    struct sf_hdtr sf;
9142
    int flags = 0;
9143
    /* Beware that "in" clashes with Python's own "in" operator keyword */
9144
    static char *keywords[] = {"out", "in",
9145
                                "offset", "count",
9146
                                "headers", "trailers", "flags", NULL};
9147
9148
    sf.headers = NULL;
9149
    sf.trailers = NULL;
9150
9151
#ifdef __APPLE__
9152
    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile",
9153
        keywords, &out, &in, Py_off_t_converter, &offset, Py_off_t_converter, &sbytes,
9154
#else
9155
    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&n|OOi:sendfile",
9156
        keywords, &out, &in, Py_off_t_converter, &offset, &len,
9157
#endif
9158
                &headers, &trailers, &flags))
9159
            return NULL;
9160
    if (headers != NULL) {
9161
        if (!PySequence_Check(headers)) {
9162
            PyErr_SetString(PyExc_TypeError,
9163
                "sendfile() headers must be a sequence");
9164
            return NULL;
9165
        } else {
9166
            Py_ssize_t i = PySequence_Size(headers);
9167
            if (i < 0)
9168
                return NULL;
9169
            if (i > INT_MAX) {
9170
                PyErr_SetString(PyExc_OverflowError,
9171
                    "sendfile() header is too large");
9172
                return NULL;
9173
            }
9174
            if (i > 0) {
9175
                sf.hdr_cnt = (int)i;
9176
                if (iov_setup(&(sf.headers), &hbuf,
9177
                              headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
9178
                    return NULL;
9179
#ifdef __APPLE__
9180
                for (i = 0; i < sf.hdr_cnt; i++) {
9181
                    Py_ssize_t blen = sf.headers[i].iov_len;
9182
# define OFF_T_MAX 0x7fffffffffffffff
9183
                    if (sbytes >= OFF_T_MAX - blen) {
9184
                        PyErr_SetString(PyExc_OverflowError,
9185
                            "sendfile() header is too large");
9186
                        return NULL;
9187
                    }
9188
                    sbytes += blen;
9189
                }
9190
#endif
9191
            }
9192
        }
9193
    }
9194
    if (trailers != NULL) {
9195
        if (!PySequence_Check(trailers)) {
9196
            PyErr_SetString(PyExc_TypeError,
9197
                "sendfile() trailers must be a sequence");
9198
            return NULL;
9199
        } else {
9200
            Py_ssize_t i = PySequence_Size(trailers);
9201
            if (i < 0)
9202
                return NULL;
9203
            if (i > INT_MAX) {
9204
                PyErr_SetString(PyExc_OverflowError,
9205
                    "sendfile() trailer is too large");
9206
                return NULL;
9207
            }
9208
            if (i > 0) {
9209
                sf.trl_cnt = (int)i;
9210
                if (iov_setup(&(sf.trailers), &tbuf,
9211
                              trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
9212
                    return NULL;
9213
            }
9214
        }
9215
    }
9216
9217
    _Py_BEGIN_SUPPRESS_IPH
9218
    do {
9219
        Py_BEGIN_ALLOW_THREADS
9220
#ifdef __APPLE__
9221
        ret = sendfile(in, out, offset, &sbytes, &sf, flags);
9222
#else
9223
        ret = sendfile(in, out, offset, len, &sf, &sbytes, flags);
9224
#endif
9225
        Py_END_ALLOW_THREADS
9226
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9227
    _Py_END_SUPPRESS_IPH
9228
9229
    if (sf.headers != NULL)
9230
        iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
9231
    if (sf.trailers != NULL)
9232
        iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
9233
9234
    if (ret < 0) {
9235
        if ((errno == EAGAIN) || (errno == EBUSY)) {
9236
            if (sbytes != 0) {
9237
                // some data has been sent
9238
                goto done;
9239
            }
9240
            else {
9241
                // no data has been sent; upper application is supposed
9242
                // to retry on EAGAIN or EBUSY
9243
                return posix_error();
9244
            }
9245
        }
9246
        return (!async_err) ? posix_error() : NULL;
9247
    }
9248
    goto done;
9249
9250
done:
9251
    #if !defined(HAVE_LARGEFILE_SUPPORT)
9252
        return Py_BuildValue("l", sbytes);
9253
    #else
9254
        return Py_BuildValue("L", sbytes);
9255
    #endif
9256
9257
#else
9258
0
    Py_ssize_t count;
9259
0
    PyObject *offobj;
9260
0
    static char *keywords[] = {"out", "in",
9261
0
                                "offset", "count", NULL};
9262
0
    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile",
9263
0
            keywords, &out, &in, &offobj, &count))
9264
0
        return NULL;
9265
0
#ifdef __linux__
9266
0
    if (offobj == Py_None) {
9267
0
        do {
9268
0
            Py_BEGIN_ALLOW_THREADS
9269
0
            ret = sendfile(out, in, NULL, count);
9270
0
            Py_END_ALLOW_THREADS
9271
0
        } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9272
0
        if (ret < 0)
9273
0
            return (!async_err) ? posix_error() : NULL;
9274
0
        return Py_BuildValue("n", ret);
9275
0
    }
9276
0
#endif
9277
0
    if (!Py_off_t_converter(offobj, &offset))
9278
0
        return NULL;
9279
9280
0
    do {
9281
0
        Py_BEGIN_ALLOW_THREADS
9282
0
        ret = sendfile(out, in, &offset, count);
9283
0
        Py_END_ALLOW_THREADS
9284
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9285
0
    if (ret < 0)
9286
0
        return (!async_err) ? posix_error() : NULL;
9287
0
    return Py_BuildValue("n", ret);
9288
0
#endif
9289
0
}
9290
#endif /* HAVE_SENDFILE */
9291
9292
9293
#if defined(__APPLE__)
9294
/*[clinic input]
9295
os._fcopyfile
9296
9297
    infd: int
9298
    outfd: int
9299
    flags: int
9300
    /
9301
9302
Efficiently copy content or metadata of 2 regular file descriptors (macOS).
9303
[clinic start generated code]*/
9304
9305
static PyObject *
9306
os__fcopyfile_impl(PyObject *module, int infd, int outfd, int flags)
9307
/*[clinic end generated code: output=8e8885c721ec38e3 input=69e0770e600cb44f]*/
9308
{
9309
    int ret;
9310
9311
    Py_BEGIN_ALLOW_THREADS
9312
    ret = fcopyfile(infd, outfd, NULL, flags);
9313
    Py_END_ALLOW_THREADS
9314
    if (ret < 0)
9315
        return posix_error();
9316
    Py_RETURN_NONE;
9317
}
9318
#endif
9319
9320
9321
/*[clinic input]
9322
os.fstat
9323
9324
    fd : int
9325
9326
Perform a stat system call on the given file descriptor.
9327
9328
Like stat(), but for an open file descriptor.
9329
Equivalent to os.stat(fd).
9330
[clinic start generated code]*/
9331
9332
static PyObject *
9333
os_fstat_impl(PyObject *module, int fd)
9334
/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
9335
0
{
9336
0
    STRUCT_STAT st;
9337
0
    int res;
9338
0
    int async_err = 0;
9339
9340
0
    do {
9341
0
        Py_BEGIN_ALLOW_THREADS
9342
0
        res = FSTAT(fd, &st);
9343
0
        Py_END_ALLOW_THREADS
9344
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9345
0
    if (res != 0) {
9346
#ifdef MS_WINDOWS
9347
        return PyErr_SetFromWindowsErr(0);
9348
#else
9349
0
        return (!async_err) ? posix_error() : NULL;
9350
0
#endif
9351
0
    }
9352
9353
0
    return _pystat_fromstructstat(&st);
9354
0
}
9355
9356
9357
/*[clinic input]
9358
os.isatty -> bool
9359
    fd: int
9360
    /
9361
9362
Return True if the fd is connected to a terminal.
9363
9364
Return True if the file descriptor is an open file descriptor
9365
connected to the slave end of a terminal.
9366
[clinic start generated code]*/
9367
9368
static int
9369
os_isatty_impl(PyObject *module, int fd)
9370
/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
9371
0
{
9372
0
    int return_value;
9373
0
    _Py_BEGIN_SUPPRESS_IPH
9374
0
    return_value = isatty(fd);
9375
0
    _Py_END_SUPPRESS_IPH
9376
0
    return return_value;
9377
0
}
9378
9379
9380
#ifdef HAVE_PIPE
9381
/*[clinic input]
9382
os.pipe
9383
9384
Create a pipe.
9385
9386
Returns a tuple of two file descriptors:
9387
  (read_fd, write_fd)
9388
[clinic start generated code]*/
9389
9390
static PyObject *
9391
os_pipe_impl(PyObject *module)
9392
/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
9393
0
{
9394
0
    int fds[2];
9395
#ifdef MS_WINDOWS
9396
    HANDLE read, write;
9397
    SECURITY_ATTRIBUTES attr;
9398
    BOOL ok;
9399
#else
9400
0
    int res;
9401
0
#endif
9402
9403
#ifdef MS_WINDOWS
9404
    attr.nLength = sizeof(attr);
9405
    attr.lpSecurityDescriptor = NULL;
9406
    attr.bInheritHandle = FALSE;
9407
9408
    Py_BEGIN_ALLOW_THREADS
9409
    _Py_BEGIN_SUPPRESS_IPH
9410
    ok = CreatePipe(&read, &write, &attr, 0);
9411
    if (ok) {
9412
        fds[0] = _open_osfhandle((intptr_t)read, _O_RDONLY);
9413
        fds[1] = _open_osfhandle((intptr_t)write, _O_WRONLY);
9414
        if (fds[0] == -1 || fds[1] == -1) {
9415
            CloseHandle(read);
9416
            CloseHandle(write);
9417
            ok = 0;
9418
        }
9419
    }
9420
    _Py_END_SUPPRESS_IPH
9421
    Py_END_ALLOW_THREADS
9422
9423
    if (!ok)
9424
        return PyErr_SetFromWindowsErr(0);
9425
#else
9426
9427
0
#ifdef HAVE_PIPE2
9428
0
    Py_BEGIN_ALLOW_THREADS
9429
0
    res = pipe2(fds, O_CLOEXEC);
9430
0
    Py_END_ALLOW_THREADS
9431
9432
0
    if (res != 0 && errno == ENOSYS)
9433
0
    {
9434
0
#endif
9435
0
        Py_BEGIN_ALLOW_THREADS
9436
0
        res = pipe(fds);
9437
0
        Py_END_ALLOW_THREADS
9438
9439
0
        if (res == 0) {
9440
0
            if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
9441
0
                close(fds[0]);
9442
0
                close(fds[1]);
9443
0
                return NULL;
9444
0
            }
9445
0
            if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
9446
0
                close(fds[0]);
9447
0
                close(fds[1]);
9448
0
                return NULL;
9449
0
            }
9450
0
        }
9451
0
#ifdef HAVE_PIPE2
9452
0
    }
9453
0
#endif
9454
9455
0
    if (res != 0)
9456
0
        return PyErr_SetFromErrno(PyExc_OSError);
9457
0
#endif /* !MS_WINDOWS */
9458
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
9459
0
}
9460
#endif  /* HAVE_PIPE */
9461
9462
9463
#ifdef HAVE_PIPE2
9464
/*[clinic input]
9465
os.pipe2
9466
9467
    flags: int
9468
    /
9469
9470
Create a pipe with flags set atomically.
9471
9472
Returns a tuple of two file descriptors:
9473
  (read_fd, write_fd)
9474
9475
flags can be constructed by ORing together one or more of these values:
9476
O_NONBLOCK, O_CLOEXEC.
9477
[clinic start generated code]*/
9478
9479
static PyObject *
9480
os_pipe2_impl(PyObject *module, int flags)
9481
/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
9482
0
{
9483
0
    int fds[2];
9484
0
    int res;
9485
9486
0
    res = pipe2(fds, flags);
9487
0
    if (res != 0)
9488
0
        return posix_error();
9489
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
9490
0
}
9491
#endif /* HAVE_PIPE2 */
9492
9493
9494
#ifdef HAVE_WRITEV
9495
/*[clinic input]
9496
os.writev -> Py_ssize_t
9497
    fd: int
9498
    buffers: object
9499
    /
9500
9501
Iterate over buffers, and write the contents of each to a file descriptor.
9502
9503
Returns the total number of bytes written.
9504
buffers must be a sequence of bytes-like objects.
9505
[clinic start generated code]*/
9506
9507
static Py_ssize_t
9508
os_writev_impl(PyObject *module, int fd, PyObject *buffers)
9509
/*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
9510
0
{
9511
0
    Py_ssize_t cnt;
9512
0
    Py_ssize_t result;
9513
0
    int async_err = 0;
9514
0
    struct iovec *iov;
9515
0
    Py_buffer *buf;
9516
9517
0
    if (!PySequence_Check(buffers)) {
9518
0
        PyErr_SetString(PyExc_TypeError,
9519
0
            "writev() arg 2 must be a sequence");
9520
0
        return -1;
9521
0
    }
9522
0
    cnt = PySequence_Size(buffers);
9523
0
    if (cnt < 0)
9524
0
        return -1;
9525
9526
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
9527
0
        return -1;
9528
0
    }
9529
9530
0
    do {
9531
0
        Py_BEGIN_ALLOW_THREADS
9532
0
        result = writev(fd, iov, cnt);
9533
0
        Py_END_ALLOW_THREADS
9534
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9535
9536
0
    iov_cleanup(iov, buf, cnt);
9537
0
    if (result < 0 && !async_err)
9538
0
        posix_error();
9539
9540
0
    return result;
9541
0
}
9542
#endif /* HAVE_WRITEV */
9543
9544
9545
#ifdef HAVE_PWRITE
9546
/*[clinic input]
9547
os.pwrite -> Py_ssize_t
9548
9549
    fd: int
9550
    buffer: Py_buffer
9551
    offset: Py_off_t
9552
    /
9553
9554
Write bytes to a file descriptor starting at a particular offset.
9555
9556
Write buffer to fd, starting at offset bytes from the beginning of
9557
the file.  Returns the number of bytes writte.  Does not change the
9558
current file offset.
9559
[clinic start generated code]*/
9560
9561
static Py_ssize_t
9562
os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
9563
/*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
9564
0
{
9565
0
    Py_ssize_t size;
9566
0
    int async_err = 0;
9567
9568
0
    do {
9569
0
        Py_BEGIN_ALLOW_THREADS
9570
0
        _Py_BEGIN_SUPPRESS_IPH
9571
0
        size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
9572
0
        _Py_END_SUPPRESS_IPH
9573
0
        Py_END_ALLOW_THREADS
9574
0
    } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9575
9576
0
    if (size < 0 && !async_err)
9577
0
        posix_error();
9578
0
    return size;
9579
0
}
9580
#endif /* HAVE_PWRITE */
9581
9582
#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
9583
/*[clinic input]
9584
os.pwritev -> Py_ssize_t
9585
9586
    fd: int
9587
    buffers: object
9588
    offset: Py_off_t
9589
    flags: int = 0
9590
    /
9591
9592
Writes the contents of bytes-like objects to a file descriptor at a given offset.
9593
9594
Combines the functionality of writev() and pwrite(). All buffers must be a sequence
9595
of bytes-like objects. Buffers are processed in array order. Entire contents of first
9596
buffer is written before proceeding to second, and so on. The operating system may
9597
set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
9598
This function writes the contents of each object to the file descriptor and returns
9599
the total number of bytes written.
9600
9601
The flags argument contains a bitwise OR of zero or more of the following flags:
9602
9603
- RWF_DSYNC
9604
- RWF_SYNC
9605
9606
Using non-zero flags requires Linux 4.7 or newer.
9607
[clinic start generated code]*/
9608
9609
static Py_ssize_t
9610
os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9611
                int flags)
9612
/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=803dc5ddbf0cfd3b]*/
9613
0
{
9614
0
    Py_ssize_t cnt;
9615
0
    Py_ssize_t result;
9616
0
    int async_err = 0;
9617
0
    struct iovec *iov;
9618
0
    Py_buffer *buf;
9619
9620
0
    if (!PySequence_Check(buffers)) {
9621
0
        PyErr_SetString(PyExc_TypeError,
9622
0
            "pwritev() arg 2 must be a sequence");
9623
0
        return -1;
9624
0
    }
9625
9626
0
    cnt = PySequence_Size(buffers);
9627
0
    if (cnt < 0) {
9628
0
        return -1;
9629
0
    }
9630
9631
#ifndef HAVE_PWRITEV2
9632
    if(flags != 0) {
9633
        argument_unavailable_error("pwritev2", "flags");
9634
        return -1;
9635
    }
9636
#endif
9637
9638
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
9639
0
        return -1;
9640
0
    }
9641
0
#ifdef HAVE_PWRITEV2
9642
0
    do {
9643
0
        Py_BEGIN_ALLOW_THREADS
9644
0
        _Py_BEGIN_SUPPRESS_IPH
9645
0
        result = pwritev2(fd, iov, cnt, offset, flags);
9646
0
        _Py_END_SUPPRESS_IPH
9647
0
        Py_END_ALLOW_THREADS
9648
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9649
#else
9650
    do {
9651
        Py_BEGIN_ALLOW_THREADS
9652
        _Py_BEGIN_SUPPRESS_IPH
9653
        result = pwritev(fd, iov, cnt, offset);
9654
        _Py_END_SUPPRESS_IPH
9655
        Py_END_ALLOW_THREADS
9656
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9657
#endif
9658
9659
0
    iov_cleanup(iov, buf, cnt);
9660
0
    if (result < 0) {
9661
0
        if (!async_err) {
9662
0
            posix_error();
9663
0
        }
9664
0
        return -1;
9665
0
    }
9666
9667
0
    return result;
9668
0
}
9669
#endif /* HAVE_PWRITEV */
9670
9671
#ifdef HAVE_COPY_FILE_RANGE
9672
/*[clinic input]
9673
9674
os.copy_file_range
9675
    src: int
9676
        Source file descriptor.
9677
    dst: int
9678
        Destination file descriptor.
9679
    count: Py_ssize_t
9680
        Number of bytes to copy.
9681
    offset_src: object = None
9682
        Starting offset in src.
9683
    offset_dst: object = None
9684
        Starting offset in dst.
9685
9686
Copy count bytes from one file descriptor to another.
9687
9688
If offset_src is None, then src is read from the current position;
9689
respectively for offset_dst.
9690
[clinic start generated code]*/
9691
9692
static PyObject *
9693
os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
9694
                        PyObject *offset_src, PyObject *offset_dst)
9695
/*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
9696
0
{
9697
0
    off_t offset_src_val, offset_dst_val;
9698
0
    off_t *p_offset_src = NULL;
9699
0
    off_t *p_offset_dst = NULL;
9700
0
    Py_ssize_t ret;
9701
0
    int async_err = 0;
9702
    /* The flags argument is provided to allow
9703
     * for future extensions and currently must be to 0. */
9704
0
    int flags = 0;
9705
9706
9707
0
    if (count < 0) {
9708
0
        PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
9709
0
        return NULL;
9710
0
    }
9711
9712
0
    if (offset_src != Py_None) {
9713
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
9714
0
            return NULL;
9715
0
        }
9716
0
        p_offset_src = &offset_src_val;
9717
0
    }
9718
9719
0
    if (offset_dst != Py_None) {
9720
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
9721
0
            return NULL;
9722
0
        }
9723
0
        p_offset_dst = &offset_dst_val;
9724
0
    }
9725
9726
0
    do {
9727
0
        Py_BEGIN_ALLOW_THREADS
9728
0
        ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
9729
0
        Py_END_ALLOW_THREADS
9730
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9731
9732
0
    if (ret < 0) {
9733
0
        return (!async_err) ? posix_error() : NULL;
9734
0
    }
9735
9736
0
    return PyLong_FromSsize_t(ret);
9737
0
}
9738
#endif /* HAVE_COPY_FILE_RANGE*/
9739
9740
#ifdef HAVE_MKFIFO
9741
/*[clinic input]
9742
os.mkfifo
9743
9744
    path: path_t
9745
    mode: int=0o666
9746
    *
9747
    dir_fd: dir_fd(requires='mkfifoat')=None
9748
9749
Create a "fifo" (a POSIX named pipe).
9750
9751
If dir_fd is not None, it should be a file descriptor open to a directory,
9752
  and path should be relative; path will then be relative to that directory.
9753
dir_fd may not be implemented on your platform.
9754
  If it is unavailable, using it will raise a NotImplementedError.
9755
[clinic start generated code]*/
9756
9757
static PyObject *
9758
os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
9759
/*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
9760
0
{
9761
0
    int result;
9762
0
    int async_err = 0;
9763
9764
0
    do {
9765
0
        Py_BEGIN_ALLOW_THREADS
9766
0
#ifdef HAVE_MKFIFOAT
9767
0
        if (dir_fd != DEFAULT_DIR_FD)
9768
0
            result = mkfifoat(dir_fd, path->narrow, mode);
9769
0
        else
9770
0
#endif
9771
0
            result = mkfifo(path->narrow, mode);
9772
0
        Py_END_ALLOW_THREADS
9773
0
    } while (result != 0 && errno == EINTR &&
9774
0
             !(async_err = PyErr_CheckSignals()));
9775
0
    if (result != 0)
9776
0
        return (!async_err) ? posix_error() : NULL;
9777
9778
0
    Py_RETURN_NONE;
9779
0
}
9780
#endif /* HAVE_MKFIFO */
9781
9782
9783
#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
9784
/*[clinic input]
9785
os.mknod
9786
9787
    path: path_t
9788
    mode: int=0o600
9789
    device: dev_t=0
9790
    *
9791
    dir_fd: dir_fd(requires='mknodat')=None
9792
9793
Create a node in the file system.
9794
9795
Create a node in the file system (file, device special file or named pipe)
9796
at path.  mode specifies both the permissions to use and the
9797
type of node to be created, being combined (bitwise OR) with one of
9798
S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
9799
device defines the newly created device special file (probably using
9800
os.makedev()).  Otherwise device is ignored.
9801
9802
If dir_fd is not None, it should be a file descriptor open to a directory,
9803
  and path should be relative; path will then be relative to that directory.
9804
dir_fd may not be implemented on your platform.
9805
  If it is unavailable, using it will raise a NotImplementedError.
9806
[clinic start generated code]*/
9807
9808
static PyObject *
9809
os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
9810
              int dir_fd)
9811
/*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
9812
0
{
9813
0
    int result;
9814
0
    int async_err = 0;
9815
9816
0
    do {
9817
0
        Py_BEGIN_ALLOW_THREADS
9818
0
#ifdef HAVE_MKNODAT
9819
0
        if (dir_fd != DEFAULT_DIR_FD)
9820
0
            result = mknodat(dir_fd, path->narrow, mode, device);
9821
0
        else
9822
0
#endif
9823
0
            result = mknod(path->narrow, mode, device);
9824
0
        Py_END_ALLOW_THREADS
9825
0
    } while (result != 0 && errno == EINTR &&
9826
0
             !(async_err = PyErr_CheckSignals()));
9827
0
    if (result != 0)
9828
0
        return (!async_err) ? posix_error() : NULL;
9829
9830
0
    Py_RETURN_NONE;
9831
0
}
9832
#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
9833
9834
9835
#ifdef HAVE_DEVICE_MACROS
9836
/*[clinic input]
9837
os.major -> unsigned_int
9838
9839
    device: dev_t
9840
    /
9841
9842
Extracts a device major number from a raw device number.
9843
[clinic start generated code]*/
9844
9845
static unsigned int
9846
os_major_impl(PyObject *module, dev_t device)
9847
/*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
9848
0
{
9849
0
    return major(device);
9850
0
}
9851
9852
9853
/*[clinic input]
9854
os.minor -> unsigned_int
9855
9856
    device: dev_t
9857
    /
9858
9859
Extracts a device minor number from a raw device number.
9860
[clinic start generated code]*/
9861
9862
static unsigned int
9863
os_minor_impl(PyObject *module, dev_t device)
9864
/*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
9865
0
{
9866
0
    return minor(device);
9867
0
}
9868
9869
9870
/*[clinic input]
9871
os.makedev -> dev_t
9872
9873
    major: int
9874
    minor: int
9875
    /
9876
9877
Composes a raw device number from the major and minor device numbers.
9878
[clinic start generated code]*/
9879
9880
static dev_t
9881
os_makedev_impl(PyObject *module, int major, int minor)
9882
/*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
9883
0
{
9884
0
    return makedev(major, minor);
9885
0
}
9886
#endif /* HAVE_DEVICE_MACROS */
9887
9888
9889
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
9890
/*[clinic input]
9891
os.ftruncate
9892
9893
    fd: int
9894
    length: Py_off_t
9895
    /
9896
9897
Truncate a file, specified by file descriptor, to a specific length.
9898
[clinic start generated code]*/
9899
9900
static PyObject *
9901
os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
9902
/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
9903
0
{
9904
0
    int result;
9905
0
    int async_err = 0;
9906
9907
0
    if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
9908
0
        return NULL;
9909
0
    }
9910
9911
0
    do {
9912
0
        Py_BEGIN_ALLOW_THREADS
9913
0
        _Py_BEGIN_SUPPRESS_IPH
9914
#ifdef MS_WINDOWS
9915
        result = _chsize_s(fd, length);
9916
#else
9917
0
        result = ftruncate(fd, length);
9918
0
#endif
9919
0
        _Py_END_SUPPRESS_IPH
9920
0
        Py_END_ALLOW_THREADS
9921
0
    } while (result != 0 && errno == EINTR &&
9922
0
             !(async_err = PyErr_CheckSignals()));
9923
0
    if (result != 0)
9924
0
        return (!async_err) ? posix_error() : NULL;
9925
0
    Py_RETURN_NONE;
9926
0
}
9927
#endif /* HAVE_FTRUNCATE || MS_WINDOWS */
9928
9929
9930
#if defined HAVE_TRUNCATE || defined MS_WINDOWS
9931
/*[clinic input]
9932
os.truncate
9933
    path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
9934
    length: Py_off_t
9935
9936
Truncate a file, specified by path, to a specific length.
9937
9938
On some platforms, path may also be specified as an open file descriptor.
9939
  If this functionality is unavailable, using it raises an exception.
9940
[clinic start generated code]*/
9941
9942
static PyObject *
9943
os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
9944
/*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
9945
0
{
9946
0
    int result;
9947
#ifdef MS_WINDOWS
9948
    int fd;
9949
#endif
9950
9951
0
    if (path->fd != -1)
9952
0
        return os_ftruncate_impl(module, path->fd, length);
9953
9954
0
    if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
9955
0
        return NULL;
9956
0
    }
9957
9958
0
    Py_BEGIN_ALLOW_THREADS
9959
0
    _Py_BEGIN_SUPPRESS_IPH
9960
#ifdef MS_WINDOWS
9961
    fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
9962
    if (fd < 0)
9963
        result = -1;
9964
    else {
9965
        result = _chsize_s(fd, length);
9966
        close(fd);
9967
        if (result < 0)
9968
            errno = result;
9969
    }
9970
#else
9971
0
    result = truncate(path->narrow, length);
9972
0
#endif
9973
0
    _Py_END_SUPPRESS_IPH
9974
0
    Py_END_ALLOW_THREADS
9975
0
    if (result < 0)
9976
0
        return posix_path_error(path);
9977
9978
0
    Py_RETURN_NONE;
9979
0
}
9980
#endif /* HAVE_TRUNCATE || MS_WINDOWS */
9981
9982
9983
/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
9984
   and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
9985
   defined, which is the case in Python on AIX. AIX bug report:
9986
   http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
9987
#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
9988
#  define POSIX_FADVISE_AIX_BUG
9989
#endif
9990
9991
9992
#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
9993
/*[clinic input]
9994
os.posix_fallocate
9995
9996
    fd: int
9997
    offset: Py_off_t
9998
    length: Py_off_t
9999
    /
10000
10001
Ensure a file has allocated at least a particular number of bytes on disk.
10002
10003
Ensure that the file specified by fd encompasses a range of bytes
10004
starting at offset bytes from the beginning and continuing for length bytes.
10005
[clinic start generated code]*/
10006
10007
static PyObject *
10008
os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
10009
                        Py_off_t length)
10010
/*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
10011
0
{
10012
0
    int result;
10013
0
    int async_err = 0;
10014
10015
0
    do {
10016
0
        Py_BEGIN_ALLOW_THREADS
10017
0
        result = posix_fallocate(fd, offset, length);
10018
0
        Py_END_ALLOW_THREADS
10019
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10020
10021
0
    if (result == 0)
10022
0
        Py_RETURN_NONE;
10023
10024
0
    if (async_err)
10025
0
        return NULL;
10026
10027
0
    errno = result;
10028
0
    return posix_error();
10029
0
}
10030
#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
10031
10032
10033
#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
10034
/*[clinic input]
10035
os.posix_fadvise
10036
10037
    fd: int
10038
    offset: Py_off_t
10039
    length: Py_off_t
10040
    advice: int
10041
    /
10042
10043
Announce an intention to access data in a specific pattern.
10044
10045
Announce an intention to access data in a specific pattern, thus allowing
10046
the kernel to make optimizations.
10047
The advice applies to the region of the file specified by fd starting at
10048
offset and continuing for length bytes.
10049
advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
10050
POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
10051
POSIX_FADV_DONTNEED.
10052
[clinic start generated code]*/
10053
10054
static PyObject *
10055
os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
10056
                      Py_off_t length, int advice)
10057
/*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
10058
0
{
10059
0
    int result;
10060
0
    int async_err = 0;
10061
10062
0
    do {
10063
0
        Py_BEGIN_ALLOW_THREADS
10064
0
        result = posix_fadvise(fd, offset, length, advice);
10065
0
        Py_END_ALLOW_THREADS
10066
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10067
10068
0
    if (result == 0)
10069
0
        Py_RETURN_NONE;
10070
10071
0
    if (async_err)
10072
0
        return NULL;
10073
10074
0
    errno = result;
10075
0
    return posix_error();
10076
0
}
10077
#endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
10078
10079
#ifdef HAVE_PUTENV
10080
10081
/* Save putenv() parameters as values here, so we can collect them when they
10082
 * get re-set with another call for the same key. */
10083
static PyObject *posix_putenv_garbage;
10084
10085
static void
10086
posix_putenv_garbage_setitem(PyObject *name, PyObject *value)
10087
0
{
10088
    /* Install the first arg and newstr in posix_putenv_garbage;
10089
     * this will cause previous value to be collected.  This has to
10090
     * happen after the real putenv() call because the old value
10091
     * was still accessible until then. */
10092
0
    if (PyDict_SetItem(posix_putenv_garbage, name, value))
10093
        /* really not much we can do; just leak */
10094
0
        PyErr_Clear();
10095
0
    else
10096
0
        Py_DECREF(value);
10097
0
}
10098
10099
10100
#ifdef MS_WINDOWS
10101
/*[clinic input]
10102
os.putenv
10103
10104
    name: unicode
10105
    value: unicode
10106
    /
10107
10108
Change or add an environment variable.
10109
[clinic start generated code]*/
10110
10111
static PyObject *
10112
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10113
/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
10114
{
10115
    const wchar_t *env;
10116
    Py_ssize_t size;
10117
10118
    /* Search from index 1 because on Windows starting '=' is allowed for
10119
       defining hidden environment variables. */
10120
    if (PyUnicode_GET_LENGTH(name) == 0 ||
10121
        PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
10122
    {
10123
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10124
        return NULL;
10125
    }
10126
    PyObject *unicode = PyUnicode_FromFormat("%U=%U", name, value);
10127
    if (unicode == NULL) {
10128
        return NULL;
10129
    }
10130
10131
    env = PyUnicode_AsUnicodeAndSize(unicode, &size);
10132
    if (env == NULL)
10133
        goto error;
10134
    if (size > _MAX_ENV) {
10135
        PyErr_Format(PyExc_ValueError,
10136
                     "the environment variable is longer than %u characters",
10137
                     _MAX_ENV);
10138
        goto error;
10139
    }
10140
    if (wcslen(env) != (size_t)size) {
10141
        PyErr_SetString(PyExc_ValueError, "embedded null character");
10142
        goto error;
10143
    }
10144
10145
    if (_wputenv(env)) {
10146
        posix_error();
10147
        goto error;
10148
    }
10149
10150
    posix_putenv_garbage_setitem(name, unicode);
10151
    Py_RETURN_NONE;
10152
10153
error:
10154
    Py_DECREF(unicode);
10155
    return NULL;
10156
}
10157
#else /* MS_WINDOWS */
10158
/*[clinic input]
10159
os.putenv
10160
10161
    name: FSConverter
10162
    value: FSConverter
10163
    /
10164
10165
Change or add an environment variable.
10166
[clinic start generated code]*/
10167
10168
static PyObject *
10169
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10170
/*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
10171
0
{
10172
0
    PyObject *bytes = NULL;
10173
0
    char *env;
10174
0
    const char *name_string = PyBytes_AS_STRING(name);
10175
0
    const char *value_string = PyBytes_AS_STRING(value);
10176
10177
0
    if (strchr(name_string, '=') != NULL) {
10178
0
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10179
0
        return NULL;
10180
0
    }
10181
0
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
10182
0
        return NULL;
10183
0
    }
10184
0
    bytes = PyBytes_FromFormat("%s=%s", name_string, value_string);
10185
0
    if (bytes == NULL) {
10186
0
        return NULL;
10187
0
    }
10188
10189
0
    env = PyBytes_AS_STRING(bytes);
10190
0
    if (putenv(env)) {
10191
0
        Py_DECREF(bytes);
10192
0
        return posix_error();
10193
0
    }
10194
10195
0
    posix_putenv_garbage_setitem(name, bytes);
10196
0
    Py_RETURN_NONE;
10197
0
}
10198
#endif /* MS_WINDOWS */
10199
#endif /* HAVE_PUTENV */
10200
10201
10202
#ifdef HAVE_UNSETENV
10203
/*[clinic input]
10204
os.unsetenv
10205
    name: FSConverter
10206
    /
10207
10208
Delete an environment variable.
10209
[clinic start generated code]*/
10210
10211
static PyObject *
10212
os_unsetenv_impl(PyObject *module, PyObject *name)
10213
/*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
10214
0
{
10215
0
#ifndef HAVE_BROKEN_UNSETENV
10216
0
    int err;
10217
0
#endif
10218
10219
0
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
10220
0
        return NULL;
10221
0
    }
10222
10223
#ifdef HAVE_BROKEN_UNSETENV
10224
    unsetenv(PyBytes_AS_STRING(name));
10225
#else
10226
0
    err = unsetenv(PyBytes_AS_STRING(name));
10227
0
    if (err)
10228
0
        return posix_error();
10229
0
#endif
10230
10231
    /* Remove the key from posix_putenv_garbage;
10232
     * this will cause it to be collected.  This has to
10233
     * happen after the real unsetenv() call because the
10234
     * old value was still accessible until then.
10235
     */
10236
0
    if (PyDict_DelItem(posix_putenv_garbage, name)) {
10237
        /* really not much we can do; just leak */
10238
0
        if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
10239
0
            return NULL;
10240
0
        }
10241
0
        PyErr_Clear();
10242
0
    }
10243
0
    Py_RETURN_NONE;
10244
0
}
10245
#endif /* HAVE_UNSETENV */
10246
10247
10248
/*[clinic input]
10249
os.strerror
10250
10251
    code: int
10252
    /
10253
10254
Translate an error code to a message string.
10255
[clinic start generated code]*/
10256
10257
static PyObject *
10258
os_strerror_impl(PyObject *module, int code)
10259
/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
10260
0
{
10261
0
    char *message = strerror(code);
10262
0
    if (message == NULL) {
10263
0
        PyErr_SetString(PyExc_ValueError,
10264
0
                        "strerror() argument out of range");
10265
0
        return NULL;
10266
0
    }
10267
0
    return PyUnicode_DecodeLocale(message, "surrogateescape");
10268
0
}
10269
10270
10271
#ifdef HAVE_SYS_WAIT_H
10272
#ifdef WCOREDUMP
10273
/*[clinic input]
10274
os.WCOREDUMP -> bool
10275
10276
    status: int
10277
    /
10278
10279
Return True if the process returning status was dumped to a core file.
10280
[clinic start generated code]*/
10281
10282
static int
10283
os_WCOREDUMP_impl(PyObject *module, int status)
10284
/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
10285
0
{
10286
0
    WAIT_TYPE wait_status;
10287
0
    WAIT_STATUS_INT(wait_status) = status;
10288
0
    return WCOREDUMP(wait_status);
10289
0
}
10290
#endif /* WCOREDUMP */
10291
10292
10293
#ifdef WIFCONTINUED
10294
/*[clinic input]
10295
os.WIFCONTINUED -> bool
10296
10297
    status: int
10298
10299
Return True if a particular process was continued from a job control stop.
10300
10301
Return True if the process returning status was continued from a
10302
job control stop.
10303
[clinic start generated code]*/
10304
10305
static int
10306
os_WIFCONTINUED_impl(PyObject *module, int status)
10307
/*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
10308
0
{
10309
0
    WAIT_TYPE wait_status;
10310
0
    WAIT_STATUS_INT(wait_status) = status;
10311
0
    return WIFCONTINUED(wait_status);
10312
0
}
10313
#endif /* WIFCONTINUED */
10314
10315
10316
#ifdef WIFSTOPPED
10317
/*[clinic input]
10318
os.WIFSTOPPED -> bool
10319
10320
    status: int
10321
10322
Return True if the process returning status was stopped.
10323
[clinic start generated code]*/
10324
10325
static int
10326
os_WIFSTOPPED_impl(PyObject *module, int status)
10327
/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
10328
0
{
10329
0
    WAIT_TYPE wait_status;
10330
0
    WAIT_STATUS_INT(wait_status) = status;
10331
0
    return WIFSTOPPED(wait_status);
10332
0
}
10333
#endif /* WIFSTOPPED */
10334
10335
10336
#ifdef WIFSIGNALED
10337
/*[clinic input]
10338
os.WIFSIGNALED -> bool
10339
10340
    status: int
10341
10342
Return True if the process returning status was terminated by a signal.
10343
[clinic start generated code]*/
10344
10345
static int
10346
os_WIFSIGNALED_impl(PyObject *module, int status)
10347
/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
10348
0
{
10349
0
    WAIT_TYPE wait_status;
10350
0
    WAIT_STATUS_INT(wait_status) = status;
10351
0
    return WIFSIGNALED(wait_status);
10352
0
}
10353
#endif /* WIFSIGNALED */
10354
10355
10356
#ifdef WIFEXITED
10357
/*[clinic input]
10358
os.WIFEXITED -> bool
10359
10360
    status: int
10361
10362
Return True if the process returning status exited via the exit() system call.
10363
[clinic start generated code]*/
10364
10365
static int
10366
os_WIFEXITED_impl(PyObject *module, int status)
10367
/*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
10368
0
{
10369
0
    WAIT_TYPE wait_status;
10370
0
    WAIT_STATUS_INT(wait_status) = status;
10371
0
    return WIFEXITED(wait_status);
10372
0
}
10373
#endif /* WIFEXITED */
10374
10375
10376
#ifdef WEXITSTATUS
10377
/*[clinic input]
10378
os.WEXITSTATUS -> int
10379
10380
    status: int
10381
10382
Return the process return code from status.
10383
[clinic start generated code]*/
10384
10385
static int
10386
os_WEXITSTATUS_impl(PyObject *module, int status)
10387
/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
10388
0
{
10389
0
    WAIT_TYPE wait_status;
10390
0
    WAIT_STATUS_INT(wait_status) = status;
10391
0
    return WEXITSTATUS(wait_status);
10392
0
}
10393
#endif /* WEXITSTATUS */
10394
10395
10396
#ifdef WTERMSIG
10397
/*[clinic input]
10398
os.WTERMSIG -> int
10399
10400
    status: int
10401
10402
Return the signal that terminated the process that provided the status value.
10403
[clinic start generated code]*/
10404
10405
static int
10406
os_WTERMSIG_impl(PyObject *module, int status)
10407
/*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
10408
0
{
10409
0
    WAIT_TYPE wait_status;
10410
0
    WAIT_STATUS_INT(wait_status) = status;
10411
0
    return WTERMSIG(wait_status);
10412
0
}
10413
#endif /* WTERMSIG */
10414
10415
10416
#ifdef WSTOPSIG
10417
/*[clinic input]
10418
os.WSTOPSIG -> int
10419
10420
    status: int
10421
10422
Return the signal that stopped the process that provided the status value.
10423
[clinic start generated code]*/
10424
10425
static int
10426
os_WSTOPSIG_impl(PyObject *module, int status)
10427
/*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
10428
0
{
10429
0
    WAIT_TYPE wait_status;
10430
0
    WAIT_STATUS_INT(wait_status) = status;
10431
0
    return WSTOPSIG(wait_status);
10432
0
}
10433
#endif /* WSTOPSIG */
10434
#endif /* HAVE_SYS_WAIT_H */
10435
10436
10437
#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
10438
#ifdef _SCO_DS
10439
/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
10440
   needed definitions in sys/statvfs.h */
10441
#define _SVID3
10442
#endif
10443
#include <sys/statvfs.h>
10444
10445
static PyObject*
10446
0
_pystatvfs_fromstructstatvfs(struct statvfs st) {
10447
0
    PyObject *v = PyStructSequence_New(StatVFSResultType);
10448
0
    if (v == NULL)
10449
0
        return NULL;
10450
10451
0
#if !defined(HAVE_LARGEFILE_SUPPORT)
10452
0
    PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
10453
0
    PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
10454
0
    PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
10455
0
    PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
10456
0
    PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
10457
0
    PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
10458
0
    PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
10459
0
    PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
10460
0
    PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
10461
0
    PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
10462
#else
10463
    PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
10464
    PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
10465
    PyStructSequence_SET_ITEM(v, 2,
10466
                              PyLong_FromLongLong((long long) st.f_blocks));
10467
    PyStructSequence_SET_ITEM(v, 3,
10468
                              PyLong_FromLongLong((long long) st.f_bfree));
10469
    PyStructSequence_SET_ITEM(v, 4,
10470
                              PyLong_FromLongLong((long long) st.f_bavail));
10471
    PyStructSequence_SET_ITEM(v, 5,
10472
                              PyLong_FromLongLong((long long) st.f_files));
10473
    PyStructSequence_SET_ITEM(v, 6,
10474
                              PyLong_FromLongLong((long long) st.f_ffree));
10475
    PyStructSequence_SET_ITEM(v, 7,
10476
                              PyLong_FromLongLong((long long) st.f_favail));
10477
    PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
10478
    PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
10479
#endif
10480
/* The _ALL_SOURCE feature test macro defines f_fsid as a structure
10481
 * (issue #32390). */
10482
#if defined(_AIX) && defined(_ALL_SOURCE)
10483
    PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
10484
#else
10485
0
    PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
10486
0
#endif
10487
0
    if (PyErr_Occurred()) {
10488
0
        Py_DECREF(v);
10489
0
        return NULL;
10490
0
    }
10491
10492
0
    return v;
10493
0
}
10494
10495
10496
/*[clinic input]
10497
os.fstatvfs
10498
    fd: int
10499
    /
10500
10501
Perform an fstatvfs system call on the given fd.
10502
10503
Equivalent to statvfs(fd).
10504
[clinic start generated code]*/
10505
10506
static PyObject *
10507
os_fstatvfs_impl(PyObject *module, int fd)
10508
/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
10509
0
{
10510
0
    int result;
10511
0
    int async_err = 0;
10512
0
    struct statvfs st;
10513
10514
0
    do {
10515
0
        Py_BEGIN_ALLOW_THREADS
10516
0
        result = fstatvfs(fd, &st);
10517
0
        Py_END_ALLOW_THREADS
10518
0
    } while (result != 0 && errno == EINTR &&
10519
0
             !(async_err = PyErr_CheckSignals()));
10520
0
    if (result != 0)
10521
0
        return (!async_err) ? posix_error() : NULL;
10522
10523
0
    return _pystatvfs_fromstructstatvfs(st);
10524
0
}
10525
#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
10526
10527
10528
#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
10529
#include <sys/statvfs.h>
10530
/*[clinic input]
10531
os.statvfs
10532
10533
    path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
10534
10535
Perform a statvfs system call on the given path.
10536
10537
path may always be specified as a string.
10538
On some platforms, path may also be specified as an open file descriptor.
10539
  If this functionality is unavailable, using it raises an exception.
10540
[clinic start generated code]*/
10541
10542
static PyObject *
10543
os_statvfs_impl(PyObject *module, path_t *path)
10544
/*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
10545
0
{
10546
0
    int result;
10547
0
    struct statvfs st;
10548
10549
0
    Py_BEGIN_ALLOW_THREADS
10550
0
#ifdef HAVE_FSTATVFS
10551
0
    if (path->fd != -1) {
10552
#ifdef __APPLE__
10553
        /* handle weak-linking on Mac OS X 10.3 */
10554
        if (fstatvfs == NULL) {
10555
            fd_specified("statvfs", path->fd);
10556
            return NULL;
10557
        }
10558
#endif
10559
0
        result = fstatvfs(path->fd, &st);
10560
0
    }
10561
0
    else
10562
0
#endif
10563
0
        result = statvfs(path->narrow, &st);
10564
0
    Py_END_ALLOW_THREADS
10565
10566
0
    if (result) {
10567
0
        return path_error(path);
10568
0
    }
10569
10570
0
    return _pystatvfs_fromstructstatvfs(st);
10571
0
}
10572
#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
10573
10574
10575
#ifdef MS_WINDOWS
10576
/*[clinic input]
10577
os._getdiskusage
10578
10579
    path: path_t
10580
10581
Return disk usage statistics about the given path as a (total, free) tuple.
10582
[clinic start generated code]*/
10583
10584
static PyObject *
10585
os__getdiskusage_impl(PyObject *module, path_t *path)
10586
/*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
10587
{
10588
    BOOL retval;
10589
    ULARGE_INTEGER _, total, free;
10590
    DWORD err = 0;
10591
10592
    Py_BEGIN_ALLOW_THREADS
10593
    retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
10594
    Py_END_ALLOW_THREADS
10595
    if (retval == 0) {
10596
        if (GetLastError() == ERROR_DIRECTORY) {
10597
            wchar_t *dir_path = NULL;
10598
10599
            dir_path = PyMem_New(wchar_t, path->length + 1);
10600
            if (dir_path == NULL) {
10601
                return PyErr_NoMemory();
10602
            }
10603
10604
            wcscpy_s(dir_path, path->length + 1, path->wide);
10605
10606
            if (_dirnameW(dir_path) != -1) {
10607
                Py_BEGIN_ALLOW_THREADS
10608
                retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
10609
                Py_END_ALLOW_THREADS
10610
            }
10611
            /* Record the last error in case it's modified by PyMem_Free. */
10612
            err = GetLastError();
10613
            PyMem_Free(dir_path);
10614
            if (retval) {
10615
                goto success;
10616
            }
10617
        }
10618
        return PyErr_SetFromWindowsErr(err);
10619
    }
10620
10621
success:
10622
    return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
10623
}
10624
#endif /* MS_WINDOWS */
10625
10626
10627
/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
10628
 * It maps strings representing configuration variable names to
10629
 * integer values, allowing those functions to be called with the
10630
 * magic names instead of polluting the module's namespace with tons of
10631
 * rarely-used constants.  There are three separate tables that use
10632
 * these definitions.
10633
 *
10634
 * This code is always included, even if none of the interfaces that
10635
 * need it are included.  The #if hackery needed to avoid it would be
10636
 * sufficiently pervasive that it's not worth the loss of readability.
10637
 */
10638
struct constdef {
10639
    const char *name;
10640
    int value;
10641
};
10642
10643
static int
10644
conv_confname(PyObject *arg, int *valuep, struct constdef *table,
10645
              size_t tablesize)
10646
0
{
10647
0
    if (PyLong_Check(arg)) {
10648
0
        int value = _PyLong_AsInt(arg);
10649
0
        if (value == -1 && PyErr_Occurred())
10650
0
            return 0;
10651
0
        *valuep = value;
10652
0
        return 1;
10653
0
    }
10654
0
    else {
10655
        /* look up the value in the table using a binary search */
10656
0
        size_t lo = 0;
10657
0
        size_t mid;
10658
0
        size_t hi = tablesize;
10659
0
        int cmp;
10660
0
        const char *confname;
10661
0
        if (!PyUnicode_Check(arg)) {
10662
0
            PyErr_SetString(PyExc_TypeError,
10663
0
                "configuration names must be strings or integers");
10664
0
            return 0;
10665
0
        }
10666
0
        confname = PyUnicode_AsUTF8(arg);
10667
0
        if (confname == NULL)
10668
0
            return 0;
10669
0
        while (lo < hi) {
10670
0
            mid = (lo + hi) / 2;
10671
0
            cmp = strcmp(confname, table[mid].name);
10672
0
            if (cmp < 0)
10673
0
                hi = mid;
10674
0
            else if (cmp > 0)
10675
0
                lo = mid + 1;
10676
0
            else {
10677
0
                *valuep = table[mid].value;
10678
0
                return 1;
10679
0
            }
10680
0
        }
10681
0
        PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
10682
0
        return 0;
10683
0
    }
10684
0
}
10685
10686
10687
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
10688
static struct constdef  posix_constants_pathconf[] = {
10689
#ifdef _PC_ABI_AIO_XFER_MAX
10690
    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
10691
#endif
10692
#ifdef _PC_ABI_ASYNC_IO
10693
    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
10694
#endif
10695
#ifdef _PC_ASYNC_IO
10696
    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
10697
#endif
10698
#ifdef _PC_CHOWN_RESTRICTED
10699
    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
10700
#endif
10701
#ifdef _PC_FILESIZEBITS
10702
    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
10703
#endif
10704
#ifdef _PC_LAST
10705
    {"PC_LAST", _PC_LAST},
10706
#endif
10707
#ifdef _PC_LINK_MAX
10708
    {"PC_LINK_MAX",     _PC_LINK_MAX},
10709
#endif
10710
#ifdef _PC_MAX_CANON
10711
    {"PC_MAX_CANON",    _PC_MAX_CANON},
10712
#endif
10713
#ifdef _PC_MAX_INPUT
10714
    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
10715
#endif
10716
#ifdef _PC_NAME_MAX
10717
    {"PC_NAME_MAX",     _PC_NAME_MAX},
10718
#endif
10719
#ifdef _PC_NO_TRUNC
10720
    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
10721
#endif
10722
#ifdef _PC_PATH_MAX
10723
    {"PC_PATH_MAX",     _PC_PATH_MAX},
10724
#endif
10725
#ifdef _PC_PIPE_BUF
10726
    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
10727
#endif
10728
#ifdef _PC_PRIO_IO
10729
    {"PC_PRIO_IO",      _PC_PRIO_IO},
10730
#endif
10731
#ifdef _PC_SOCK_MAXBUF
10732
    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
10733
#endif
10734
#ifdef _PC_SYNC_IO
10735
    {"PC_SYNC_IO",      _PC_SYNC_IO},
10736
#endif
10737
#ifdef _PC_VDISABLE
10738
    {"PC_VDISABLE",     _PC_VDISABLE},
10739
#endif
10740
#ifdef _PC_ACL_ENABLED
10741
    {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
10742
#endif
10743
#ifdef _PC_MIN_HOLE_SIZE
10744
    {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
10745
#endif
10746
#ifdef _PC_ALLOC_SIZE_MIN
10747
    {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
10748
#endif
10749
#ifdef _PC_REC_INCR_XFER_SIZE
10750
    {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
10751
#endif
10752
#ifdef _PC_REC_MAX_XFER_SIZE
10753
    {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
10754
#endif
10755
#ifdef _PC_REC_MIN_XFER_SIZE
10756
    {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
10757
#endif
10758
#ifdef _PC_REC_XFER_ALIGN
10759
    {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
10760
#endif
10761
#ifdef _PC_SYMLINK_MAX
10762
    {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
10763
#endif
10764
#ifdef _PC_XATTR_ENABLED
10765
    {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
10766
#endif
10767
#ifdef _PC_XATTR_EXISTS
10768
    {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
10769
#endif
10770
#ifdef _PC_TIMESTAMP_RESOLUTION
10771
    {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
10772
#endif
10773
};
10774
10775
static int
10776
conv_path_confname(PyObject *arg, int *valuep)
10777
0
{
10778
0
    return conv_confname(arg, valuep, posix_constants_pathconf,
10779
0
                         sizeof(posix_constants_pathconf)
10780
0
                           / sizeof(struct constdef));
10781
0
}
10782
#endif
10783
10784
10785
#ifdef HAVE_FPATHCONF
10786
/*[clinic input]
10787
os.fpathconf -> long
10788
10789
    fd: int
10790
    name: path_confname
10791
    /
10792
10793
Return the configuration limit name for the file descriptor fd.
10794
10795
If there is no limit, return -1.
10796
[clinic start generated code]*/
10797
10798
static long
10799
os_fpathconf_impl(PyObject *module, int fd, int name)
10800
/*[clinic end generated code: output=d5b7042425fc3e21 input=5942a024d3777810]*/
10801
0
{
10802
0
    long limit;
10803
10804
0
    errno = 0;
10805
0
    limit = fpathconf(fd, name);
10806
0
    if (limit == -1 && errno != 0)
10807
0
        posix_error();
10808
10809
0
    return limit;
10810
0
}
10811
#endif /* HAVE_FPATHCONF */
10812
10813
10814
#ifdef HAVE_PATHCONF
10815
/*[clinic input]
10816
os.pathconf -> long
10817
    path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
10818
    name: path_confname
10819
10820
Return the configuration limit name for the file or directory path.
10821
10822
If there is no limit, return -1.
10823
On some platforms, path may also be specified as an open file descriptor.
10824
  If this functionality is unavailable, using it raises an exception.
10825
[clinic start generated code]*/
10826
10827
static long
10828
os_pathconf_impl(PyObject *module, path_t *path, int name)
10829
/*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
10830
0
{
10831
0
    long limit;
10832
10833
0
    errno = 0;
10834
0
#ifdef HAVE_FPATHCONF
10835
0
    if (path->fd != -1)
10836
0
        limit = fpathconf(path->fd, name);
10837
0
    else
10838
0
#endif
10839
0
        limit = pathconf(path->narrow, name);
10840
0
    if (limit == -1 && errno != 0) {
10841
0
        if (errno == EINVAL)
10842
            /* could be a path or name problem */
10843
0
            posix_error();
10844
0
        else
10845
0
            path_error(path);
10846
0
    }
10847
10848
0
    return limit;
10849
0
}
10850
#endif /* HAVE_PATHCONF */
10851
10852
#ifdef HAVE_CONFSTR
10853
static struct constdef posix_constants_confstr[] = {
10854
#ifdef _CS_ARCHITECTURE
10855
    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
10856
#endif
10857
#ifdef _CS_GNU_LIBC_VERSION
10858
    {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
10859
#endif
10860
#ifdef _CS_GNU_LIBPTHREAD_VERSION
10861
    {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
10862
#endif
10863
#ifdef _CS_HOSTNAME
10864
    {"CS_HOSTNAME",     _CS_HOSTNAME},
10865
#endif
10866
#ifdef _CS_HW_PROVIDER
10867
    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
10868
#endif
10869
#ifdef _CS_HW_SERIAL
10870
    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
10871
#endif
10872
#ifdef _CS_INITTAB_NAME
10873
    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
10874
#endif
10875
#ifdef _CS_LFS64_CFLAGS
10876
    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
10877
#endif
10878
#ifdef _CS_LFS64_LDFLAGS
10879
    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
10880
#endif
10881
#ifdef _CS_LFS64_LIBS
10882
    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
10883
#endif
10884
#ifdef _CS_LFS64_LINTFLAGS
10885
    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
10886
#endif
10887
#ifdef _CS_LFS_CFLAGS
10888
    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
10889
#endif
10890
#ifdef _CS_LFS_LDFLAGS
10891
    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
10892
#endif
10893
#ifdef _CS_LFS_LIBS
10894
    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
10895
#endif
10896
#ifdef _CS_LFS_LINTFLAGS
10897
    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
10898
#endif
10899
#ifdef _CS_MACHINE
10900
    {"CS_MACHINE",      _CS_MACHINE},
10901
#endif
10902
#ifdef _CS_PATH
10903
    {"CS_PATH", _CS_PATH},
10904
#endif
10905
#ifdef _CS_RELEASE
10906
    {"CS_RELEASE",      _CS_RELEASE},
10907
#endif
10908
#ifdef _CS_SRPC_DOMAIN
10909
    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
10910
#endif
10911
#ifdef _CS_SYSNAME
10912
    {"CS_SYSNAME",      _CS_SYSNAME},
10913
#endif
10914
#ifdef _CS_VERSION
10915
    {"CS_VERSION",      _CS_VERSION},
10916
#endif
10917
#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
10918
    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
10919
#endif
10920
#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
10921
    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
10922
#endif
10923
#ifdef _CS_XBS5_ILP32_OFF32_LIBS
10924
    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
10925
#endif
10926
#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
10927
    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
10928
#endif
10929
#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
10930
    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
10931
#endif
10932
#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
10933
    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
10934
#endif
10935
#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
10936
    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
10937
#endif
10938
#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
10939
    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
10940
#endif
10941
#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
10942
    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
10943
#endif
10944
#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
10945
    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
10946
#endif
10947
#ifdef _CS_XBS5_LP64_OFF64_LIBS
10948
    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
10949
#endif
10950
#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
10951
    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
10952
#endif
10953
#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
10954
    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
10955
#endif
10956
#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
10957
    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
10958
#endif
10959
#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
10960
    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
10961
#endif
10962
#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
10963
    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
10964
#endif
10965
#ifdef _MIPS_CS_AVAIL_PROCESSORS
10966
    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
10967
#endif
10968
#ifdef _MIPS_CS_BASE
10969
    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
10970
#endif
10971
#ifdef _MIPS_CS_HOSTID
10972
    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
10973
#endif
10974
#ifdef _MIPS_CS_HW_NAME
10975
    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
10976
#endif
10977
#ifdef _MIPS_CS_NUM_PROCESSORS
10978
    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
10979
#endif
10980
#ifdef _MIPS_CS_OSREL_MAJ
10981
    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
10982
#endif
10983
#ifdef _MIPS_CS_OSREL_MIN
10984
    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
10985
#endif
10986
#ifdef _MIPS_CS_OSREL_PATCH
10987
    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
10988
#endif
10989
#ifdef _MIPS_CS_OS_NAME
10990
    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
10991
#endif
10992
#ifdef _MIPS_CS_OS_PROVIDER
10993
    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
10994
#endif
10995
#ifdef _MIPS_CS_PROCESSORS
10996
    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
10997
#endif
10998
#ifdef _MIPS_CS_SERIAL
10999
    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
11000
#endif
11001
#ifdef _MIPS_CS_VENDOR
11002
    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
11003
#endif
11004
};
11005
11006
static int
11007
conv_confstr_confname(PyObject *arg, int *valuep)
11008
0
{
11009
0
    return conv_confname(arg, valuep, posix_constants_confstr,
11010
0
                         sizeof(posix_constants_confstr)
11011
0
                           / sizeof(struct constdef));
11012
0
}
11013
11014
11015
/*[clinic input]
11016
os.confstr
11017
11018
    name: confstr_confname
11019
    /
11020
11021
Return a string-valued system configuration variable.
11022
[clinic start generated code]*/
11023
11024
static PyObject *
11025
os_confstr_impl(PyObject *module, int name)
11026
/*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
11027
0
{
11028
0
    PyObject *result = NULL;
11029
0
    char buffer[255];
11030
0
    size_t len;
11031
11032
0
    errno = 0;
11033
0
    len = confstr(name, buffer, sizeof(buffer));
11034
0
    if (len == 0) {
11035
0
        if (errno) {
11036
0
            posix_error();
11037
0
            return NULL;
11038
0
        }
11039
0
        else {
11040
0
            Py_RETURN_NONE;
11041
0
        }
11042
0
    }
11043
11044
0
    if (len >= sizeof(buffer)) {
11045
0
        size_t len2;
11046
0
        char *buf = PyMem_Malloc(len);
11047
0
        if (buf == NULL)
11048
0
            return PyErr_NoMemory();
11049
0
        len2 = confstr(name, buf, len);
11050
0
        assert(len == len2);
11051
0
        result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
11052
0
        PyMem_Free(buf);
11053
0
    }
11054
0
    else
11055
0
        result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
11056
0
    return result;
11057
0
}
11058
#endif /* HAVE_CONFSTR */
11059
11060
11061
#ifdef HAVE_SYSCONF
11062
static struct constdef posix_constants_sysconf[] = {
11063
#ifdef _SC_2_CHAR_TERM
11064
    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
11065
#endif
11066
#ifdef _SC_2_C_BIND
11067
    {"SC_2_C_BIND",     _SC_2_C_BIND},
11068
#endif
11069
#ifdef _SC_2_C_DEV
11070
    {"SC_2_C_DEV",      _SC_2_C_DEV},
11071
#endif
11072
#ifdef _SC_2_C_VERSION
11073
    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
11074
#endif
11075
#ifdef _SC_2_FORT_DEV
11076
    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
11077
#endif
11078
#ifdef _SC_2_FORT_RUN
11079
    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
11080
#endif
11081
#ifdef _SC_2_LOCALEDEF
11082
    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
11083
#endif
11084
#ifdef _SC_2_SW_DEV
11085
    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
11086
#endif
11087
#ifdef _SC_2_UPE
11088
    {"SC_2_UPE",        _SC_2_UPE},
11089
#endif
11090
#ifdef _SC_2_VERSION
11091
    {"SC_2_VERSION",    _SC_2_VERSION},
11092
#endif
11093
#ifdef _SC_ABI_ASYNCHRONOUS_IO
11094
    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
11095
#endif
11096
#ifdef _SC_ACL
11097
    {"SC_ACL",  _SC_ACL},
11098
#endif
11099
#ifdef _SC_AIO_LISTIO_MAX
11100
    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
11101
#endif
11102
#ifdef _SC_AIO_MAX
11103
    {"SC_AIO_MAX",      _SC_AIO_MAX},
11104
#endif
11105
#ifdef _SC_AIO_PRIO_DELTA_MAX
11106
    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
11107
#endif
11108
#ifdef _SC_ARG_MAX
11109
    {"SC_ARG_MAX",      _SC_ARG_MAX},
11110
#endif
11111
#ifdef _SC_ASYNCHRONOUS_IO
11112
    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
11113
#endif
11114
#ifdef _SC_ATEXIT_MAX
11115
    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
11116
#endif
11117
#ifdef _SC_AUDIT
11118
    {"SC_AUDIT",        _SC_AUDIT},
11119
#endif
11120
#ifdef _SC_AVPHYS_PAGES
11121
    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
11122
#endif
11123
#ifdef _SC_BC_BASE_MAX
11124
    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
11125
#endif
11126
#ifdef _SC_BC_DIM_MAX
11127
    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
11128
#endif
11129
#ifdef _SC_BC_SCALE_MAX
11130
    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
11131
#endif
11132
#ifdef _SC_BC_STRING_MAX
11133
    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
11134
#endif
11135
#ifdef _SC_CAP
11136
    {"SC_CAP",  _SC_CAP},
11137
#endif
11138
#ifdef _SC_CHARCLASS_NAME_MAX
11139
    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
11140
#endif
11141
#ifdef _SC_CHAR_BIT
11142
    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
11143
#endif
11144
#ifdef _SC_CHAR_MAX
11145
    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
11146
#endif
11147
#ifdef _SC_CHAR_MIN
11148
    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
11149
#endif
11150
#ifdef _SC_CHILD_MAX
11151
    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
11152
#endif
11153
#ifdef _SC_CLK_TCK
11154
    {"SC_CLK_TCK",      _SC_CLK_TCK},
11155
#endif
11156
#ifdef _SC_COHER_BLKSZ
11157
    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
11158
#endif
11159
#ifdef _SC_COLL_WEIGHTS_MAX
11160
    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
11161
#endif
11162
#ifdef _SC_DCACHE_ASSOC
11163
    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
11164
#endif
11165
#ifdef _SC_DCACHE_BLKSZ
11166
    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
11167
#endif
11168
#ifdef _SC_DCACHE_LINESZ
11169
    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
11170
#endif
11171
#ifdef _SC_DCACHE_SZ
11172
    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
11173
#endif
11174
#ifdef _SC_DCACHE_TBLKSZ
11175
    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
11176
#endif
11177
#ifdef _SC_DELAYTIMER_MAX
11178
    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
11179
#endif
11180
#ifdef _SC_EQUIV_CLASS_MAX
11181
    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
11182
#endif
11183
#ifdef _SC_EXPR_NEST_MAX
11184
    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
11185
#endif
11186
#ifdef _SC_FSYNC
11187
    {"SC_FSYNC",        _SC_FSYNC},
11188
#endif
11189
#ifdef _SC_GETGR_R_SIZE_MAX
11190
    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
11191
#endif
11192
#ifdef _SC_GETPW_R_SIZE_MAX
11193
    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
11194
#endif
11195
#ifdef _SC_ICACHE_ASSOC
11196
    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
11197
#endif
11198
#ifdef _SC_ICACHE_BLKSZ
11199
    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
11200
#endif
11201
#ifdef _SC_ICACHE_LINESZ
11202
    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
11203
#endif
11204
#ifdef _SC_ICACHE_SZ
11205
    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
11206
#endif
11207
#ifdef _SC_INF
11208
    {"SC_INF",  _SC_INF},
11209
#endif
11210
#ifdef _SC_INT_MAX
11211
    {"SC_INT_MAX",      _SC_INT_MAX},
11212
#endif
11213
#ifdef _SC_INT_MIN
11214
    {"SC_INT_MIN",      _SC_INT_MIN},
11215
#endif
11216
#ifdef _SC_IOV_MAX
11217
    {"SC_IOV_MAX",      _SC_IOV_MAX},
11218
#endif
11219
#ifdef _SC_IP_SECOPTS
11220
    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
11221
#endif
11222
#ifdef _SC_JOB_CONTROL
11223
    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
11224
#endif
11225
#ifdef _SC_KERN_POINTERS
11226
    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
11227
#endif
11228
#ifdef _SC_KERN_SIM
11229
    {"SC_KERN_SIM",     _SC_KERN_SIM},
11230
#endif
11231
#ifdef _SC_LINE_MAX
11232
    {"SC_LINE_MAX",     _SC_LINE_MAX},
11233
#endif
11234
#ifdef _SC_LOGIN_NAME_MAX
11235
    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
11236
#endif
11237
#ifdef _SC_LOGNAME_MAX
11238
    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
11239
#endif
11240
#ifdef _SC_LONG_BIT
11241
    {"SC_LONG_BIT",     _SC_LONG_BIT},
11242
#endif
11243
#ifdef _SC_MAC
11244
    {"SC_MAC",  _SC_MAC},
11245
#endif
11246
#ifdef _SC_MAPPED_FILES
11247
    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
11248
#endif
11249
#ifdef _SC_MAXPID
11250
    {"SC_MAXPID",       _SC_MAXPID},
11251
#endif
11252
#ifdef _SC_MB_LEN_MAX
11253
    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
11254
#endif
11255
#ifdef _SC_MEMLOCK
11256
    {"SC_MEMLOCK",      _SC_MEMLOCK},
11257
#endif
11258
#ifdef _SC_MEMLOCK_RANGE
11259
    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
11260
#endif
11261
#ifdef _SC_MEMORY_PROTECTION
11262
    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
11263
#endif
11264
#ifdef _SC_MESSAGE_PASSING
11265
    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
11266
#endif
11267
#ifdef _SC_MMAP_FIXED_ALIGNMENT
11268
    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
11269
#endif
11270
#ifdef _SC_MQ_OPEN_MAX
11271
    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
11272
#endif
11273
#ifdef _SC_MQ_PRIO_MAX
11274
    {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
11275
#endif
11276
#ifdef _SC_NACLS_MAX
11277
    {"SC_NACLS_MAX",    _SC_NACLS_MAX},
11278
#endif
11279
#ifdef _SC_NGROUPS_MAX
11280
    {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
11281
#endif
11282
#ifdef _SC_NL_ARGMAX
11283
    {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
11284
#endif
11285
#ifdef _SC_NL_LANGMAX
11286
    {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
11287
#endif
11288
#ifdef _SC_NL_MSGMAX
11289
    {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
11290
#endif
11291
#ifdef _SC_NL_NMAX
11292
    {"SC_NL_NMAX",      _SC_NL_NMAX},
11293
#endif
11294
#ifdef _SC_NL_SETMAX
11295
    {"SC_NL_SETMAX",    _SC_NL_SETMAX},
11296
#endif
11297
#ifdef _SC_NL_TEXTMAX
11298
    {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
11299
#endif
11300
#ifdef _SC_NPROCESSORS_CONF
11301
    {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
11302
#endif
11303
#ifdef _SC_NPROCESSORS_ONLN
11304
    {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
11305
#endif
11306
#ifdef _SC_NPROC_CONF
11307
    {"SC_NPROC_CONF",   _SC_NPROC_CONF},
11308
#endif
11309
#ifdef _SC_NPROC_ONLN
11310
    {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
11311
#endif
11312
#ifdef _SC_NZERO
11313
    {"SC_NZERO",        _SC_NZERO},
11314
#endif
11315
#ifdef _SC_OPEN_MAX
11316
    {"SC_OPEN_MAX",     _SC_OPEN_MAX},
11317
#endif
11318
#ifdef _SC_PAGESIZE
11319
    {"SC_PAGESIZE",     _SC_PAGESIZE},
11320
#endif
11321
#ifdef _SC_PAGE_SIZE
11322
    {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
11323
#endif
11324
#ifdef _SC_PASS_MAX
11325
    {"SC_PASS_MAX",     _SC_PASS_MAX},
11326
#endif
11327
#ifdef _SC_PHYS_PAGES
11328
    {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
11329
#endif
11330
#ifdef _SC_PII
11331
    {"SC_PII",  _SC_PII},
11332
#endif
11333
#ifdef _SC_PII_INTERNET
11334
    {"SC_PII_INTERNET", _SC_PII_INTERNET},
11335
#endif
11336
#ifdef _SC_PII_INTERNET_DGRAM
11337
    {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
11338
#endif
11339
#ifdef _SC_PII_INTERNET_STREAM
11340
    {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
11341
#endif
11342
#ifdef _SC_PII_OSI
11343
    {"SC_PII_OSI",      _SC_PII_OSI},
11344
#endif
11345
#ifdef _SC_PII_OSI_CLTS
11346
    {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
11347
#endif
11348
#ifdef _SC_PII_OSI_COTS
11349
    {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
11350
#endif
11351
#ifdef _SC_PII_OSI_M
11352
    {"SC_PII_OSI_M",    _SC_PII_OSI_M},
11353
#endif
11354
#ifdef _SC_PII_SOCKET
11355
    {"SC_PII_SOCKET",   _SC_PII_SOCKET},
11356
#endif
11357
#ifdef _SC_PII_XTI
11358
    {"SC_PII_XTI",      _SC_PII_XTI},
11359
#endif
11360
#ifdef _SC_POLL
11361
    {"SC_POLL", _SC_POLL},
11362
#endif
11363
#ifdef _SC_PRIORITIZED_IO
11364
    {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
11365
#endif
11366
#ifdef _SC_PRIORITY_SCHEDULING
11367
    {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
11368
#endif
11369
#ifdef _SC_REALTIME_SIGNALS
11370
    {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
11371
#endif
11372
#ifdef _SC_RE_DUP_MAX
11373
    {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
11374
#endif
11375
#ifdef _SC_RTSIG_MAX
11376
    {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
11377
#endif
11378
#ifdef _SC_SAVED_IDS
11379
    {"SC_SAVED_IDS",    _SC_SAVED_IDS},
11380
#endif
11381
#ifdef _SC_SCHAR_MAX
11382
    {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
11383
#endif
11384
#ifdef _SC_SCHAR_MIN
11385
    {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
11386
#endif
11387
#ifdef _SC_SELECT
11388
    {"SC_SELECT",       _SC_SELECT},
11389
#endif
11390
#ifdef _SC_SEMAPHORES
11391
    {"SC_SEMAPHORES",   _SC_SEMAPHORES},
11392
#endif
11393
#ifdef _SC_SEM_NSEMS_MAX
11394
    {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
11395
#endif
11396
#ifdef _SC_SEM_VALUE_MAX
11397
    {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
11398
#endif
11399
#ifdef _SC_SHARED_MEMORY_OBJECTS
11400
    {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
11401
#endif
11402
#ifdef _SC_SHRT_MAX
11403
    {"SC_SHRT_MAX",     _SC_SHRT_MAX},
11404
#endif
11405
#ifdef _SC_SHRT_MIN
11406
    {"SC_SHRT_MIN",     _SC_SHRT_MIN},
11407
#endif
11408
#ifdef _SC_SIGQUEUE_MAX
11409
    {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
11410
#endif
11411
#ifdef _SC_SIGRT_MAX
11412
    {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
11413
#endif
11414
#ifdef _SC_SIGRT_MIN
11415
    {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
11416
#endif
11417
#ifdef _SC_SOFTPOWER
11418
    {"SC_SOFTPOWER",    _SC_SOFTPOWER},
11419
#endif
11420
#ifdef _SC_SPLIT_CACHE
11421
    {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
11422
#endif
11423
#ifdef _SC_SSIZE_MAX
11424
    {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
11425
#endif
11426
#ifdef _SC_STACK_PROT
11427
    {"SC_STACK_PROT",   _SC_STACK_PROT},
11428
#endif
11429
#ifdef _SC_STREAM_MAX
11430
    {"SC_STREAM_MAX",   _SC_STREAM_MAX},
11431
#endif
11432
#ifdef _SC_SYNCHRONIZED_IO
11433
    {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
11434
#endif
11435
#ifdef _SC_THREADS
11436
    {"SC_THREADS",      _SC_THREADS},
11437
#endif
11438
#ifdef _SC_THREAD_ATTR_STACKADDR
11439
    {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
11440
#endif
11441
#ifdef _SC_THREAD_ATTR_STACKSIZE
11442
    {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
11443
#endif
11444
#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
11445
    {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
11446
#endif
11447
#ifdef _SC_THREAD_KEYS_MAX
11448
    {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
11449
#endif
11450
#ifdef _SC_THREAD_PRIORITY_SCHEDULING
11451
    {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
11452
#endif
11453
#ifdef _SC_THREAD_PRIO_INHERIT
11454
    {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
11455
#endif
11456
#ifdef _SC_THREAD_PRIO_PROTECT
11457
    {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
11458
#endif
11459
#ifdef _SC_THREAD_PROCESS_SHARED
11460
    {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
11461
#endif
11462
#ifdef _SC_THREAD_SAFE_FUNCTIONS
11463
    {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
11464
#endif
11465
#ifdef _SC_THREAD_STACK_MIN
11466
    {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
11467
#endif
11468
#ifdef _SC_THREAD_THREADS_MAX
11469
    {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
11470
#endif
11471
#ifdef _SC_TIMERS
11472
    {"SC_TIMERS",       _SC_TIMERS},
11473
#endif
11474
#ifdef _SC_TIMER_MAX
11475
    {"SC_TIMER_MAX",    _SC_TIMER_MAX},
11476
#endif
11477
#ifdef _SC_TTY_NAME_MAX
11478
    {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
11479
#endif
11480
#ifdef _SC_TZNAME_MAX
11481
    {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
11482
#endif
11483
#ifdef _SC_T_IOV_MAX
11484
    {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
11485
#endif
11486
#ifdef _SC_UCHAR_MAX
11487
    {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
11488
#endif
11489
#ifdef _SC_UINT_MAX
11490
    {"SC_UINT_MAX",     _SC_UINT_MAX},
11491
#endif
11492
#ifdef _SC_UIO_MAXIOV
11493
    {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
11494
#endif
11495
#ifdef _SC_ULONG_MAX
11496
    {"SC_ULONG_MAX",    _SC_ULONG_MAX},
11497
#endif
11498
#ifdef _SC_USHRT_MAX
11499
    {"SC_USHRT_MAX",    _SC_USHRT_MAX},
11500
#endif
11501
#ifdef _SC_VERSION
11502
    {"SC_VERSION",      _SC_VERSION},
11503
#endif
11504
#ifdef _SC_WORD_BIT
11505
    {"SC_WORD_BIT",     _SC_WORD_BIT},
11506
#endif
11507
#ifdef _SC_XBS5_ILP32_OFF32
11508
    {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
11509
#endif
11510
#ifdef _SC_XBS5_ILP32_OFFBIG
11511
    {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
11512
#endif
11513
#ifdef _SC_XBS5_LP64_OFF64
11514
    {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
11515
#endif
11516
#ifdef _SC_XBS5_LPBIG_OFFBIG
11517
    {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
11518
#endif
11519
#ifdef _SC_XOPEN_CRYPT
11520
    {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
11521
#endif
11522
#ifdef _SC_XOPEN_ENH_I18N
11523
    {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
11524
#endif
11525
#ifdef _SC_XOPEN_LEGACY
11526
    {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
11527
#endif
11528
#ifdef _SC_XOPEN_REALTIME
11529
    {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
11530
#endif
11531
#ifdef _SC_XOPEN_REALTIME_THREADS
11532
    {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
11533
#endif
11534
#ifdef _SC_XOPEN_SHM
11535
    {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
11536
#endif
11537
#ifdef _SC_XOPEN_UNIX
11538
    {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
11539
#endif
11540
#ifdef _SC_XOPEN_VERSION
11541
    {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
11542
#endif
11543
#ifdef _SC_XOPEN_XCU_VERSION
11544
    {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
11545
#endif
11546
#ifdef _SC_XOPEN_XPG2
11547
    {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
11548
#endif
11549
#ifdef _SC_XOPEN_XPG3
11550
    {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
11551
#endif
11552
#ifdef _SC_XOPEN_XPG4
11553
    {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
11554
#endif
11555
};
11556
11557
static int
11558
conv_sysconf_confname(PyObject *arg, int *valuep)
11559
0
{
11560
0
    return conv_confname(arg, valuep, posix_constants_sysconf,
11561
0
                         sizeof(posix_constants_sysconf)
11562
0
                           / sizeof(struct constdef));
11563
0
}
11564
11565
11566
/*[clinic input]
11567
os.sysconf -> long
11568
    name: sysconf_confname
11569
    /
11570
11571
Return an integer-valued system configuration variable.
11572
[clinic start generated code]*/
11573
11574
static long
11575
os_sysconf_impl(PyObject *module, int name)
11576
/*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
11577
0
{
11578
0
    long value;
11579
11580
0
    errno = 0;
11581
0
    value = sysconf(name);
11582
0
    if (value == -1 && errno != 0)
11583
0
        posix_error();
11584
0
    return value;
11585
0
}
11586
#endif /* HAVE_SYSCONF */
11587
11588
11589
/* This code is used to ensure that the tables of configuration value names
11590
 * are in sorted order as required by conv_confname(), and also to build
11591
 * the exported dictionaries that are used to publish information about the
11592
 * names available on the host platform.
11593
 *
11594
 * Sorting the table at runtime ensures that the table is properly ordered
11595
 * when used, even for platforms we're not able to test on.  It also makes
11596
 * it easier to add additional entries to the tables.
11597
 */
11598
11599
static int
11600
cmp_constdefs(const void *v1,  const void *v2)
11601
7.93k
{
11602
7.93k
    const struct constdef *c1 =
11603
7.93k
    (const struct constdef *) v1;
11604
7.93k
    const struct constdef *c2 =
11605
7.93k
    (const struct constdef *) v2;
11606
11607
7.93k
    return strcmp(c1->name, c2->name);
11608
7.93k
}
11609
11610
static int
11611
setup_confname_table(struct constdef *table, size_t tablesize,
11612
                     const char *tablename, PyObject *module)
11613
42
{
11614
42
    PyObject *d = NULL;
11615
42
    size_t i;
11616
11617
42
    qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
11618
42
    d = PyDict_New();
11619
42
    if (d == NULL)
11620
0
        return -1;
11621
11622
2.57k
    for (i=0; i < tablesize; ++i) {
11623
2.53k
        PyObject *o = PyLong_FromLong(table[i].value);
11624
2.53k
        if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
11625
0
            Py_XDECREF(o);
11626
0
            Py_DECREF(d);
11627
0
            return -1;
11628
0
        }
11629
2.53k
        Py_DECREF(o);
11630
2.53k
    }
11631
42
    return PyModule_AddObject(module, tablename, d);
11632
42
}
11633
11634
/* Return -1 on failure, 0 on success. */
11635
static int
11636
setup_confname_tables(PyObject *module)
11637
14
{
11638
14
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
11639
14
    if (setup_confname_table(posix_constants_pathconf,
11640
14
                             sizeof(posix_constants_pathconf)
11641
14
                               / sizeof(struct constdef),
11642
14
                             "pathconf_names", module))
11643
0
        return -1;
11644
14
#endif
11645
14
#ifdef HAVE_CONFSTR
11646
14
    if (setup_confname_table(posix_constants_confstr,
11647
14
                             sizeof(posix_constants_confstr)
11648
14
                               / sizeof(struct constdef),
11649
14
                             "confstr_names", module))
11650
0
        return -1;
11651
14
#endif
11652
14
#ifdef HAVE_SYSCONF
11653
14
    if (setup_confname_table(posix_constants_sysconf,
11654
14
                             sizeof(posix_constants_sysconf)
11655
14
                               / sizeof(struct constdef),
11656
14
                             "sysconf_names", module))
11657
0
        return -1;
11658
14
#endif
11659
14
    return 0;
11660
14
}
11661
11662
11663
/*[clinic input]
11664
os.abort
11665
11666
Abort the interpreter immediately.
11667
11668
This function 'dumps core' or otherwise fails in the hardest way possible
11669
on the hosting operating system.  This function never returns.
11670
[clinic start generated code]*/
11671
11672
static PyObject *
11673
os_abort_impl(PyObject *module)
11674
/*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
11675
0
{
11676
0
    abort();
11677
    /*NOTREACHED*/
11678
#ifndef __clang__
11679
    /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
11680
       GCC emits a warning without "return NULL;" (compiler bug?), but Clang
11681
       is smarter and emits a warning on the return. */
11682
    Py_FatalError("abort() called from Python code didn't abort!");
11683
    return NULL;
11684
#endif
11685
0
}
11686
11687
#ifdef MS_WINDOWS
11688
/* Grab ShellExecute dynamically from shell32 */
11689
static int has_ShellExecute = -1;
11690
static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
11691
                                              LPCWSTR, INT);
11692
static int
11693
check_ShellExecute()
11694
{
11695
    HINSTANCE hShell32;
11696
11697
    /* only recheck */
11698
    if (-1 == has_ShellExecute) {
11699
        Py_BEGIN_ALLOW_THREADS
11700
        /* Security note: this call is not vulnerable to "DLL hijacking".
11701
           SHELL32 is part of "KnownDLLs" and so Windows always load
11702
           the system SHELL32.DLL, even if there is another SHELL32.DLL
11703
           in the DLL search path. */
11704
        hShell32 = LoadLibraryW(L"SHELL32");
11705
        if (hShell32) {
11706
            *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
11707
                                            "ShellExecuteW");
11708
            has_ShellExecute = Py_ShellExecuteW != NULL;
11709
        } else {
11710
            has_ShellExecute = 0;
11711
        }
11712
        Py_END_ALLOW_THREADS
11713
    }
11714
    return has_ShellExecute;
11715
}
11716
11717
11718
/*[clinic input]
11719
os.startfile
11720
    filepath: path_t
11721
    operation: Py_UNICODE = NULL
11722
11723
Start a file with its associated application.
11724
11725
When "operation" is not specified or "open", this acts like
11726
double-clicking the file in Explorer, or giving the file name as an
11727
argument to the DOS "start" command: the file is opened with whatever
11728
application (if any) its extension is associated.
11729
When another "operation" is given, it specifies what should be done with
11730
the file.  A typical operation is "print".
11731
11732
startfile returns as soon as the associated application is launched.
11733
There is no option to wait for the application to close, and no way
11734
to retrieve the application's exit status.
11735
11736
The filepath is relative to the current directory.  If you want to use
11737
an absolute path, make sure the first character is not a slash ("/");
11738
the underlying Win32 ShellExecute function doesn't work if it is.
11739
[clinic start generated code]*/
11740
11741
static PyObject *
11742
os_startfile_impl(PyObject *module, path_t *filepath,
11743
                  const Py_UNICODE *operation)
11744
/*[clinic end generated code: output=66dc311c94d50797 input=c940888a5390f039]*/
11745
{
11746
    HINSTANCE rc;
11747
11748
    if(!check_ShellExecute()) {
11749
        /* If the OS doesn't have ShellExecute, return a
11750
           NotImplementedError. */
11751
        return PyErr_Format(PyExc_NotImplementedError,
11752
            "startfile not available on this platform");
11753
    }
11754
11755
    if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
11756
        return NULL;
11757
    }
11758
11759
    Py_BEGIN_ALLOW_THREADS
11760
    rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
11761
                          NULL, NULL, SW_SHOWNORMAL);
11762
    Py_END_ALLOW_THREADS
11763
11764
    if (rc <= (HINSTANCE)32) {
11765
        win32_error_object("startfile", filepath->object);
11766
        return NULL;
11767
    }
11768
    Py_RETURN_NONE;
11769
}
11770
#endif /* MS_WINDOWS */
11771
11772
11773
#ifdef HAVE_GETLOADAVG
11774
/*[clinic input]
11775
os.getloadavg
11776
11777
Return average recent system load information.
11778
11779
Return the number of processes in the system run queue averaged over
11780
the last 1, 5, and 15 minutes as a tuple of three floats.
11781
Raises OSError if the load average was unobtainable.
11782
[clinic start generated code]*/
11783
11784
static PyObject *
11785
os_getloadavg_impl(PyObject *module)
11786
/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
11787
0
{
11788
0
    double loadavg[3];
11789
0
    if (getloadavg(loadavg, 3)!=3) {
11790
0
        PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
11791
0
        return NULL;
11792
0
    } else
11793
0
        return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
11794
0
}
11795
#endif /* HAVE_GETLOADAVG */
11796
11797
11798
/*[clinic input]
11799
os.device_encoding
11800
    fd: int
11801
11802
Return a string describing the encoding of a terminal's file descriptor.
11803
11804
The file descriptor must be attached to a terminal.
11805
If the device is not a terminal, return None.
11806
[clinic start generated code]*/
11807
11808
static PyObject *
11809
os_device_encoding_impl(PyObject *module, int fd)
11810
/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
11811
0
{
11812
0
    return _Py_device_encoding(fd);
11813
0
}
11814
11815
11816
#ifdef HAVE_SETRESUID
11817
/*[clinic input]
11818
os.setresuid
11819
11820
    ruid: uid_t
11821
    euid: uid_t
11822
    suid: uid_t
11823
    /
11824
11825
Set the current process's real, effective, and saved user ids.
11826
[clinic start generated code]*/
11827
11828
static PyObject *
11829
os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
11830
/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
11831
0
{
11832
0
    if (setresuid(ruid, euid, suid) < 0)
11833
0
        return posix_error();
11834
0
    Py_RETURN_NONE;
11835
0
}
11836
#endif /* HAVE_SETRESUID */
11837
11838
11839
#ifdef HAVE_SETRESGID
11840
/*[clinic input]
11841
os.setresgid
11842
11843
    rgid: gid_t
11844
    egid: gid_t
11845
    sgid: gid_t
11846
    /
11847
11848
Set the current process's real, effective, and saved group ids.
11849
[clinic start generated code]*/
11850
11851
static PyObject *
11852
os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
11853
/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
11854
0
{
11855
0
    if (setresgid(rgid, egid, sgid) < 0)
11856
0
        return posix_error();
11857
0
    Py_RETURN_NONE;
11858
0
}
11859
#endif /* HAVE_SETRESGID */
11860
11861
11862
#ifdef HAVE_GETRESUID
11863
/*[clinic input]
11864
os.getresuid
11865
11866
Return a tuple of the current process's real, effective, and saved user ids.
11867
[clinic start generated code]*/
11868
11869
static PyObject *
11870
os_getresuid_impl(PyObject *module)
11871
/*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
11872
0
{
11873
0
    uid_t ruid, euid, suid;
11874
0
    if (getresuid(&ruid, &euid, &suid) < 0)
11875
0
        return posix_error();
11876
0
    return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
11877
0
                                  _PyLong_FromUid(euid),
11878
0
                                  _PyLong_FromUid(suid));
11879
0
}
11880
#endif /* HAVE_GETRESUID */
11881
11882
11883
#ifdef HAVE_GETRESGID
11884
/*[clinic input]
11885
os.getresgid
11886
11887
Return a tuple of the current process's real, effective, and saved group ids.
11888
[clinic start generated code]*/
11889
11890
static PyObject *
11891
os_getresgid_impl(PyObject *module)
11892
/*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
11893
0
{
11894
0
    gid_t rgid, egid, sgid;
11895
0
    if (getresgid(&rgid, &egid, &sgid) < 0)
11896
0
        return posix_error();
11897
0
    return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
11898
0
                                  _PyLong_FromGid(egid),
11899
0
                                  _PyLong_FromGid(sgid));
11900
0
}
11901
#endif /* HAVE_GETRESGID */
11902
11903
11904
#ifdef USE_XATTRS
11905
/*[clinic input]
11906
os.getxattr
11907
11908
    path: path_t(allow_fd=True)
11909
    attribute: path_t
11910
    *
11911
    follow_symlinks: bool = True
11912
11913
Return the value of extended attribute attribute on path.
11914
11915
path may be either a string, a path-like object, or an open file descriptor.
11916
If follow_symlinks is False, and the last element of the path is a symbolic
11917
  link, getxattr will examine the symbolic link itself instead of the file
11918
  the link points to.
11919
11920
[clinic start generated code]*/
11921
11922
static PyObject *
11923
os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
11924
                 int follow_symlinks)
11925
/*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
11926
0
{
11927
0
    Py_ssize_t i;
11928
0
    PyObject *buffer = NULL;
11929
11930
0
    if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
11931
0
        return NULL;
11932
11933
0
    if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
11934
0
        return NULL;
11935
0
    }
11936
11937
0
    for (i = 0; ; i++) {
11938
0
        void *ptr;
11939
0
        ssize_t result;
11940
0
        static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
11941
0
        Py_ssize_t buffer_size = buffer_sizes[i];
11942
0
        if (!buffer_size) {
11943
0
            path_error(path);
11944
0
            return NULL;
11945
0
        }
11946
0
        buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
11947
0
        if (!buffer)
11948
0
            return NULL;
11949
0
        ptr = PyBytes_AS_STRING(buffer);
11950
11951
0
        Py_BEGIN_ALLOW_THREADS;
11952
0
        if (path->fd >= 0)
11953
0
            result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
11954
0
        else if (follow_symlinks)
11955
0
            result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
11956
0
        else
11957
0
            result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
11958
0
        Py_END_ALLOW_THREADS;
11959
11960
0
        if (result < 0) {
11961
0
            Py_DECREF(buffer);
11962
0
            if (errno == ERANGE)
11963
0
                continue;
11964
0
            path_error(path);
11965
0
            return NULL;
11966
0
        }
11967
11968
0
        if (result != buffer_size) {
11969
            /* Can only shrink. */
11970
0
            _PyBytes_Resize(&buffer, result);
11971
0
        }
11972
0
        break;
11973
0
    }
11974
11975
0
    return buffer;
11976
0
}
11977
11978
11979
/*[clinic input]
11980
os.setxattr
11981
11982
    path: path_t(allow_fd=True)
11983
    attribute: path_t
11984
    value: Py_buffer
11985
    flags: int = 0
11986
    *
11987
    follow_symlinks: bool = True
11988
11989
Set extended attribute attribute on path to value.
11990
11991
path may be either a string, a path-like object,  or an open file descriptor.
11992
If follow_symlinks is False, and the last element of the path is a symbolic
11993
  link, setxattr will modify the symbolic link itself instead of the file
11994
  the link points to.
11995
11996
[clinic start generated code]*/
11997
11998
static PyObject *
11999
os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12000
                 Py_buffer *value, int flags, int follow_symlinks)
12001
/*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
12002
0
{
12003
0
    ssize_t result;
12004
12005
0
    if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
12006
0
        return NULL;
12007
12008
0
    if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
12009
0
                    value->buf, value->len, flags) < 0) {
12010
0
        return NULL;
12011
0
    }
12012
12013
0
    Py_BEGIN_ALLOW_THREADS;
12014
0
    if (path->fd > -1)
12015
0
        result = fsetxattr(path->fd, attribute->narrow,
12016
0
                           value->buf, value->len, flags);
12017
0
    else if (follow_symlinks)
12018
0
        result = setxattr(path->narrow, attribute->narrow,
12019
0
                           value->buf, value->len, flags);
12020
0
    else
12021
0
        result = lsetxattr(path->narrow, attribute->narrow,
12022
0
                           value->buf, value->len, flags);
12023
0
    Py_END_ALLOW_THREADS;
12024
12025
0
    if (result) {
12026
0
        path_error(path);
12027
0
        return NULL;
12028
0
    }
12029
12030
0
    Py_RETURN_NONE;
12031
0
}
12032
12033
12034
/*[clinic input]
12035
os.removexattr
12036
12037
    path: path_t(allow_fd=True)
12038
    attribute: path_t
12039
    *
12040
    follow_symlinks: bool = True
12041
12042
Remove extended attribute attribute on path.
12043
12044
path may be either a string, a path-like object, or an open file descriptor.
12045
If follow_symlinks is False, and the last element of the path is a symbolic
12046
  link, removexattr will modify the symbolic link itself instead of the file
12047
  the link points to.
12048
12049
[clinic start generated code]*/
12050
12051
static PyObject *
12052
os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
12053
                    int follow_symlinks)
12054
/*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
12055
0
{
12056
0
    ssize_t result;
12057
12058
0
    if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
12059
0
        return NULL;
12060
12061
0
    if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
12062
0
        return NULL;
12063
0
    }
12064
12065
0
    Py_BEGIN_ALLOW_THREADS;
12066
0
    if (path->fd > -1)
12067
0
        result = fremovexattr(path->fd, attribute->narrow);
12068
0
    else if (follow_symlinks)
12069
0
        result = removexattr(path->narrow, attribute->narrow);
12070
0
    else
12071
0
        result = lremovexattr(path->narrow, attribute->narrow);
12072
0
    Py_END_ALLOW_THREADS;
12073
12074
0
    if (result) {
12075
0
        return path_error(path);
12076
0
    }
12077
12078
0
    Py_RETURN_NONE;
12079
0
}
12080
12081
12082
/*[clinic input]
12083
os.listxattr
12084
12085
    path: path_t(allow_fd=True, nullable=True) = None
12086
    *
12087
    follow_symlinks: bool = True
12088
12089
Return a list of extended attributes on path.
12090
12091
path may be either None, a string, a path-like object, or an open file descriptor.
12092
if path is None, listxattr will examine the current directory.
12093
If follow_symlinks is False, and the last element of the path is a symbolic
12094
  link, listxattr will examine the symbolic link itself instead of the file
12095
  the link points to.
12096
[clinic start generated code]*/
12097
12098
static PyObject *
12099
os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
12100
/*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
12101
0
{
12102
0
    Py_ssize_t i;
12103
0
    PyObject *result = NULL;
12104
0
    const char *name;
12105
0
    char *buffer = NULL;
12106
12107
0
    if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
12108
0
        goto exit;
12109
12110
0
    if (PySys_Audit("os.listxattr", "(O)",
12111
0
                    path->object ? path->object : Py_None) < 0) {
12112
0
        return NULL;
12113
0
    }
12114
12115
0
    name = path->narrow ? path->narrow : ".";
12116
12117
0
    for (i = 0; ; i++) {
12118
0
        const char *start, *trace, *end;
12119
0
        ssize_t length;
12120
0
        static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
12121
0
        Py_ssize_t buffer_size = buffer_sizes[i];
12122
0
        if (!buffer_size) {
12123
            /* ERANGE */
12124
0
            path_error(path);
12125
0
            break;
12126
0
        }
12127
0
        buffer = PyMem_MALLOC(buffer_size);
12128
0
        if (!buffer) {
12129
0
            PyErr_NoMemory();
12130
0
            break;
12131
0
        }
12132
12133
0
        Py_BEGIN_ALLOW_THREADS;
12134
0
        if (path->fd > -1)
12135
0
            length = flistxattr(path->fd, buffer, buffer_size);
12136
0
        else if (follow_symlinks)
12137
0
            length = listxattr(name, buffer, buffer_size);
12138
0
        else
12139
0
            length = llistxattr(name, buffer, buffer_size);
12140
0
        Py_END_ALLOW_THREADS;
12141
12142
0
        if (length < 0) {
12143
0
            if (errno == ERANGE) {
12144
0
                PyMem_FREE(buffer);
12145
0
                buffer = NULL;
12146
0
                continue;
12147
0
            }
12148
0
            path_error(path);
12149
0
            break;
12150
0
        }
12151
12152
0
        result = PyList_New(0);
12153
0
        if (!result) {
12154
0
            goto exit;
12155
0
        }
12156
12157
0
        end = buffer + length;
12158
0
        for (trace = start = buffer; trace != end; trace++) {
12159
0
            if (!*trace) {
12160
0
                int error;
12161
0
                PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
12162
0
                                                                 trace - start);
12163
0
                if (!attribute) {
12164
0
                    Py_DECREF(result);
12165
0
                    result = NULL;
12166
0
                    goto exit;
12167
0
                }
12168
0
                error = PyList_Append(result, attribute);
12169
0
                Py_DECREF(attribute);
12170
0
                if (error) {
12171
0
                    Py_DECREF(result);
12172
0
                    result = NULL;
12173
0
                    goto exit;
12174
0
                }
12175
0
                start = trace + 1;
12176
0
            }
12177
0
        }
12178
0
    break;
12179
0
    }
12180
0
exit:
12181
0
    if (buffer)
12182
0
        PyMem_FREE(buffer);
12183
0
    return result;
12184
0
}
12185
#endif /* USE_XATTRS */
12186
12187
12188
/*[clinic input]
12189
os.urandom
12190
12191
    size: Py_ssize_t
12192
    /
12193
12194
Return a bytes object containing random bytes suitable for cryptographic use.
12195
[clinic start generated code]*/
12196
12197
static PyObject *
12198
os_urandom_impl(PyObject *module, Py_ssize_t size)
12199
/*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
12200
0
{
12201
0
    PyObject *bytes;
12202
0
    int result;
12203
12204
0
    if (size < 0)
12205
0
        return PyErr_Format(PyExc_ValueError,
12206
0
                            "negative argument not allowed");
12207
0
    bytes = PyBytes_FromStringAndSize(NULL, size);
12208
0
    if (bytes == NULL)
12209
0
        return NULL;
12210
12211
0
    result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
12212
0
    if (result == -1) {
12213
0
        Py_DECREF(bytes);
12214
0
        return NULL;
12215
0
    }
12216
0
    return bytes;
12217
0
}
12218
12219
#ifdef HAVE_MEMFD_CREATE
12220
/*[clinic input]
12221
os.memfd_create
12222
12223
    name: FSConverter
12224
    flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
12225
12226
[clinic start generated code]*/
12227
12228
static PyObject *
12229
os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
12230
/*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
12231
0
{
12232
0
    int fd;
12233
0
    const char *bytes = PyBytes_AS_STRING(name);
12234
0
    Py_BEGIN_ALLOW_THREADS
12235
0
    fd = memfd_create(bytes, flags);
12236
0
    Py_END_ALLOW_THREADS
12237
0
    if (fd == -1) {
12238
0
        return PyErr_SetFromErrno(PyExc_OSError);
12239
0
    }
12240
0
    return PyLong_FromLong(fd);
12241
0
}
12242
#endif
12243
12244
/* Terminal size querying */
12245
12246
static PyTypeObject* TerminalSizeType;
12247
12248
PyDoc_STRVAR(TerminalSize_docstring,
12249
    "A tuple of (columns, lines) for holding terminal window size");
12250
12251
static PyStructSequence_Field TerminalSize_fields[] = {
12252
    {"columns", "width of the terminal window in characters"},
12253
    {"lines", "height of the terminal window in characters"},
12254
    {NULL, NULL}
12255
};
12256
12257
static PyStructSequence_Desc TerminalSize_desc = {
12258
    "os.terminal_size",
12259
    TerminalSize_docstring,
12260
    TerminalSize_fields,
12261
    2,
12262
};
12263
12264
#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
12265
/* AC 3.5: fd should accept None */
12266
PyDoc_STRVAR(termsize__doc__,
12267
    "Return the size of the terminal window as (columns, lines).\n"        \
12268
    "\n"                                                                   \
12269
    "The optional argument fd (default standard output) specifies\n"       \
12270
    "which file descriptor should be queried.\n"                           \
12271
    "\n"                                                                   \
12272
    "If the file descriptor is not connected to a terminal, an OSError\n"  \
12273
    "is thrown.\n"                                                         \
12274
    "\n"                                                                   \
12275
    "This function will only be defined if an implementation is\n"         \
12276
    "available for this system.\n"                                         \
12277
    "\n"                                                                   \
12278
    "shutil.get_terminal_size is the high-level function which should\n"  \
12279
    "normally be used, os.get_terminal_size is the low-level implementation.");
12280
12281
static PyObject*
12282
get_terminal_size(PyObject *self, PyObject *args)
12283
0
{
12284
0
    int columns, lines;
12285
0
    PyObject *termsize;
12286
12287
0
    int fd = fileno(stdout);
12288
    /* Under some conditions stdout may not be connected and
12289
     * fileno(stdout) may point to an invalid file descriptor. For example
12290
     * GUI apps don't have valid standard streams by default.
12291
     *
12292
     * If this happens, and the optional fd argument is not present,
12293
     * the ioctl below will fail returning EBADF. This is what we want.
12294
     */
12295
12296
0
    if (!PyArg_ParseTuple(args, "|i", &fd))
12297
0
        return NULL;
12298
12299
0
#ifdef TERMSIZE_USE_IOCTL
12300
0
    {
12301
0
        struct winsize w;
12302
0
        if (ioctl(fd, TIOCGWINSZ, &w))
12303
0
            return PyErr_SetFromErrno(PyExc_OSError);
12304
0
        columns = w.ws_col;
12305
0
        lines = w.ws_row;
12306
0
    }
12307
0
#endif /* TERMSIZE_USE_IOCTL */
12308
12309
#ifdef TERMSIZE_USE_CONIO
12310
    {
12311
        DWORD nhandle;
12312
        HANDLE handle;
12313
        CONSOLE_SCREEN_BUFFER_INFO csbi;
12314
        switch (fd) {
12315
        case 0: nhandle = STD_INPUT_HANDLE;
12316
            break;
12317
        case 1: nhandle = STD_OUTPUT_HANDLE;
12318
            break;
12319
        case 2: nhandle = STD_ERROR_HANDLE;
12320
            break;
12321
        default:
12322
            return PyErr_Format(PyExc_ValueError, "bad file descriptor");
12323
        }
12324
        handle = GetStdHandle(nhandle);
12325
        if (handle == NULL)
12326
            return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
12327
        if (handle == INVALID_HANDLE_VALUE)
12328
            return PyErr_SetFromWindowsErr(0);
12329
12330
        if (!GetConsoleScreenBufferInfo(handle, &csbi))
12331
            return PyErr_SetFromWindowsErr(0);
12332
12333
        columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
12334
        lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
12335
    }
12336
#endif /* TERMSIZE_USE_CONIO */
12337
12338
0
    termsize = PyStructSequence_New(TerminalSizeType);
12339
0
    if (termsize == NULL)
12340
0
        return NULL;
12341
0
    PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
12342
0
    PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
12343
0
    if (PyErr_Occurred()) {
12344
0
        Py_DECREF(termsize);
12345
0
        return NULL;
12346
0
    }
12347
0
    return termsize;
12348
0
}
12349
#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
12350
12351
12352
/*[clinic input]
12353
os.cpu_count
12354
12355
Return the number of CPUs in the system; return None if indeterminable.
12356
12357
This number is not equivalent to the number of CPUs the current process can
12358
use.  The number of usable CPUs can be obtained with
12359
``len(os.sched_getaffinity(0))``
12360
[clinic start generated code]*/
12361
12362
static PyObject *
12363
os_cpu_count_impl(PyObject *module)
12364
/*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
12365
0
{
12366
0
    int ncpu = 0;
12367
#ifdef MS_WINDOWS
12368
    /* Declare prototype here to avoid pulling in all of the Win7 APIs in 3.8 */
12369
    DWORD WINAPI GetActiveProcessorCount(WORD group);
12370
    ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
12371
#elif defined(__hpux)
12372
    ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
12373
#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
12374
    ncpu = sysconf(_SC_NPROCESSORS_ONLN);
12375
#elif defined(__DragonFly__) || \
12376
      defined(__OpenBSD__)   || \
12377
      defined(__FreeBSD__)   || \
12378
      defined(__NetBSD__)    || \
12379
      defined(__APPLE__)
12380
    int mib[2];
12381
    size_t len = sizeof(ncpu);
12382
    mib[0] = CTL_HW;
12383
    mib[1] = HW_NCPU;
12384
    if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
12385
        ncpu = 0;
12386
#endif
12387
0
    if (ncpu >= 1)
12388
0
        return PyLong_FromLong(ncpu);
12389
0
    else
12390
0
        Py_RETURN_NONE;
12391
0
}
12392
12393
12394
/*[clinic input]
12395
os.get_inheritable -> bool
12396
12397
    fd: int
12398
    /
12399
12400
Get the close-on-exe flag of the specified file descriptor.
12401
[clinic start generated code]*/
12402
12403
static int
12404
os_get_inheritable_impl(PyObject *module, int fd)
12405
/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
12406
0
{
12407
0
    int return_value;
12408
0
    _Py_BEGIN_SUPPRESS_IPH
12409
0
    return_value = _Py_get_inheritable(fd);
12410
0
    _Py_END_SUPPRESS_IPH
12411
0
    return return_value;
12412
0
}
12413
12414
12415
/*[clinic input]
12416
os.set_inheritable
12417
    fd: int
12418
    inheritable: int
12419
    /
12420
12421
Set the inheritable flag of the specified file descriptor.
12422
[clinic start generated code]*/
12423
12424
static PyObject *
12425
os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
12426
/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
12427
0
{
12428
0
    int result;
12429
12430
0
    _Py_BEGIN_SUPPRESS_IPH
12431
0
    result = _Py_set_inheritable(fd, inheritable, NULL);
12432
0
    _Py_END_SUPPRESS_IPH
12433
0
    if (result < 0)
12434
0
        return NULL;
12435
0
    Py_RETURN_NONE;
12436
0
}
12437
12438
12439
#ifdef MS_WINDOWS
12440
/*[clinic input]
12441
os.get_handle_inheritable -> bool
12442
    handle: intptr_t
12443
    /
12444
12445
Get the close-on-exe flag of the specified file descriptor.
12446
[clinic start generated code]*/
12447
12448
static int
12449
os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
12450
/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
12451
{
12452
    DWORD flags;
12453
12454
    if (!GetHandleInformation((HANDLE)handle, &flags)) {
12455
        PyErr_SetFromWindowsErr(0);
12456
        return -1;
12457
    }
12458
12459
    return flags & HANDLE_FLAG_INHERIT;
12460
}
12461
12462
12463
/*[clinic input]
12464
os.set_handle_inheritable
12465
    handle: intptr_t
12466
    inheritable: bool
12467
    /
12468
12469
Set the inheritable flag of the specified handle.
12470
[clinic start generated code]*/
12471
12472
static PyObject *
12473
os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
12474
                               int inheritable)
12475
/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
12476
{
12477
    DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
12478
    if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
12479
        PyErr_SetFromWindowsErr(0);
12480
        return NULL;
12481
    }
12482
    Py_RETURN_NONE;
12483
}
12484
#endif /* MS_WINDOWS */
12485
12486
#ifndef MS_WINDOWS
12487
/*[clinic input]
12488
os.get_blocking -> bool
12489
    fd: int
12490
    /
12491
12492
Get the blocking mode of the file descriptor.
12493
12494
Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
12495
[clinic start generated code]*/
12496
12497
static int
12498
os_get_blocking_impl(PyObject *module, int fd)
12499
/*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
12500
0
{
12501
0
    int blocking;
12502
12503
0
    _Py_BEGIN_SUPPRESS_IPH
12504
0
    blocking = _Py_get_blocking(fd);
12505
0
    _Py_END_SUPPRESS_IPH
12506
0
    return blocking;
12507
0
}
12508
12509
/*[clinic input]
12510
os.set_blocking
12511
    fd: int
12512
    blocking: bool(accept={int})
12513
    /
12514
12515
Set the blocking mode of the specified file descriptor.
12516
12517
Set the O_NONBLOCK flag if blocking is False,
12518
clear the O_NONBLOCK flag otherwise.
12519
[clinic start generated code]*/
12520
12521
static PyObject *
12522
os_set_blocking_impl(PyObject *module, int fd, int blocking)
12523
/*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/
12524
0
{
12525
0
    int result;
12526
12527
0
    _Py_BEGIN_SUPPRESS_IPH
12528
0
    result = _Py_set_blocking(fd, blocking);
12529
0
    _Py_END_SUPPRESS_IPH
12530
0
    if (result < 0)
12531
0
        return NULL;
12532
0
    Py_RETURN_NONE;
12533
0
}
12534
#endif   /* !MS_WINDOWS */
12535
12536
12537
/*[clinic input]
12538
class os.DirEntry "DirEntry *" "&DirEntryType"
12539
[clinic start generated code]*/
12540
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3138f09f7c683f1d]*/
12541
12542
typedef struct {
12543
    PyObject_HEAD
12544
    PyObject *name;
12545
    PyObject *path;
12546
    PyObject *stat;
12547
    PyObject *lstat;
12548
#ifdef MS_WINDOWS
12549
    struct _Py_stat_struct win32_lstat;
12550
    uint64_t win32_file_index;
12551
    int got_file_index;
12552
#else /* POSIX */
12553
#ifdef HAVE_DIRENT_D_TYPE
12554
    unsigned char d_type;
12555
#endif
12556
    ino_t d_ino;
12557
    int dir_fd;
12558
#endif
12559
} DirEntry;
12560
12561
static void
12562
DirEntry_dealloc(DirEntry *entry)
12563
0
{
12564
0
    Py_XDECREF(entry->name);
12565
0
    Py_XDECREF(entry->path);
12566
0
    Py_XDECREF(entry->stat);
12567
0
    Py_XDECREF(entry->lstat);
12568
0
    Py_TYPE(entry)->tp_free((PyObject *)entry);
12569
0
}
12570
12571
/* Forward reference */
12572
static int
12573
DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits);
12574
12575
/*[clinic input]
12576
os.DirEntry.is_symlink -> bool
12577
12578
Return True if the entry is a symbolic link; cached per entry.
12579
[clinic start generated code]*/
12580
12581
static int
12582
os_DirEntry_is_symlink_impl(DirEntry *self)
12583
/*[clinic end generated code: output=42244667d7bcfc25 input=1605a1b4b96976c3]*/
12584
0
{
12585
#ifdef MS_WINDOWS
12586
    return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
12587
#elif defined(HAVE_DIRENT_D_TYPE)
12588
    /* POSIX */
12589
0
    if (self->d_type != DT_UNKNOWN)
12590
0
        return self->d_type == DT_LNK;
12591
0
    else
12592
0
        return DirEntry_test_mode(self, 0, S_IFLNK);
12593
#else
12594
    /* POSIX without d_type */
12595
    return DirEntry_test_mode(self, 0, S_IFLNK);
12596
#endif
12597
0
}
12598
12599
static PyObject *
12600
DirEntry_fetch_stat(DirEntry *self, int follow_symlinks)
12601
0
{
12602
0
    int result;
12603
0
    STRUCT_STAT st;
12604
0
    PyObject *ub;
12605
12606
#ifdef MS_WINDOWS
12607
    if (!PyUnicode_FSDecoder(self->path, &ub))
12608
        return NULL;
12609
    const wchar_t *path = PyUnicode_AsUnicode(ub);
12610
#else /* POSIX */
12611
0
    if (!PyUnicode_FSConverter(self->path, &ub))
12612
0
        return NULL;
12613
0
    const char *path = PyBytes_AS_STRING(ub);
12614
0
    if (self->dir_fd != DEFAULT_DIR_FD) {
12615
0
#ifdef HAVE_FSTATAT
12616
0
        result = fstatat(self->dir_fd, path, &st,
12617
0
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
12618
#else
12619
        PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
12620
        return NULL;
12621
#endif /* HAVE_FSTATAT */
12622
0
    }
12623
0
    else
12624
0
#endif
12625
0
    {
12626
0
        if (follow_symlinks)
12627
0
            result = STAT(path, &st);
12628
0
        else
12629
0
            result = LSTAT(path, &st);
12630
0
    }
12631
0
    Py_DECREF(ub);
12632
12633
0
    if (result != 0)
12634
0
        return path_object_error(self->path);
12635
12636
0
    return _pystat_fromstructstat(&st);
12637
0
}
12638
12639
static PyObject *
12640
DirEntry_get_lstat(DirEntry *self)
12641
0
{
12642
0
    if (!self->lstat) {
12643
#ifdef MS_WINDOWS
12644
        self->lstat = _pystat_fromstructstat(&self->win32_lstat);
12645
#else /* POSIX */
12646
0
        self->lstat = DirEntry_fetch_stat(self, 0);
12647
0
#endif
12648
0
    }
12649
0
    Py_XINCREF(self->lstat);
12650
0
    return self->lstat;
12651
0
}
12652
12653
/*[clinic input]
12654
os.DirEntry.stat
12655
    *
12656
    follow_symlinks: bool = True
12657
12658
Return stat_result object for the entry; cached per entry.
12659
[clinic start generated code]*/
12660
12661
static PyObject *
12662
os_DirEntry_stat_impl(DirEntry *self, int follow_symlinks)
12663
/*[clinic end generated code: output=008593b3a6d01305 input=280d14c1d6f1d00d]*/
12664
0
{
12665
0
    if (!follow_symlinks)
12666
0
        return DirEntry_get_lstat(self);
12667
12668
0
    if (!self->stat) {
12669
0
        int result = os_DirEntry_is_symlink_impl(self);
12670
0
        if (result == -1)
12671
0
            return NULL;
12672
0
        else if (result)
12673
0
            self->stat = DirEntry_fetch_stat(self, 1);
12674
0
        else
12675
0
            self->stat = DirEntry_get_lstat(self);
12676
0
    }
12677
12678
0
    Py_XINCREF(self->stat);
12679
0
    return self->stat;
12680
0
}
12681
12682
/* Set exception and return -1 on error, 0 for False, 1 for True */
12683
static int
12684
DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits)
12685
0
{
12686
0
    PyObject *stat = NULL;
12687
0
    PyObject *st_mode = NULL;
12688
0
    long mode;
12689
0
    int result;
12690
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
12691
0
    int is_symlink;
12692
0
    int need_stat;
12693
0
#endif
12694
#ifdef MS_WINDOWS
12695
    unsigned long dir_bits;
12696
#endif
12697
0
    _Py_IDENTIFIER(st_mode);
12698
12699
#ifdef MS_WINDOWS
12700
    is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
12701
    need_stat = follow_symlinks && is_symlink;
12702
#elif defined(HAVE_DIRENT_D_TYPE)
12703
    is_symlink = self->d_type == DT_LNK;
12704
0
    need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
12705
0
#endif
12706
12707
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
12708
0
    if (need_stat) {
12709
0
#endif
12710
0
        stat = os_DirEntry_stat_impl(self, follow_symlinks);
12711
0
        if (!stat) {
12712
0
            if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
12713
                /* If file doesn't exist (anymore), then return False
12714
                   (i.e., say it's not a file/directory) */
12715
0
                PyErr_Clear();
12716
0
                return 0;
12717
0
            }
12718
0
            goto error;
12719
0
        }
12720
0
        st_mode = _PyObject_GetAttrId(stat, &PyId_st_mode);
12721
0
        if (!st_mode)
12722
0
            goto error;
12723
12724
0
        mode = PyLong_AsLong(st_mode);
12725
0
        if (mode == -1 && PyErr_Occurred())
12726
0
            goto error;
12727
0
        Py_CLEAR(st_mode);
12728
0
        Py_CLEAR(stat);
12729
0
        result = (mode & S_IFMT) == mode_bits;
12730
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
12731
0
    }
12732
0
    else if (is_symlink) {
12733
0
        assert(mode_bits != S_IFLNK);
12734
0
        result = 0;
12735
0
    }
12736
0
    else {
12737
0
        assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
12738
#ifdef MS_WINDOWS
12739
        dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
12740
        if (mode_bits == S_IFDIR)
12741
            result = dir_bits != 0;
12742
        else
12743
            result = dir_bits == 0;
12744
#else /* POSIX */
12745
0
        if (mode_bits == S_IFDIR)
12746
0
            result = self->d_type == DT_DIR;
12747
0
        else
12748
0
            result = self->d_type == DT_REG;
12749
0
#endif
12750
0
    }
12751
0
#endif
12752
12753
0
    return result;
12754
12755
0
error:
12756
0
    Py_XDECREF(st_mode);
12757
0
    Py_XDECREF(stat);
12758
0
    return -1;
12759
0
}
12760
12761
/*[clinic input]
12762
os.DirEntry.is_dir -> bool
12763
    *
12764
    follow_symlinks: bool = True
12765
12766
Return True if the entry is a directory; cached per entry.
12767
[clinic start generated code]*/
12768
12769
static int
12770
os_DirEntry_is_dir_impl(DirEntry *self, int follow_symlinks)
12771
/*[clinic end generated code: output=ad2e8d54365da287 input=0135232766f53f58]*/
12772
0
{
12773
0
    return DirEntry_test_mode(self, follow_symlinks, S_IFDIR);
12774
0
}
12775
12776
/*[clinic input]
12777
os.DirEntry.is_file -> bool
12778
    *
12779
    follow_symlinks: bool = True
12780
12781
Return True if the entry is a file; cached per entry.
12782
[clinic start generated code]*/
12783
12784
static int
12785
os_DirEntry_is_file_impl(DirEntry *self, int follow_symlinks)
12786
/*[clinic end generated code: output=8462ade481d8a476 input=0dc90be168b041ee]*/
12787
0
{
12788
0
    return DirEntry_test_mode(self, follow_symlinks, S_IFREG);
12789
0
}
12790
12791
/*[clinic input]
12792
os.DirEntry.inode
12793
12794
Return inode of the entry; cached per entry.
12795
[clinic start generated code]*/
12796
12797
static PyObject *
12798
os_DirEntry_inode_impl(DirEntry *self)
12799
/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
12800
0
{
12801
#ifdef MS_WINDOWS
12802
    if (!self->got_file_index) {
12803
        PyObject *unicode;
12804
        const wchar_t *path;
12805
        STRUCT_STAT stat;
12806
        int result;
12807
12808
        if (!PyUnicode_FSDecoder(self->path, &unicode))
12809
            return NULL;
12810
        path = PyUnicode_AsUnicode(unicode);
12811
        result = LSTAT(path, &stat);
12812
        Py_DECREF(unicode);
12813
12814
        if (result != 0)
12815
            return path_object_error(self->path);
12816
12817
        self->win32_file_index = stat.st_ino;
12818
        self->got_file_index = 1;
12819
    }
12820
    Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->win32_file_index));
12821
    return PyLong_FromUnsignedLongLong(self->win32_file_index);
12822
#else /* POSIX */
12823
0
    Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->d_ino));
12824
0
    return PyLong_FromUnsignedLongLong(self->d_ino);
12825
0
#endif
12826
0
}
12827
12828
static PyObject *
12829
DirEntry_repr(DirEntry *self)
12830
0
{
12831
0
    return PyUnicode_FromFormat("<DirEntry %R>", self->name);
12832
0
}
12833
12834
/*[clinic input]
12835
os.DirEntry.__fspath__
12836
12837
Returns the path for the entry.
12838
[clinic start generated code]*/
12839
12840
static PyObject *
12841
os_DirEntry___fspath___impl(DirEntry *self)
12842
/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
12843
0
{
12844
0
    Py_INCREF(self->path);
12845
0
    return self->path;
12846
0
}
12847
12848
static PyMemberDef DirEntry_members[] = {
12849
    {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
12850
     "the entry's base filename, relative to scandir() \"path\" argument"},
12851
    {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
12852
     "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
12853
    {NULL}
12854
};
12855
12856
#include "clinic/posixmodule.c.h"
12857
12858
static PyMethodDef DirEntry_methods[] = {
12859
    OS_DIRENTRY_IS_DIR_METHODDEF
12860
    OS_DIRENTRY_IS_FILE_METHODDEF
12861
    OS_DIRENTRY_IS_SYMLINK_METHODDEF
12862
    OS_DIRENTRY_STAT_METHODDEF
12863
    OS_DIRENTRY_INODE_METHODDEF
12864
    OS_DIRENTRY___FSPATH___METHODDEF
12865
    {NULL}
12866
};
12867
12868
static PyTypeObject DirEntryType = {
12869
    PyVarObject_HEAD_INIT(NULL, 0)
12870
    MODNAME ".DirEntry",                    /* tp_name */
12871
    sizeof(DirEntry),                       /* tp_basicsize */
12872
    0,                                      /* tp_itemsize */
12873
    /* methods */
12874
    (destructor)DirEntry_dealloc,           /* tp_dealloc */
12875
    0,                                      /* tp_vectorcall_offset */
12876
    0,                                      /* tp_getattr */
12877
    0,                                      /* tp_setattr */
12878
    0,                                      /* tp_as_async */
12879
    (reprfunc)DirEntry_repr,                /* tp_repr */
12880
    0,                                      /* tp_as_number */
12881
    0,                                      /* tp_as_sequence */
12882
    0,                                      /* tp_as_mapping */
12883
    0,                                      /* tp_hash */
12884
    0,                                      /* tp_call */
12885
    0,                                      /* tp_str */
12886
    0,                                      /* tp_getattro */
12887
    0,                                      /* tp_setattro */
12888
    0,                                      /* tp_as_buffer */
12889
    Py_TPFLAGS_DEFAULT,                     /* tp_flags */
12890
    0,                                      /* tp_doc */
12891
    0,                                      /* tp_traverse */
12892
    0,                                      /* tp_clear */
12893
    0,                                      /* tp_richcompare */
12894
    0,                                      /* tp_weaklistoffset */
12895
    0,                                      /* tp_iter */
12896
    0,                                      /* tp_iternext */
12897
    DirEntry_methods,                       /* tp_methods */
12898
    DirEntry_members,                       /* tp_members */
12899
};
12900
12901
#ifdef MS_WINDOWS
12902
12903
static wchar_t *
12904
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
12905
{
12906
    Py_ssize_t path_len;
12907
    Py_ssize_t size;
12908
    wchar_t *result;
12909
    wchar_t ch;
12910
12911
    if (!path_wide) { /* Default arg: "." */
12912
        path_wide = L".";
12913
        path_len = 1;
12914
    }
12915
    else {
12916
        path_len = wcslen(path_wide);
12917
    }
12918
12919
    /* The +1's are for the path separator and the NUL */
12920
    size = path_len + 1 + wcslen(filename) + 1;
12921
    result = PyMem_New(wchar_t, size);
12922
    if (!result) {
12923
        PyErr_NoMemory();
12924
        return NULL;
12925
    }
12926
    wcscpy(result, path_wide);
12927
    if (path_len > 0) {
12928
        ch = result[path_len - 1];
12929
        if (ch != SEP && ch != ALTSEP && ch != L':')
12930
            result[path_len++] = SEP;
12931
        wcscpy(result + path_len, filename);
12932
    }
12933
    return result;
12934
}
12935
12936
static PyObject *
12937
DirEntry_from_find_data(path_t *path, WIN32_FIND_DATAW *dataW)
12938
{
12939
    DirEntry *entry;
12940
    BY_HANDLE_FILE_INFORMATION file_info;
12941
    ULONG reparse_tag;
12942
    wchar_t *joined_path;
12943
12944
    entry = PyObject_New(DirEntry, &DirEntryType);
12945
    if (!entry)
12946
        return NULL;
12947
    entry->name = NULL;
12948
    entry->path = NULL;
12949
    entry->stat = NULL;
12950
    entry->lstat = NULL;
12951
    entry->got_file_index = 0;
12952
12953
    entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
12954
    if (!entry->name)
12955
        goto error;
12956
    if (path->narrow) {
12957
        Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
12958
        if (!entry->name)
12959
            goto error;
12960
    }
12961
12962
    joined_path = join_path_filenameW(path->wide, dataW->cFileName);
12963
    if (!joined_path)
12964
        goto error;
12965
12966
    entry->path = PyUnicode_FromWideChar(joined_path, -1);
12967
    PyMem_Free(joined_path);
12968
    if (!entry->path)
12969
        goto error;
12970
    if (path->narrow) {
12971
        Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
12972
        if (!entry->path)
12973
            goto error;
12974
    }
12975
12976
    find_data_to_file_info(dataW, &file_info, &reparse_tag);
12977
    _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
12978
12979
    return (PyObject *)entry;
12980
12981
error:
12982
    Py_DECREF(entry);
12983
    return NULL;
12984
}
12985
12986
#else /* POSIX */
12987
12988
static char *
12989
join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
12990
0
{
12991
0
    Py_ssize_t path_len;
12992
0
    Py_ssize_t size;
12993
0
    char *result;
12994
12995
0
    if (!path_narrow) { /* Default arg: "." */
12996
0
        path_narrow = ".";
12997
0
        path_len = 1;
12998
0
    }
12999
0
    else {
13000
0
        path_len = strlen(path_narrow);
13001
0
    }
13002
13003
0
    if (filename_len == -1)
13004
0
        filename_len = strlen(filename);
13005
13006
    /* The +1's are for the path separator and the NUL */
13007
0
    size = path_len + 1 + filename_len + 1;
13008
0
    result = PyMem_New(char, size);
13009
0
    if (!result) {
13010
0
        PyErr_NoMemory();
13011
0
        return NULL;
13012
0
    }
13013
0
    strcpy(result, path_narrow);
13014
0
    if (path_len > 0 && result[path_len - 1] != '/')
13015
0
        result[path_len++] = '/';
13016
0
    strcpy(result + path_len, filename);
13017
0
    return result;
13018
0
}
13019
13020
static PyObject *
13021
DirEntry_from_posix_info(path_t *path, const char *name, Py_ssize_t name_len,
13022
                         ino_t d_ino
13023
#ifdef HAVE_DIRENT_D_TYPE
13024
                         , unsigned char d_type
13025
#endif
13026
                         )
13027
0
{
13028
0
    DirEntry *entry;
13029
0
    char *joined_path;
13030
13031
0
    entry = PyObject_New(DirEntry, &DirEntryType);
13032
0
    if (!entry)
13033
0
        return NULL;
13034
0
    entry->name = NULL;
13035
0
    entry->path = NULL;
13036
0
    entry->stat = NULL;
13037
0
    entry->lstat = NULL;
13038
13039
0
    if (path->fd != -1) {
13040
0
        entry->dir_fd = path->fd;
13041
0
        joined_path = NULL;
13042
0
    }
13043
0
    else {
13044
0
        entry->dir_fd = DEFAULT_DIR_FD;
13045
0
        joined_path = join_path_filename(path->narrow, name, name_len);
13046
0
        if (!joined_path)
13047
0
            goto error;
13048
0
    }
13049
13050
0
    if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
13051
0
        entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
13052
0
        if (joined_path)
13053
0
            entry->path = PyUnicode_DecodeFSDefault(joined_path);
13054
0
    }
13055
0
    else {
13056
0
        entry->name = PyBytes_FromStringAndSize(name, name_len);
13057
0
        if (joined_path)
13058
0
            entry->path = PyBytes_FromString(joined_path);
13059
0
    }
13060
0
    PyMem_Free(joined_path);
13061
0
    if (!entry->name)
13062
0
        goto error;
13063
13064
0
    if (path->fd != -1) {
13065
0
        entry->path = entry->name;
13066
0
        Py_INCREF(entry->path);
13067
0
    }
13068
0
    else if (!entry->path)
13069
0
        goto error;
13070
13071
0
#ifdef HAVE_DIRENT_D_TYPE
13072
0
    entry->d_type = d_type;
13073
0
#endif
13074
0
    entry->d_ino = d_ino;
13075
13076
0
    return (PyObject *)entry;
13077
13078
0
error:
13079
0
    Py_XDECREF(entry);
13080
0
    return NULL;
13081
0
}
13082
13083
#endif
13084
13085
13086
typedef struct {
13087
    PyObject_HEAD
13088
    path_t path;
13089
#ifdef MS_WINDOWS
13090
    HANDLE handle;
13091
    WIN32_FIND_DATAW file_data;
13092
    int first_time;
13093
#else /* POSIX */
13094
    DIR *dirp;
13095
#endif
13096
#ifdef HAVE_FDOPENDIR
13097
    int fd;
13098
#endif
13099
} ScandirIterator;
13100
13101
#ifdef MS_WINDOWS
13102
13103
static int
13104
ScandirIterator_is_closed(ScandirIterator *iterator)
13105
{
13106
    return iterator->handle == INVALID_HANDLE_VALUE;
13107
}
13108
13109
static void
13110
ScandirIterator_closedir(ScandirIterator *iterator)
13111
{
13112
    HANDLE handle = iterator->handle;
13113
13114
    if (handle == INVALID_HANDLE_VALUE)
13115
        return;
13116
13117
    iterator->handle = INVALID_HANDLE_VALUE;
13118
    Py_BEGIN_ALLOW_THREADS
13119
    FindClose(handle);
13120
    Py_END_ALLOW_THREADS
13121
}
13122
13123
static PyObject *
13124
ScandirIterator_iternext(ScandirIterator *iterator)
13125
{
13126
    WIN32_FIND_DATAW *file_data = &iterator->file_data;
13127
    BOOL success;
13128
    PyObject *entry;
13129
13130
    /* Happens if the iterator is iterated twice, or closed explicitly */
13131
    if (iterator->handle == INVALID_HANDLE_VALUE)
13132
        return NULL;
13133
13134
    while (1) {
13135
        if (!iterator->first_time) {
13136
            Py_BEGIN_ALLOW_THREADS
13137
            success = FindNextFileW(iterator->handle, file_data);
13138
            Py_END_ALLOW_THREADS
13139
            if (!success) {
13140
                /* Error or no more files */
13141
                if (GetLastError() != ERROR_NO_MORE_FILES)
13142
                    path_error(&iterator->path);
13143
                break;
13144
            }
13145
        }
13146
        iterator->first_time = 0;
13147
13148
        /* Skip over . and .. */
13149
        if (wcscmp(file_data->cFileName, L".") != 0 &&
13150
            wcscmp(file_data->cFileName, L"..") != 0) {
13151
            entry = DirEntry_from_find_data(&iterator->path, file_data);
13152
            if (!entry)
13153
                break;
13154
            return entry;
13155
        }
13156
13157
        /* Loop till we get a non-dot directory or finish iterating */
13158
    }
13159
13160
    /* Error or no more files */
13161
    ScandirIterator_closedir(iterator);
13162
    return NULL;
13163
}
13164
13165
#else /* POSIX */
13166
13167
static int
13168
ScandirIterator_is_closed(ScandirIterator *iterator)
13169
0
{
13170
0
    return !iterator->dirp;
13171
0
}
13172
13173
static void
13174
ScandirIterator_closedir(ScandirIterator *iterator)
13175
0
{
13176
0
    DIR *dirp = iterator->dirp;
13177
13178
0
    if (!dirp)
13179
0
        return;
13180
13181
0
    iterator->dirp = NULL;
13182
0
    Py_BEGIN_ALLOW_THREADS
13183
0
#ifdef HAVE_FDOPENDIR
13184
0
    if (iterator->path.fd != -1)
13185
0
        rewinddir(dirp);
13186
0
#endif
13187
0
    closedir(dirp);
13188
0
    Py_END_ALLOW_THREADS
13189
0
    return;
13190
0
}
13191
13192
static PyObject *
13193
ScandirIterator_iternext(ScandirIterator *iterator)
13194
0
{
13195
0
    struct dirent *direntp;
13196
0
    Py_ssize_t name_len;
13197
0
    int is_dot;
13198
0
    PyObject *entry;
13199
13200
    /* Happens if the iterator is iterated twice, or closed explicitly */
13201
0
    if (!iterator->dirp)
13202
0
        return NULL;
13203
13204
0
    while (1) {
13205
0
        errno = 0;
13206
0
        Py_BEGIN_ALLOW_THREADS
13207
0
        direntp = readdir(iterator->dirp);
13208
0
        Py_END_ALLOW_THREADS
13209
13210
0
        if (!direntp) {
13211
            /* Error or no more files */
13212
0
            if (errno != 0)
13213
0
                path_error(&iterator->path);
13214
0
            break;
13215
0
        }
13216
13217
        /* Skip over . and .. */
13218
0
        name_len = NAMLEN(direntp);
13219
0
        is_dot = direntp->d_name[0] == '.' &&
13220
0
                 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
13221
0
        if (!is_dot) {
13222
0
            entry = DirEntry_from_posix_info(&iterator->path, direntp->d_name,
13223
0
                                            name_len, direntp->d_ino
13224
0
#ifdef HAVE_DIRENT_D_TYPE
13225
0
                                            , direntp->d_type
13226
0
#endif
13227
0
                                            );
13228
0
            if (!entry)
13229
0
                break;
13230
0
            return entry;
13231
0
        }
13232
13233
        /* Loop till we get a non-dot directory or finish iterating */
13234
0
    }
13235
13236
    /* Error or no more files */
13237
0
    ScandirIterator_closedir(iterator);
13238
0
    return NULL;
13239
0
}
13240
13241
#endif
13242
13243
static PyObject *
13244
ScandirIterator_close(ScandirIterator *self, PyObject *args)
13245
0
{
13246
0
    ScandirIterator_closedir(self);
13247
0
    Py_RETURN_NONE;
13248
0
}
13249
13250
static PyObject *
13251
ScandirIterator_enter(PyObject *self, PyObject *args)
13252
0
{
13253
0
    Py_INCREF(self);
13254
0
    return self;
13255
0
}
13256
13257
static PyObject *
13258
ScandirIterator_exit(ScandirIterator *self, PyObject *args)
13259
0
{
13260
0
    ScandirIterator_closedir(self);
13261
0
    Py_RETURN_NONE;
13262
0
}
13263
13264
static void
13265
ScandirIterator_finalize(ScandirIterator *iterator)
13266
0
{
13267
0
    PyObject *error_type, *error_value, *error_traceback;
13268
13269
    /* Save the current exception, if any. */
13270
0
    PyErr_Fetch(&error_type, &error_value, &error_traceback);
13271
13272
0
    if (!ScandirIterator_is_closed(iterator)) {
13273
0
        ScandirIterator_closedir(iterator);
13274
13275
0
        if (PyErr_ResourceWarning((PyObject *)iterator, 1,
13276
0
                                  "unclosed scandir iterator %R", iterator)) {
13277
            /* Spurious errors can appear at shutdown */
13278
0
            if (PyErr_ExceptionMatches(PyExc_Warning)) {
13279
0
                PyErr_WriteUnraisable((PyObject *) iterator);
13280
0
            }
13281
0
        }
13282
0
    }
13283
13284
0
    path_cleanup(&iterator->path);
13285
13286
    /* Restore the saved exception. */
13287
0
    PyErr_Restore(error_type, error_value, error_traceback);
13288
0
}
13289
13290
static void
13291
ScandirIterator_dealloc(ScandirIterator *iterator)
13292
0
{
13293
0
    if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
13294
0
        return;
13295
13296
0
    Py_TYPE(iterator)->tp_free((PyObject *)iterator);
13297
0
}
13298
13299
static PyMethodDef ScandirIterator_methods[] = {
13300
    {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
13301
    {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
13302
    {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
13303
    {NULL}
13304
};
13305
13306
static PyTypeObject ScandirIteratorType = {
13307
    PyVarObject_HEAD_INIT(NULL, 0)
13308
    MODNAME ".ScandirIterator",             /* tp_name */
13309
    sizeof(ScandirIterator),                /* tp_basicsize */
13310
    0,                                      /* tp_itemsize */
13311
    /* methods */
13312
    (destructor)ScandirIterator_dealloc,    /* tp_dealloc */
13313
    0,                                      /* tp_vectorcall_offset */
13314
    0,                                      /* tp_getattr */
13315
    0,                                      /* tp_setattr */
13316
    0,                                      /* tp_as_async */
13317
    0,                                      /* tp_repr */
13318
    0,                                      /* tp_as_number */
13319
    0,                                      /* tp_as_sequence */
13320
    0,                                      /* tp_as_mapping */
13321
    0,                                      /* tp_hash */
13322
    0,                                      /* tp_call */
13323
    0,                                      /* tp_str */
13324
    0,                                      /* tp_getattro */
13325
    0,                                      /* tp_setattro */
13326
    0,                                      /* tp_as_buffer */
13327
    Py_TPFLAGS_DEFAULT,                     /* tp_flags */
13328
    0,                                      /* tp_doc */
13329
    0,                                      /* tp_traverse */
13330
    0,                                      /* tp_clear */
13331
    0,                                      /* tp_richcompare */
13332
    0,                                      /* tp_weaklistoffset */
13333
    PyObject_SelfIter,                      /* tp_iter */
13334
    (iternextfunc)ScandirIterator_iternext, /* tp_iternext */
13335
    ScandirIterator_methods,                /* tp_methods */
13336
    0,                                      /* tp_members */
13337
    0,                                      /* tp_getset */
13338
    0,                                      /* tp_base */
13339
    0,                                      /* tp_dict */
13340
    0,                                      /* tp_descr_get */
13341
    0,                                      /* tp_descr_set */
13342
    0,                                      /* tp_dictoffset */
13343
    0,                                      /* tp_init */
13344
    0,                                      /* tp_alloc */
13345
    0,                                      /* tp_new */
13346
    0,                                      /* tp_free */
13347
    0,                                      /* tp_is_gc */
13348
    0,                                      /* tp_bases */
13349
    0,                                      /* tp_mro */
13350
    0,                                      /* tp_cache */
13351
    0,                                      /* tp_subclasses */
13352
    0,                                      /* tp_weaklist */
13353
    0,                                      /* tp_del */
13354
    0,                                      /* tp_version_tag */
13355
    (destructor)ScandirIterator_finalize,   /* tp_finalize */
13356
};
13357
13358
/*[clinic input]
13359
os.scandir
13360
13361
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
13362
13363
Return an iterator of DirEntry objects for given path.
13364
13365
path can be specified as either str, bytes, or a path-like object.  If path
13366
is bytes, the names of yielded DirEntry objects will also be bytes; in
13367
all other circumstances they will be str.
13368
13369
If path is None, uses the path='.'.
13370
[clinic start generated code]*/
13371
13372
static PyObject *
13373
os_scandir_impl(PyObject *module, path_t *path)
13374
/*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
13375
0
{
13376
0
    ScandirIterator *iterator;
13377
#ifdef MS_WINDOWS
13378
    wchar_t *path_strW;
13379
#else
13380
0
    const char *path_str;
13381
0
#ifdef HAVE_FDOPENDIR
13382
0
    int fd = -1;
13383
0
#endif
13384
0
#endif
13385
13386
0
    if (PySys_Audit("os.scandir", "O",
13387
0
                    path->object ? path->object : Py_None) < 0) {
13388
0
        return NULL;
13389
0
    }
13390
13391
0
    iterator = PyObject_New(ScandirIterator, &ScandirIteratorType);
13392
0
    if (!iterator)
13393
0
        return NULL;
13394
13395
#ifdef MS_WINDOWS
13396
    iterator->handle = INVALID_HANDLE_VALUE;
13397
#else
13398
0
    iterator->dirp = NULL;
13399
0
#endif
13400
13401
0
    memcpy(&iterator->path, path, sizeof(path_t));
13402
    /* Move the ownership to iterator->path */
13403
0
    path->object = NULL;
13404
0
    path->cleanup = NULL;
13405
13406
#ifdef MS_WINDOWS
13407
    iterator->first_time = 1;
13408
13409
    path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
13410
    if (!path_strW)
13411
        goto error;
13412
13413
    Py_BEGIN_ALLOW_THREADS
13414
    iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
13415
    Py_END_ALLOW_THREADS
13416
13417
    PyMem_Free(path_strW);
13418
13419
    if (iterator->handle == INVALID_HANDLE_VALUE) {
13420
        path_error(&iterator->path);
13421
        goto error;
13422
    }
13423
#else /* POSIX */
13424
0
    errno = 0;
13425
0
#ifdef HAVE_FDOPENDIR
13426
0
    if (path->fd != -1) {
13427
        /* closedir() closes the FD, so we duplicate it */
13428
0
        fd = _Py_dup(path->fd);
13429
0
        if (fd == -1)
13430
0
            goto error;
13431
13432
0
        Py_BEGIN_ALLOW_THREADS
13433
0
        iterator->dirp = fdopendir(fd);
13434
0
        Py_END_ALLOW_THREADS
13435
0
    }
13436
0
    else
13437
0
#endif
13438
0
    {
13439
0
        if (iterator->path.narrow)
13440
0
            path_str = iterator->path.narrow;
13441
0
        else
13442
0
            path_str = ".";
13443
13444
0
        Py_BEGIN_ALLOW_THREADS
13445
0
        iterator->dirp = opendir(path_str);
13446
0
        Py_END_ALLOW_THREADS
13447
0
    }
13448
13449
0
    if (!iterator->dirp) {
13450
0
        path_error(&iterator->path);
13451
0
#ifdef HAVE_FDOPENDIR
13452
0
        if (fd != -1) {
13453
0
            Py_BEGIN_ALLOW_THREADS
13454
0
            close(fd);
13455
0
            Py_END_ALLOW_THREADS
13456
0
        }
13457
0
#endif
13458
0
        goto error;
13459
0
    }
13460
0
#endif
13461
13462
0
    return (PyObject *)iterator;
13463
13464
0
error:
13465
0
    Py_DECREF(iterator);
13466
0
    return NULL;
13467
0
}
13468
13469
/*
13470
    Return the file system path representation of the object.
13471
13472
    If the object is str or bytes, then allow it to pass through with
13473
    an incremented refcount. If the object defines __fspath__(), then
13474
    return the result of that method. All other types raise a TypeError.
13475
*/
13476
PyObject *
13477
PyOS_FSPath(PyObject *path)
13478
3.03k
{
13479
    /* For error message reasons, this function is manually inlined in
13480
       path_converter(). */
13481
3.03k
    _Py_IDENTIFIER(__fspath__);
13482
3.03k
    PyObject *func = NULL;
13483
3.03k
    PyObject *path_repr = NULL;
13484
13485
3.03k
    if (PyUnicode_Check(path) || PyBytes_Check(path)) {
13486
3.03k
        Py_INCREF(path);
13487
3.03k
        return path;
13488
3.03k
    }
13489
13490
0
    func = _PyObject_LookupSpecial(path, &PyId___fspath__);
13491
0
    if (NULL == func) {
13492
0
        return PyErr_Format(PyExc_TypeError,
13493
0
                            "expected str, bytes or os.PathLike object, "
13494
0
                            "not %.200s",
13495
0
                            Py_TYPE(path)->tp_name);
13496
0
    }
13497
13498
0
    path_repr = _PyObject_CallNoArg(func);
13499
0
    Py_DECREF(func);
13500
0
    if (NULL == path_repr) {
13501
0
        return NULL;
13502
0
    }
13503
13504
0
    if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
13505
0
        PyErr_Format(PyExc_TypeError,
13506
0
                     "expected %.200s.__fspath__() to return str or bytes, "
13507
0
                     "not %.200s", Py_TYPE(path)->tp_name,
13508
0
                     Py_TYPE(path_repr)->tp_name);
13509
0
        Py_DECREF(path_repr);
13510
0
        return NULL;
13511
0
    }
13512
13513
0
    return path_repr;
13514
0
}
13515
13516
/*[clinic input]
13517
os.fspath
13518
13519
    path: object
13520
13521
Return the file system path representation of the object.
13522
13523
If the object is str or bytes, then allow it to pass through as-is. If the
13524
object defines __fspath__(), then return the result of that method. All other
13525
types raise a TypeError.
13526
[clinic start generated code]*/
13527
13528
static PyObject *
13529
os_fspath_impl(PyObject *module, PyObject *path)
13530
/*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
13531
1.44k
{
13532
1.44k
    return PyOS_FSPath(path);
13533
1.44k
}
13534
13535
#ifdef HAVE_GETRANDOM_SYSCALL
13536
/*[clinic input]
13537
os.getrandom
13538
13539
    size: Py_ssize_t
13540
    flags: int=0
13541
13542
Obtain a series of random bytes.
13543
[clinic start generated code]*/
13544
13545
static PyObject *
13546
os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
13547
/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
13548
0
{
13549
0
    PyObject *bytes;
13550
0
    Py_ssize_t n;
13551
13552
0
    if (size < 0) {
13553
0
        errno = EINVAL;
13554
0
        return posix_error();
13555
0
    }
13556
13557
0
    bytes = PyBytes_FromStringAndSize(NULL, size);
13558
0
    if (bytes == NULL) {
13559
0
        PyErr_NoMemory();
13560
0
        return NULL;
13561
0
    }
13562
13563
0
    while (1) {
13564
0
        n = syscall(SYS_getrandom,
13565
0
                    PyBytes_AS_STRING(bytes),
13566
0
                    PyBytes_GET_SIZE(bytes),
13567
0
                    flags);
13568
0
        if (n < 0 && errno == EINTR) {
13569
0
            if (PyErr_CheckSignals() < 0) {
13570
0
                goto error;
13571
0
            }
13572
13573
            /* getrandom() was interrupted by a signal: retry */
13574
0
            continue;
13575
0
        }
13576
0
        break;
13577
0
    }
13578
13579
0
    if (n < 0) {
13580
0
        PyErr_SetFromErrno(PyExc_OSError);
13581
0
        goto error;
13582
0
    }
13583
13584
0
    if (n != size) {
13585
0
        _PyBytes_Resize(&bytes, n);
13586
0
    }
13587
13588
0
    return bytes;
13589
13590
0
error:
13591
0
    Py_DECREF(bytes);
13592
0
    return NULL;
13593
0
}
13594
#endif   /* HAVE_GETRANDOM_SYSCALL */
13595
13596
#ifdef MS_WINDOWS
13597
/* bpo-36085: Helper functions for managing DLL search directories
13598
 * on win32
13599
 */
13600
13601
typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);
13602
typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);
13603
13604
/*[clinic input]
13605
os._add_dll_directory
13606
13607
    path: path_t
13608
13609
Add a path to the DLL search path.
13610
13611
This search path is used when resolving dependencies for imported
13612
extension modules (the module itself is resolved through sys.path),
13613
and also by ctypes.
13614
13615
Returns an opaque value that may be passed to os.remove_dll_directory
13616
to remove this directory from the search path.
13617
[clinic start generated code]*/
13618
13619
static PyObject *
13620
os__add_dll_directory_impl(PyObject *module, path_t *path)
13621
/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
13622
{
13623
    HMODULE hKernel32;
13624
    PAddDllDirectory AddDllDirectory;
13625
    DLL_DIRECTORY_COOKIE cookie = 0;
13626
    DWORD err = 0;
13627
13628
    if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
13629
        return NULL;
13630
    }
13631
13632
    /* For Windows 7, we have to load this. As this will be a fairly
13633
       infrequent operation, just do it each time. Kernel32 is always
13634
       loaded. */
13635
    Py_BEGIN_ALLOW_THREADS
13636
    if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
13637
        !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
13638
            hKernel32, "AddDllDirectory")) ||
13639
        !(cookie = (*AddDllDirectory)(path->wide))) {
13640
        err = GetLastError();
13641
    }
13642
    Py_END_ALLOW_THREADS
13643
13644
    if (err) {
13645
        return win32_error_object_err("add_dll_directory",
13646
                                      path->object, err);
13647
    }
13648
13649
    return PyCapsule_New(cookie, "DLL directory cookie", NULL);
13650
}
13651
13652
/*[clinic input]
13653
os._remove_dll_directory
13654
13655
    cookie: object
13656
13657
Removes a path from the DLL search path.
13658
13659
The parameter is an opaque value that was returned from
13660
os.add_dll_directory. You can only remove directories that you added
13661
yourself.
13662
[clinic start generated code]*/
13663
13664
static PyObject *
13665
os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
13666
/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
13667
{
13668
    HMODULE hKernel32;
13669
    PRemoveDllDirectory RemoveDllDirectory;
13670
    DLL_DIRECTORY_COOKIE cookieValue;
13671
    DWORD err = 0;
13672
13673
    if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
13674
        PyErr_SetString(PyExc_TypeError,
13675
            "Provided cookie was not returned from os.add_dll_directory");
13676
        return NULL;
13677
    }
13678
13679
    cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
13680
        cookie, "DLL directory cookie");
13681
13682
    /* For Windows 7, we have to load this. As this will be a fairly
13683
       infrequent operation, just do it each time. Kernel32 is always
13684
       loaded. */
13685
    Py_BEGIN_ALLOW_THREADS
13686
    if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
13687
        !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
13688
            hKernel32, "RemoveDllDirectory")) ||
13689
        !(*RemoveDllDirectory)(cookieValue)) {
13690
        err = GetLastError();
13691
    }
13692
    Py_END_ALLOW_THREADS
13693
13694
    if (err) {
13695
        return win32_error_object_err("remove_dll_directory",
13696
                                      NULL, err);
13697
    }
13698
13699
    if (PyCapsule_SetName(cookie, NULL)) {
13700
        return NULL;
13701
    }
13702
13703
    Py_RETURN_NONE;
13704
}
13705
13706
#endif
13707
13708
static PyMethodDef posix_methods[] = {
13709
13710
    OS_STAT_METHODDEF
13711
    OS_ACCESS_METHODDEF
13712
    OS_TTYNAME_METHODDEF
13713
    OS_CHDIR_METHODDEF
13714
    OS_CHFLAGS_METHODDEF
13715
    OS_CHMOD_METHODDEF
13716
    OS_FCHMOD_METHODDEF
13717
    OS_LCHMOD_METHODDEF
13718
    OS_CHOWN_METHODDEF
13719
    OS_FCHOWN_METHODDEF
13720
    OS_LCHOWN_METHODDEF
13721
    OS_LCHFLAGS_METHODDEF
13722
    OS_CHROOT_METHODDEF
13723
    OS_CTERMID_METHODDEF
13724
    OS_GETCWD_METHODDEF
13725
    OS_GETCWDB_METHODDEF
13726
    OS_LINK_METHODDEF
13727
    OS_LISTDIR_METHODDEF
13728
    OS_LSTAT_METHODDEF
13729
    OS_MKDIR_METHODDEF
13730
    OS_NICE_METHODDEF
13731
    OS_GETPRIORITY_METHODDEF
13732
    OS_SETPRIORITY_METHODDEF
13733
    OS_POSIX_SPAWN_METHODDEF
13734
    OS_POSIX_SPAWNP_METHODDEF
13735
    OS_READLINK_METHODDEF
13736
    OS_COPY_FILE_RANGE_METHODDEF
13737
    OS_RENAME_METHODDEF
13738
    OS_REPLACE_METHODDEF
13739
    OS_RMDIR_METHODDEF
13740
    OS_SYMLINK_METHODDEF
13741
    OS_SYSTEM_METHODDEF
13742
    OS_UMASK_METHODDEF
13743
    OS_UNAME_METHODDEF
13744
    OS_UNLINK_METHODDEF
13745
    OS_REMOVE_METHODDEF
13746
    OS_UTIME_METHODDEF
13747
    OS_TIMES_METHODDEF
13748
    OS__EXIT_METHODDEF
13749
    OS__FCOPYFILE_METHODDEF
13750
    OS_EXECV_METHODDEF
13751
    OS_EXECVE_METHODDEF
13752
    OS_SPAWNV_METHODDEF
13753
    OS_SPAWNVE_METHODDEF
13754
    OS_FORK1_METHODDEF
13755
    OS_FORK_METHODDEF
13756
    OS_REGISTER_AT_FORK_METHODDEF
13757
    OS_SCHED_GET_PRIORITY_MAX_METHODDEF
13758
    OS_SCHED_GET_PRIORITY_MIN_METHODDEF
13759
    OS_SCHED_GETPARAM_METHODDEF
13760
    OS_SCHED_GETSCHEDULER_METHODDEF
13761
    OS_SCHED_RR_GET_INTERVAL_METHODDEF
13762
    OS_SCHED_SETPARAM_METHODDEF
13763
    OS_SCHED_SETSCHEDULER_METHODDEF
13764
    OS_SCHED_YIELD_METHODDEF
13765
    OS_SCHED_SETAFFINITY_METHODDEF
13766
    OS_SCHED_GETAFFINITY_METHODDEF
13767
    OS_OPENPTY_METHODDEF
13768
    OS_FORKPTY_METHODDEF
13769
    OS_GETEGID_METHODDEF
13770
    OS_GETEUID_METHODDEF
13771
    OS_GETGID_METHODDEF
13772
#ifdef HAVE_GETGROUPLIST
13773
    {"getgrouplist",    posix_getgrouplist, METH_VARARGS, posix_getgrouplist__doc__},
13774
#endif
13775
    OS_GETGROUPS_METHODDEF
13776
    OS_GETPID_METHODDEF
13777
    OS_GETPGRP_METHODDEF
13778
    OS_GETPPID_METHODDEF
13779
    OS_GETUID_METHODDEF
13780
    OS_GETLOGIN_METHODDEF
13781
    OS_KILL_METHODDEF
13782
    OS_KILLPG_METHODDEF
13783
    OS_PLOCK_METHODDEF
13784
#ifdef MS_WINDOWS
13785
    OS_STARTFILE_METHODDEF
13786
#endif
13787
    OS_SETUID_METHODDEF
13788
    OS_SETEUID_METHODDEF
13789
    OS_SETREUID_METHODDEF
13790
    OS_SETGID_METHODDEF
13791
    OS_SETEGID_METHODDEF
13792
    OS_SETREGID_METHODDEF
13793
    OS_SETGROUPS_METHODDEF
13794
#ifdef HAVE_INITGROUPS
13795
    {"initgroups",      posix_initgroups, METH_VARARGS, posix_initgroups__doc__},
13796
#endif /* HAVE_INITGROUPS */
13797
    OS_GETPGID_METHODDEF
13798
    OS_SETPGRP_METHODDEF
13799
    OS_WAIT_METHODDEF
13800
    OS_WAIT3_METHODDEF
13801
    OS_WAIT4_METHODDEF
13802
    OS_WAITID_METHODDEF
13803
    OS_WAITPID_METHODDEF
13804
    OS_GETSID_METHODDEF
13805
    OS_SETSID_METHODDEF
13806
    OS_SETPGID_METHODDEF
13807
    OS_TCGETPGRP_METHODDEF
13808
    OS_TCSETPGRP_METHODDEF
13809
    OS_OPEN_METHODDEF
13810
    OS_CLOSE_METHODDEF
13811
    OS_CLOSERANGE_METHODDEF
13812
    OS_DEVICE_ENCODING_METHODDEF
13813
    OS_DUP_METHODDEF
13814
    OS_DUP2_METHODDEF
13815
    OS_LOCKF_METHODDEF
13816
    OS_LSEEK_METHODDEF
13817
    OS_READ_METHODDEF
13818
    OS_READV_METHODDEF
13819
    OS_PREAD_METHODDEF
13820
    OS_PREADV_METHODDEF
13821
    OS_WRITE_METHODDEF
13822
    OS_WRITEV_METHODDEF
13823
    OS_PWRITE_METHODDEF
13824
    OS_PWRITEV_METHODDEF
13825
#ifdef HAVE_SENDFILE
13826
    {"sendfile",        (PyCFunction)(void(*)(void))posix_sendfile, METH_VARARGS | METH_KEYWORDS,
13827
                            posix_sendfile__doc__},
13828
#endif
13829
    OS_FSTAT_METHODDEF
13830
    OS_ISATTY_METHODDEF
13831
    OS_PIPE_METHODDEF
13832
    OS_PIPE2_METHODDEF
13833
    OS_MKFIFO_METHODDEF
13834
    OS_MKNOD_METHODDEF
13835
    OS_MAJOR_METHODDEF
13836
    OS_MINOR_METHODDEF
13837
    OS_MAKEDEV_METHODDEF
13838
    OS_FTRUNCATE_METHODDEF
13839
    OS_TRUNCATE_METHODDEF
13840
    OS_POSIX_FALLOCATE_METHODDEF
13841
    OS_POSIX_FADVISE_METHODDEF
13842
    OS_PUTENV_METHODDEF
13843
    OS_UNSETENV_METHODDEF
13844
    OS_STRERROR_METHODDEF
13845
    OS_FCHDIR_METHODDEF
13846
    OS_FSYNC_METHODDEF
13847
    OS_SYNC_METHODDEF
13848
    OS_FDATASYNC_METHODDEF
13849
    OS_WCOREDUMP_METHODDEF
13850
    OS_WIFCONTINUED_METHODDEF
13851
    OS_WIFSTOPPED_METHODDEF
13852
    OS_WIFSIGNALED_METHODDEF
13853
    OS_WIFEXITED_METHODDEF
13854
    OS_WEXITSTATUS_METHODDEF
13855
    OS_WTERMSIG_METHODDEF
13856
    OS_WSTOPSIG_METHODDEF
13857
    OS_FSTATVFS_METHODDEF
13858
    OS_STATVFS_METHODDEF
13859
    OS_CONFSTR_METHODDEF
13860
    OS_SYSCONF_METHODDEF
13861
    OS_FPATHCONF_METHODDEF
13862
    OS_PATHCONF_METHODDEF
13863
    OS_ABORT_METHODDEF
13864
    OS__GETFULLPATHNAME_METHODDEF
13865
    OS__GETDISKUSAGE_METHODDEF
13866
    OS__GETFINALPATHNAME_METHODDEF
13867
    OS__GETVOLUMEPATHNAME_METHODDEF
13868
    OS_GETLOADAVG_METHODDEF
13869
    OS_URANDOM_METHODDEF
13870
    OS_SETRESUID_METHODDEF
13871
    OS_SETRESGID_METHODDEF
13872
    OS_GETRESUID_METHODDEF
13873
    OS_GETRESGID_METHODDEF
13874
13875
    OS_GETXATTR_METHODDEF
13876
    OS_SETXATTR_METHODDEF
13877
    OS_REMOVEXATTR_METHODDEF
13878
    OS_LISTXATTR_METHODDEF
13879
13880
#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
13881
    {"get_terminal_size", get_terminal_size, METH_VARARGS, termsize__doc__},
13882
#endif
13883
    OS_CPU_COUNT_METHODDEF
13884
    OS_GET_INHERITABLE_METHODDEF
13885
    OS_SET_INHERITABLE_METHODDEF
13886
    OS_GET_HANDLE_INHERITABLE_METHODDEF
13887
    OS_SET_HANDLE_INHERITABLE_METHODDEF
13888
#ifndef MS_WINDOWS
13889
    OS_GET_BLOCKING_METHODDEF
13890
    OS_SET_BLOCKING_METHODDEF
13891
#endif
13892
    OS_SCANDIR_METHODDEF
13893
    OS_FSPATH_METHODDEF
13894
    OS_GETRANDOM_METHODDEF
13895
    OS_MEMFD_CREATE_METHODDEF
13896
#ifdef MS_WINDOWS
13897
    OS__ADD_DLL_DIRECTORY_METHODDEF
13898
    OS__REMOVE_DLL_DIRECTORY_METHODDEF
13899
#endif
13900
    {NULL,              NULL}            /* Sentinel */
13901
};
13902
13903
static int
13904
all_ins(PyObject *m)
13905
14
{
13906
14
#ifdef F_OK
13907
14
    if (PyModule_AddIntMacro(m, F_OK)) return -1;
13908
14
#endif
13909
14
#ifdef R_OK
13910
14
    if (PyModule_AddIntMacro(m, R_OK)) return -1;
13911
14
#endif
13912
14
#ifdef W_OK
13913
14
    if (PyModule_AddIntMacro(m, W_OK)) return -1;
13914
14
#endif
13915
14
#ifdef X_OK
13916
14
    if (PyModule_AddIntMacro(m, X_OK)) return -1;
13917
14
#endif
13918
14
#ifdef NGROUPS_MAX
13919
14
    if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
13920
14
#endif
13921
14
#ifdef TMP_MAX
13922
14
    if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
13923
14
#endif
13924
14
#ifdef WCONTINUED
13925
14
    if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
13926
14
#endif
13927
14
#ifdef WNOHANG
13928
14
    if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
13929
14
#endif
13930
14
#ifdef WUNTRACED
13931
14
    if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
13932
14
#endif
13933
14
#ifdef O_RDONLY
13934
14
    if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
13935
14
#endif
13936
14
#ifdef O_WRONLY
13937
14
    if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
13938
14
#endif
13939
14
#ifdef O_RDWR
13940
14
    if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
13941
14
#endif
13942
14
#ifdef O_NDELAY
13943
14
    if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
13944
14
#endif
13945
14
#ifdef O_NONBLOCK
13946
14
    if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
13947
14
#endif
13948
14
#ifdef O_APPEND
13949
14
    if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
13950
14
#endif
13951
14
#ifdef O_DSYNC
13952
14
    if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
13953
14
#endif
13954
14
#ifdef O_RSYNC
13955
14
    if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
13956
14
#endif
13957
14
#ifdef O_SYNC
13958
14
    if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
13959
14
#endif
13960
14
#ifdef O_NOCTTY
13961
14
    if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
13962
14
#endif
13963
14
#ifdef O_CREAT
13964
14
    if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
13965
14
#endif
13966
14
#ifdef O_EXCL
13967
14
    if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
13968
14
#endif
13969
14
#ifdef O_TRUNC
13970
14
    if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
13971
14
#endif
13972
#ifdef O_BINARY
13973
    if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
13974
#endif
13975
#ifdef O_TEXT
13976
    if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
13977
#endif
13978
#ifdef O_XATTR
13979
    if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
13980
#endif
13981
14
#ifdef O_LARGEFILE
13982
14
    if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
13983
14
#endif
13984
14
#ifndef __GNU__
13985
#ifdef O_SHLOCK
13986
    if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
13987
#endif
13988
#ifdef O_EXLOCK
13989
    if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
13990
#endif
13991
14
#endif
13992
#ifdef O_EXEC
13993
    if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
13994
#endif
13995
#ifdef O_SEARCH
13996
    if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
13997
#endif
13998
14
#ifdef O_PATH
13999
14
    if (PyModule_AddIntMacro(m, O_PATH)) return -1;
14000
14
#endif
14001
#ifdef O_TTY_INIT
14002
    if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
14003
#endif
14004
14
#ifdef O_TMPFILE
14005
14
    if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
14006
14
#endif
14007
14
#ifdef PRIO_PROCESS
14008
14
    if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
14009
14
#endif
14010
14
#ifdef PRIO_PGRP
14011
14
    if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
14012
14
#endif
14013
14
#ifdef PRIO_USER
14014
14
    if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
14015
14
#endif
14016
14
#ifdef O_CLOEXEC
14017
14
    if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
14018
14
#endif
14019
14
#ifdef O_ACCMODE
14020
14
    if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
14021
14
#endif
14022
14023
14024
14
#ifdef SEEK_HOLE
14025
14
    if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
14026
14
#endif
14027
14
#ifdef SEEK_DATA
14028
14
    if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
14029
14
#endif
14030
14031
/* MS Windows */
14032
#ifdef O_NOINHERIT
14033
    /* Don't inherit in child processes. */
14034
    if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
14035
#endif
14036
#ifdef _O_SHORT_LIVED
14037
    /* Optimize for short life (keep in memory). */
14038
    /* MS forgot to define this one with a non-underscore form too. */
14039
    if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
14040
#endif
14041
#ifdef O_TEMPORARY
14042
    /* Automatically delete when last handle is closed. */
14043
    if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
14044
#endif
14045
#ifdef O_RANDOM
14046
    /* Optimize for random access. */
14047
    if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
14048
#endif
14049
#ifdef O_SEQUENTIAL
14050
    /* Optimize for sequential access. */
14051
    if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
14052
#endif
14053
14054
/* GNU extensions. */
14055
14
#ifdef O_ASYNC
14056
    /* Send a SIGIO signal whenever input or output
14057
       becomes available on file descriptor */
14058
14
    if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
14059
14
#endif
14060
14
#ifdef O_DIRECT
14061
    /* Direct disk access. */
14062
14
    if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
14063
14
#endif
14064
14
#ifdef O_DIRECTORY
14065
    /* Must be a directory.      */
14066
14
    if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
14067
14
#endif
14068
14
#ifdef O_NOFOLLOW
14069
    /* Do not follow links.      */
14070
14
    if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
14071
14
#endif
14072
#ifdef O_NOLINKS
14073
    /* Fails if link count of the named file is greater than 1 */
14074
    if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
14075
#endif
14076
14
#ifdef O_NOATIME
14077
    /* Do not update the access time. */
14078
14
    if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
14079
14
#endif
14080
14081
    /* These come from sysexits.h */
14082
14
#ifdef EX_OK
14083
14
    if (PyModule_AddIntMacro(m, EX_OK)) return -1;
14084
14
#endif /* EX_OK */
14085
14
#ifdef EX_USAGE
14086
14
    if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
14087
14
#endif /* EX_USAGE */
14088
14
#ifdef EX_DATAERR
14089
14
    if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
14090
14
#endif /* EX_DATAERR */
14091
14
#ifdef EX_NOINPUT
14092
14
    if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
14093
14
#endif /* EX_NOINPUT */
14094
14
#ifdef EX_NOUSER
14095
14
    if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
14096
14
#endif /* EX_NOUSER */
14097
14
#ifdef EX_NOHOST
14098
14
    if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
14099
14
#endif /* EX_NOHOST */
14100
14
#ifdef EX_UNAVAILABLE
14101
14
    if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
14102
14
#endif /* EX_UNAVAILABLE */
14103
14
#ifdef EX_SOFTWARE
14104
14
    if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
14105
14
#endif /* EX_SOFTWARE */
14106
14
#ifdef EX_OSERR
14107
14
    if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
14108
14
#endif /* EX_OSERR */
14109
14
#ifdef EX_OSFILE
14110
14
    if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
14111
14
#endif /* EX_OSFILE */
14112
14
#ifdef EX_CANTCREAT
14113
14
    if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
14114
14
#endif /* EX_CANTCREAT */
14115
14
#ifdef EX_IOERR
14116
14
    if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
14117
14
#endif /* EX_IOERR */
14118
14
#ifdef EX_TEMPFAIL
14119
14
    if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
14120
14
#endif /* EX_TEMPFAIL */
14121
14
#ifdef EX_PROTOCOL
14122
14
    if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
14123
14
#endif /* EX_PROTOCOL */
14124
14
#ifdef EX_NOPERM
14125
14
    if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
14126
14
#endif /* EX_NOPERM */
14127
14
#ifdef EX_CONFIG
14128
14
    if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
14129
14
#endif /* EX_CONFIG */
14130
#ifdef EX_NOTFOUND
14131
    if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
14132
#endif /* EX_NOTFOUND */
14133
14134
    /* statvfs */
14135
14
#ifdef ST_RDONLY
14136
14
    if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
14137
14
#endif /* ST_RDONLY */
14138
14
#ifdef ST_NOSUID
14139
14
    if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
14140
14
#endif /* ST_NOSUID */
14141
14142
       /* GNU extensions */
14143
14
#ifdef ST_NODEV
14144
14
    if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
14145
14
#endif /* ST_NODEV */
14146
14
#ifdef ST_NOEXEC
14147
14
    if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
14148
14
#endif /* ST_NOEXEC */
14149
14
#ifdef ST_SYNCHRONOUS
14150
14
    if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
14151
14
#endif /* ST_SYNCHRONOUS */
14152
14
#ifdef ST_MANDLOCK
14153
14
    if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
14154
14
#endif /* ST_MANDLOCK */
14155
14
#ifdef ST_WRITE
14156
14
    if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
14157
14
#endif /* ST_WRITE */
14158
14
#ifdef ST_APPEND
14159
14
    if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
14160
14
#endif /* ST_APPEND */
14161
14
#ifdef ST_NOATIME
14162
14
    if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
14163
14
#endif /* ST_NOATIME */
14164
14
#ifdef ST_NODIRATIME
14165
14
    if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
14166
14
#endif /* ST_NODIRATIME */
14167
14
#ifdef ST_RELATIME
14168
14
    if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
14169
14
#endif /* ST_RELATIME */
14170
14171
    /* FreeBSD sendfile() constants */
14172
#ifdef SF_NODISKIO
14173
    if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
14174
#endif
14175
#ifdef SF_MNOWAIT
14176
    if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
14177
#endif
14178
#ifdef SF_SYNC
14179
    if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
14180
#endif
14181
14182
    /* constants for posix_fadvise */
14183
14
#ifdef POSIX_FADV_NORMAL
14184
14
    if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
14185
14
#endif
14186
14
#ifdef POSIX_FADV_SEQUENTIAL
14187
14
    if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
14188
14
#endif
14189
14
#ifdef POSIX_FADV_RANDOM
14190
14
    if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
14191
14
#endif
14192
14
#ifdef POSIX_FADV_NOREUSE
14193
14
    if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
14194
14
#endif
14195
14
#ifdef POSIX_FADV_WILLNEED
14196
14
    if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
14197
14
#endif
14198
14
#ifdef POSIX_FADV_DONTNEED
14199
14
    if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
14200
14
#endif
14201
14202
    /* constants for waitid */
14203
14
#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
14204
14
    if (PyModule_AddIntMacro(m, P_PID)) return -1;
14205
14
    if (PyModule_AddIntMacro(m, P_PGID)) return -1;
14206
14
    if (PyModule_AddIntMacro(m, P_ALL)) return -1;
14207
14
#endif
14208
14
#ifdef WEXITED
14209
14
    if (PyModule_AddIntMacro(m, WEXITED)) return -1;
14210
14
#endif
14211
14
#ifdef WNOWAIT
14212
14
    if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
14213
14
#endif
14214
14
#ifdef WSTOPPED
14215
14
    if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
14216
14
#endif
14217
14
#ifdef CLD_EXITED
14218
14
    if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
14219
14
#endif
14220
14
#ifdef CLD_DUMPED
14221
14
    if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
14222
14
#endif
14223
14
#ifdef CLD_TRAPPED
14224
14
    if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
14225
14
#endif
14226
14
#ifdef CLD_CONTINUED
14227
14
    if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
14228
14
#endif
14229
14230
    /* constants for lockf */
14231
14
#ifdef F_LOCK
14232
14
    if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
14233
14
#endif
14234
14
#ifdef F_TLOCK
14235
14
    if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
14236
14
#endif
14237
14
#ifdef F_ULOCK
14238
14
    if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
14239
14
#endif
14240
14
#ifdef F_TEST
14241
14
    if (PyModule_AddIntMacro(m, F_TEST)) return -1;
14242
14
#endif
14243
14244
14
#ifdef RWF_DSYNC
14245
14
    if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
14246
14
#endif
14247
14
#ifdef RWF_HIPRI
14248
14
    if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
14249
14
#endif
14250
14
#ifdef RWF_SYNC
14251
14
    if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
14252
14
#endif
14253
14
#ifdef RWF_NOWAIT
14254
14
    if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
14255
14
#endif
14256
14257
/* constants for posix_spawn */
14258
14
#ifdef HAVE_POSIX_SPAWN
14259
14
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
14260
14
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
14261
14
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
14262
14
#endif
14263
14264
#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
14265
    if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
14266
    if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
14267
    if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
14268
#endif
14269
#ifdef HAVE_SPAWNV
14270
    if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
14271
    if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
14272
#endif
14273
14274
14
#ifdef HAVE_SCHED_H
14275
14
#ifdef SCHED_OTHER
14276
14
    if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
14277
14
#endif
14278
14
#ifdef SCHED_FIFO
14279
14
    if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
14280
14
#endif
14281
14
#ifdef SCHED_RR
14282
14
    if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
14283
14
#endif
14284
#ifdef SCHED_SPORADIC
14285
    if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
14286
#endif
14287
14
#ifdef SCHED_BATCH
14288
14
    if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
14289
14
#endif
14290
14
#ifdef SCHED_IDLE
14291
14
    if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
14292
14
#endif
14293
14
#ifdef SCHED_RESET_ON_FORK
14294
14
    if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
14295
14
#endif
14296
#ifdef SCHED_SYS
14297
    if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
14298
#endif
14299
#ifdef SCHED_IA
14300
    if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
14301
#endif
14302
#ifdef SCHED_FSS
14303
    if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
14304
#endif
14305
#ifdef SCHED_FX
14306
    if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
14307
#endif
14308
14
#endif
14309
14310
14
#ifdef USE_XATTRS
14311
14
    if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
14312
14
    if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
14313
14
    if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
14314
14
#endif
14315
14316
14
#if HAVE_DECL_RTLD_LAZY
14317
14
    if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
14318
14
#endif
14319
14
#if HAVE_DECL_RTLD_NOW
14320
14
    if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
14321
14
#endif
14322
14
#if HAVE_DECL_RTLD_GLOBAL
14323
14
    if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
14324
14
#endif
14325
14
#if HAVE_DECL_RTLD_LOCAL
14326
14
    if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
14327
14
#endif
14328
14
#if HAVE_DECL_RTLD_NODELETE
14329
14
    if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
14330
14
#endif
14331
14
#if HAVE_DECL_RTLD_NOLOAD
14332
14
    if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
14333
14
#endif
14334
14
#if HAVE_DECL_RTLD_DEEPBIND
14335
14
    if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
14336
14
#endif
14337
#if HAVE_DECL_RTLD_MEMBER
14338
    if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
14339
#endif
14340
14341
14
#ifdef HAVE_GETRANDOM_SYSCALL
14342
14
    if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
14343
14
    if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
14344
14
#endif
14345
14
#ifdef HAVE_MEMFD_CREATE
14346
14
    if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
14347
14
    if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
14348
14
#ifdef MFD_HUGETLB
14349
14
    if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
14350
14
#endif
14351
14
#ifdef MFD_HUGE_SHIFT
14352
14
    if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
14353
14
#endif
14354
14
#ifdef MFD_HUGE_MASK
14355
14
    if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
14356
14
#endif
14357
14
#ifdef MFD_HUGE_64KB
14358
14
    if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
14359
14
#endif
14360
14
#ifdef MFD_HUGE_512KB
14361
14
    if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
14362
14
#endif
14363
14
#ifdef MFD_HUGE_1MB
14364
14
    if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
14365
14
#endif
14366
14
#ifdef MFD_HUGE_2MB
14367
14
    if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
14368
14
#endif
14369
14
#ifdef MFD_HUGE_8MB
14370
14
    if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
14371
14
#endif
14372
14
#ifdef MFD_HUGE_16MB
14373
14
    if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
14374
14
#endif
14375
14
#ifdef MFD_HUGE_32MB
14376
14
    if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
14377
14
#endif
14378
14
#ifdef MFD_HUGE_256MB
14379
14
    if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
14380
14
#endif
14381
14
#ifdef MFD_HUGE_512MB
14382
14
    if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
14383
14
#endif
14384
14
#ifdef MFD_HUGE_1GB
14385
14
    if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
14386
14
#endif
14387
14
#ifdef MFD_HUGE_2GB
14388
14
    if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
14389
14
#endif
14390
14
#ifdef MFD_HUGE_16GB
14391
14
    if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
14392
14
#endif
14393
14
#endif
14394
14395
#if defined(__APPLE__)
14396
    if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
14397
#endif
14398
14399
#ifdef MS_WINDOWS
14400
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
14401
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
14402
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
14403
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
14404
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
14405
#endif
14406
14407
14
    return 0;
14408
14
}
14409
14410
14411
static struct PyModuleDef posixmodule = {
14412
    PyModuleDef_HEAD_INIT,
14413
    MODNAME,
14414
    posix__doc__,
14415
    -1,
14416
    posix_methods,
14417
    NULL,
14418
    NULL,
14419
    NULL,
14420
    NULL
14421
};
14422
14423
14424
static const char * const have_functions[] = {
14425
14426
#ifdef HAVE_FACCESSAT
14427
    "HAVE_FACCESSAT",
14428
#endif
14429
14430
#ifdef HAVE_FCHDIR
14431
    "HAVE_FCHDIR",
14432
#endif
14433
14434
#ifdef HAVE_FCHMOD
14435
    "HAVE_FCHMOD",
14436
#endif
14437
14438
#ifdef HAVE_FCHMODAT
14439
    "HAVE_FCHMODAT",
14440
#endif
14441
14442
#ifdef HAVE_FCHOWN
14443
    "HAVE_FCHOWN",
14444
#endif
14445
14446
#ifdef HAVE_FCHOWNAT
14447
    "HAVE_FCHOWNAT",
14448
#endif
14449
14450
#ifdef HAVE_FEXECVE
14451
    "HAVE_FEXECVE",
14452
#endif
14453
14454
#ifdef HAVE_FDOPENDIR
14455
    "HAVE_FDOPENDIR",
14456
#endif
14457
14458
#ifdef HAVE_FPATHCONF
14459
    "HAVE_FPATHCONF",
14460
#endif
14461
14462
#ifdef HAVE_FSTATAT
14463
    "HAVE_FSTATAT",
14464
#endif
14465
14466
#ifdef HAVE_FSTATVFS
14467
    "HAVE_FSTATVFS",
14468
#endif
14469
14470
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
14471
    "HAVE_FTRUNCATE",
14472
#endif
14473
14474
#ifdef HAVE_FUTIMENS
14475
    "HAVE_FUTIMENS",
14476
#endif
14477
14478
#ifdef HAVE_FUTIMES
14479
    "HAVE_FUTIMES",
14480
#endif
14481
14482
#ifdef HAVE_FUTIMESAT
14483
    "HAVE_FUTIMESAT",
14484
#endif
14485
14486
#ifdef HAVE_LINKAT
14487
    "HAVE_LINKAT",
14488
#endif
14489
14490
#ifdef HAVE_LCHFLAGS
14491
    "HAVE_LCHFLAGS",
14492
#endif
14493
14494
#ifdef HAVE_LCHMOD
14495
    "HAVE_LCHMOD",
14496
#endif
14497
14498
#ifdef HAVE_LCHOWN
14499
    "HAVE_LCHOWN",
14500
#endif
14501
14502
#ifdef HAVE_LSTAT
14503
    "HAVE_LSTAT",
14504
#endif
14505
14506
#ifdef HAVE_LUTIMES
14507
    "HAVE_LUTIMES",
14508
#endif
14509
14510
#ifdef HAVE_MEMFD_CREATE
14511
    "HAVE_MEMFD_CREATE",
14512
#endif
14513
14514
#ifdef HAVE_MKDIRAT
14515
    "HAVE_MKDIRAT",
14516
#endif
14517
14518
#ifdef HAVE_MKFIFOAT
14519
    "HAVE_MKFIFOAT",
14520
#endif
14521
14522
#ifdef HAVE_MKNODAT
14523
    "HAVE_MKNODAT",
14524
#endif
14525
14526
#ifdef HAVE_OPENAT
14527
    "HAVE_OPENAT",
14528
#endif
14529
14530
#ifdef HAVE_READLINKAT
14531
    "HAVE_READLINKAT",
14532
#endif
14533
14534
#ifdef HAVE_RENAMEAT
14535
    "HAVE_RENAMEAT",
14536
#endif
14537
14538
#ifdef HAVE_SYMLINKAT
14539
    "HAVE_SYMLINKAT",
14540
#endif
14541
14542
#ifdef HAVE_UNLINKAT
14543
    "HAVE_UNLINKAT",
14544
#endif
14545
14546
#ifdef HAVE_UTIMENSAT
14547
    "HAVE_UTIMENSAT",
14548
#endif
14549
14550
#ifdef MS_WINDOWS
14551
    "MS_WINDOWS",
14552
#endif
14553
14554
    NULL
14555
};
14556
14557
14558
PyMODINIT_FUNC
14559
INITFUNC(void)
14560
14
{
14561
14
    PyObject *m, *v;
14562
14
    PyObject *list;
14563
14
    const char * const *trace;
14564
14565
14
    m = PyModule_Create(&posixmodule);
14566
14
    if (m == NULL)
14567
0
        return NULL;
14568
14569
    /* Initialize environ dictionary */
14570
14
    v = convertenviron();
14571
14
    Py_XINCREF(v);
14572
14
    if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
14573
0
        return NULL;
14574
14
    Py_DECREF(v);
14575
14576
14
    if (all_ins(m))
14577
0
        return NULL;
14578
14579
14
    if (setup_confname_tables(m))
14580
0
        return NULL;
14581
14582
14
    Py_INCREF(PyExc_OSError);
14583
14
    PyModule_AddObject(m, "error", PyExc_OSError);
14584
14585
14
#ifdef HAVE_PUTENV
14586
14
    if (posix_putenv_garbage == NULL)
14587
14
        posix_putenv_garbage = PyDict_New();
14588
14
#endif
14589
14590
14
    if (!initialized) {
14591
14
#if defined(HAVE_WAITID) && !defined(__APPLE__)
14592
14
        waitid_result_desc.name = MODNAME ".waitid_result";
14593
14
        WaitidResultType = PyStructSequence_NewType(&waitid_result_desc);
14594
14
        if (WaitidResultType == NULL) {
14595
0
            return NULL;
14596
0
        }
14597
14
#endif
14598
14599
14
        stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
14600
14
        stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
14601
14
        stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
14602
14
        stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
14603
14
        StatResultType = PyStructSequence_NewType(&stat_result_desc);
14604
14
        if (StatResultType == NULL) {
14605
0
            return NULL;
14606
0
        }
14607
14
        structseq_new = StatResultType->tp_new;
14608
14
        StatResultType->tp_new = statresult_new;
14609
14610
14
        statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
14611
14
        StatVFSResultType = PyStructSequence_NewType(&statvfs_result_desc);
14612
14
        if (StatVFSResultType == NULL) {
14613
0
            return NULL;
14614
0
        }
14615
14
#ifdef NEED_TICKS_PER_SECOND
14616
14
#  if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
14617
14
        ticks_per_second = sysconf(_SC_CLK_TCK);
14618
#  elif defined(HZ)
14619
        ticks_per_second = HZ;
14620
#  else
14621
        ticks_per_second = 60; /* magic fallback value; may be bogus */
14622
#  endif
14623
14
#endif
14624
14625
14
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
14626
14
        sched_param_desc.name = MODNAME ".sched_param";
14627
14
        SchedParamType = PyStructSequence_NewType(&sched_param_desc);
14628
14
        if (SchedParamType == NULL) {
14629
0
            return NULL;
14630
0
        }
14631
14
        SchedParamType->tp_new = os_sched_param;
14632
14
#endif
14633
14634
        /* initialize TerminalSize_info */
14635
14
        TerminalSizeType = PyStructSequence_NewType(&TerminalSize_desc);
14636
14
        if (TerminalSizeType == NULL) {
14637
0
            return NULL;
14638
0
        }
14639
14640
        /* initialize scandir types */
14641
14
        if (PyType_Ready(&ScandirIteratorType) < 0)
14642
0
            return NULL;
14643
14
        if (PyType_Ready(&DirEntryType) < 0)
14644
0
            return NULL;
14645
14
    }
14646
14
#if defined(HAVE_WAITID) && !defined(__APPLE__)
14647
14
    Py_INCREF((PyObject*) WaitidResultType);
14648
14
    PyModule_AddObject(m, "waitid_result", (PyObject*) WaitidResultType);
14649
14
#endif
14650
14
    Py_INCREF((PyObject*) StatResultType);
14651
14
    PyModule_AddObject(m, "stat_result", (PyObject*) StatResultType);
14652
14
    Py_INCREF((PyObject*) StatVFSResultType);
14653
14
    PyModule_AddObject(m, "statvfs_result",
14654
14
                       (PyObject*) StatVFSResultType);
14655
14656
14
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER)
14657
14
    Py_INCREF(SchedParamType);
14658
14
    PyModule_AddObject(m, "sched_param", (PyObject *)SchedParamType);
14659
14
#endif
14660
14661
14
    times_result_desc.name = MODNAME ".times_result";
14662
14
    TimesResultType = PyStructSequence_NewType(&times_result_desc);
14663
14
    if (TimesResultType == NULL) {
14664
0
        return NULL;
14665
0
    }
14666
14
    PyModule_AddObject(m, "times_result", (PyObject *)TimesResultType);
14667
14668
14
    uname_result_desc.name = MODNAME ".uname_result";
14669
14
    UnameResultType = PyStructSequence_NewType(&uname_result_desc);
14670
14
    if (UnameResultType == NULL) {
14671
0
        return NULL;
14672
0
    }
14673
14
    PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
14674
14675
#ifdef __APPLE__
14676
    /*
14677
     * Step 2 of weak-linking support on Mac OS X.
14678
     *
14679
     * The code below removes functions that are not available on the
14680
     * currently active platform.
14681
     *
14682
     * This block allow one to use a python binary that was build on
14683
     * OSX 10.4 on OSX 10.3, without losing access to new APIs on
14684
     * OSX 10.4.
14685
     */
14686
#ifdef HAVE_FSTATVFS
14687
    if (fstatvfs == NULL) {
14688
        if (PyObject_DelAttrString(m, "fstatvfs") == -1) {
14689
            return NULL;
14690
        }
14691
    }
14692
#endif /* HAVE_FSTATVFS */
14693
14694
#ifdef HAVE_STATVFS
14695
    if (statvfs == NULL) {
14696
        if (PyObject_DelAttrString(m, "statvfs") == -1) {
14697
            return NULL;
14698
        }
14699
    }
14700
#endif /* HAVE_STATVFS */
14701
14702
# ifdef HAVE_LCHOWN
14703
    if (lchown == NULL) {
14704
        if (PyObject_DelAttrString(m, "lchown") == -1) {
14705
            return NULL;
14706
        }
14707
    }
14708
#endif /* HAVE_LCHOWN */
14709
14710
14711
#endif /* __APPLE__ */
14712
14713
14
    Py_INCREF(TerminalSizeType);
14714
14
    PyModule_AddObject(m, "terminal_size", (PyObject*)TerminalSizeType);
14715
14716
14
    billion = PyLong_FromLong(1000000000);
14717
14
    if (!billion)
14718
0
        return NULL;
14719
14720
    /* suppress "function not used" warnings */
14721
14
    {
14722
14
    int ignored;
14723
14
    fd_specified("", -1);
14724
14
    follow_symlinks_specified("", 1);
14725
14
    dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
14726
14
    dir_fd_converter(Py_None, &ignored);
14727
14
    dir_fd_unavailable(Py_None, &ignored);
14728
14
    }
14729
14730
    /*
14731
     * provide list of locally available functions
14732
     * so os.py can populate support_* lists
14733
     */
14734
14
    list = PyList_New(0);
14735
14
    if (!list)
14736
0
        return NULL;
14737
420
    for (trace = have_functions; *trace; trace++) {
14738
406
        PyObject *unicode = PyUnicode_DecodeASCII(*trace, strlen(*trace), NULL);
14739
406
        if (!unicode)
14740
0
            return NULL;
14741
406
        if (PyList_Append(list, unicode))
14742
0
            return NULL;
14743
406
        Py_DECREF(unicode);
14744
406
    }
14745
14
    PyModule_AddObject(m, "_have_functions", list);
14746
14747
14
    Py_INCREF((PyObject *) &DirEntryType);
14748
14
    PyModule_AddObject(m, "DirEntry", (PyObject *)&DirEntryType);
14749
14750
14
    initialized = 1;
14751
14752
14
    return m;
14753
14
}
14754
14755
#ifdef __cplusplus
14756
}
14757
#endif