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