ยปCore Development>Code coverage>Modules/posixmodule.c

Python code coverage for Modules/posixmodule.c

#countcontent
1n/a
2n/a/* POSIX module implementation */
3n/a
4n/a/* This file is also used for Windows NT/MS-Win. In that case the
5n/a module actually calls itself 'nt', not 'posix', and a few
6n/a functions are either unimplemented or implemented differently. The source
7n/a assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
8n/a of the compiler used. Different compilers define their own feature
9n/a test macro, e.g. '_MSC_VER'. */
10n/a
11n/a
12n/a
13n/a#ifdef __APPLE__
14n/a /*
15n/a * Step 1 of support for weak-linking a number of symbols existing on
16n/a * OSX 10.4 and later, see the comment in the #ifdef __APPLE__ block
17n/a * at the end of this file for more information.
18n/a */
19n/a# pragma weak lchown
20n/a# pragma weak statvfs
21n/a# pragma weak fstatvfs
22n/a
23n/a#endif /* __APPLE__ */
24n/a
25n/a#define PY_SSIZE_T_CLEAN
26n/a
27n/a#include "Python.h"
28n/a#include "structmember.h"
29n/a#ifndef MS_WINDOWS
30n/a#include "posixmodule.h"
31n/a#else
32n/a#include "winreparse.h"
33n/a#endif
34n/a
35n/a/* On android API level 21, 'AT_EACCESS' is not declared although
36n/a * HAVE_FACCESSAT is defined. */
37n/a#ifdef __ANDROID__
38n/a#undef HAVE_FACCESSAT
39n/a#endif
40n/a
41n/a#include <stdio.h> /* needed for ctermid() */
42n/a
43n/a#ifdef __cplusplus
44n/aextern "C" {
45n/a#endif
46n/a
47n/aPyDoc_STRVAR(posix__doc__,
48n/a"This module provides access to operating system functionality that is\n\
49n/astandardized by the C Standard and the POSIX standard (a thinly\n\
50n/adisguised Unix interface). Refer to the library manual and\n\
51n/acorresponding Unix manual entries for more information on calls.");
52n/a
53n/a
54n/a#ifdef HAVE_SYS_UIO_H
55n/a#include <sys/uio.h>
56n/a#endif
57n/a
58n/a#ifdef HAVE_SYS_TYPES_H
59n/a#include <sys/types.h>
60n/a#endif /* HAVE_SYS_TYPES_H */
61n/a
62n/a#ifdef HAVE_SYS_STAT_H
63n/a#include <sys/stat.h>
64n/a#endif /* HAVE_SYS_STAT_H */
65n/a
66n/a#ifdef HAVE_SYS_WAIT_H
67n/a#include <sys/wait.h> /* For WNOHANG */
68n/a#endif
69n/a
70n/a#ifdef HAVE_SIGNAL_H
71n/a#include <signal.h>
72n/a#endif
73n/a
74n/a#ifdef HAVE_FCNTL_H
75n/a#include <fcntl.h>
76n/a#endif /* HAVE_FCNTL_H */
77n/a
78n/a#ifdef HAVE_GRP_H
79n/a#include <grp.h>
80n/a#endif
81n/a
82n/a#ifdef HAVE_SYSEXITS_H
83n/a#include <sysexits.h>
84n/a#endif /* HAVE_SYSEXITS_H */
85n/a
86n/a#ifdef HAVE_SYS_LOADAVG_H
87n/a#include <sys/loadavg.h>
88n/a#endif
89n/a
90n/a#ifdef HAVE_LANGINFO_H
91n/a#include <langinfo.h>
92n/a#endif
93n/a
94n/a#ifdef HAVE_SYS_SENDFILE_H
95n/a#include <sys/sendfile.h>
96n/a#endif
97n/a
98n/a#ifdef HAVE_SCHED_H
99n/a#include <sched.h>
100n/a#endif
101n/a
102n/a#if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
103n/a#undef HAVE_SCHED_SETAFFINITY
104n/a#endif
105n/a
106n/a#if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
107n/a#define USE_XATTRS
108n/a#endif
109n/a
110n/a#ifdef USE_XATTRS
111n/a#include <sys/xattr.h>
112n/a#endif
113n/a
114n/a#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
115n/a#ifdef HAVE_SYS_SOCKET_H
116n/a#include <sys/socket.h>
117n/a#endif
118n/a#endif
119n/a
120n/a#ifdef HAVE_DLFCN_H
121n/a#include <dlfcn.h>
122n/a#endif
123n/a
124n/a#ifdef __hpux
125n/a#include <sys/mpctl.h>
126n/a#endif
127n/a
128n/a#if defined(__DragonFly__) || \
129n/a defined(__OpenBSD__) || \
130n/a defined(__FreeBSD__) || \
131n/a defined(__NetBSD__) || \
132n/a defined(__APPLE__)
133n/a#include <sys/sysctl.h>
134n/a#endif
135n/a
136n/a#ifdef HAVE_LINUX_RANDOM_H
137n/a# include <linux/random.h>
138n/a#endif
139n/a#ifdef HAVE_GETRANDOM_SYSCALL
140n/a# include <sys/syscall.h>
141n/a#endif
142n/a
143n/a#if defined(MS_WINDOWS)
144n/a# define TERMSIZE_USE_CONIO
145n/a#elif defined(HAVE_SYS_IOCTL_H)
146n/a# include <sys/ioctl.h>
147n/a# if defined(HAVE_TERMIOS_H)
148n/a# include <termios.h>
149n/a# endif
150n/a# if defined(TIOCGWINSZ)
151n/a# define TERMSIZE_USE_IOCTL
152n/a# endif
153n/a#endif /* MS_WINDOWS */
154n/a
155n/a/* Various compilers have only certain posix functions */
156n/a/* XXX Gosh I wish these were all moved into pyconfig.h */
157n/a#if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */
158n/a#define HAVE_OPENDIR 1
159n/a#define HAVE_SYSTEM 1
160n/a#include <process.h>
161n/a#else
162n/a#ifdef _MSC_VER /* Microsoft compiler */
163n/a#define HAVE_GETPPID 1
164n/a#define HAVE_GETLOGIN 1
165n/a#define HAVE_SPAWNV 1
166n/a#define HAVE_EXECV 1
167n/a#define HAVE_WSPAWNV 1
168n/a#define HAVE_WEXECV 1
169n/a#define HAVE_PIPE 1
170n/a#define HAVE_SYSTEM 1
171n/a#define HAVE_CWAIT 1
172n/a#define HAVE_FSYNC 1
173n/a#define fsync _commit
174n/a#else
175n/a/* Unix functions that the configure script doesn't check for */
176n/a#define HAVE_EXECV 1
177n/a#define HAVE_FORK 1
178n/a#if defined(__USLC__) && defined(__SCO_VERSION__) /* SCO UDK Compiler */
179n/a#define HAVE_FORK1 1
180n/a#endif
181n/a#define HAVE_GETEGID 1
182n/a#define HAVE_GETEUID 1
183n/a#define HAVE_GETGID 1
184n/a#define HAVE_GETPPID 1
185n/a#define HAVE_GETUID 1
186n/a#define HAVE_KILL 1
187n/a#define HAVE_OPENDIR 1
188n/a#define HAVE_PIPE 1
189n/a#define HAVE_SYSTEM 1
190n/a#define HAVE_WAIT 1
191n/a#define HAVE_TTYNAME 1
192n/a#endif /* _MSC_VER */
193n/a#endif /* ! __WATCOMC__ || __QNX__ */
194n/a
195n/a
196n/a/*[clinic input]
197n/a# one of the few times we lie about this name!
198n/amodule os
199n/a[clinic start generated code]*/
200n/a/*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
201n/a
202n/a#ifndef _MSC_VER
203n/a
204n/a#if defined(__sgi)&&_COMPILER_VERSION>=700
205n/a/* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
206n/a (default) */
207n/aextern char *ctermid_r(char *);
208n/a#endif
209n/a
210n/a#ifndef HAVE_UNISTD_H
211n/a#if defined(PYCC_VACPP)
212n/aextern int mkdir(char *);
213n/a#else
214n/a#if ( defined(__WATCOMC__) || defined(_MSC_VER) ) && !defined(__QNX__)
215n/aextern int mkdir(const char *);
216n/a#else
217n/aextern int mkdir(const char *, mode_t);
218n/a#endif
219n/a#endif
220n/a#if defined(__IBMC__) || defined(__IBMCPP__)
221n/aextern int chdir(char *);
222n/aextern int rmdir(char *);
223n/a#else
224n/aextern int chdir(const char *);
225n/aextern int rmdir(const char *);
226n/a#endif
227n/aextern int chmod(const char *, mode_t);
228n/a/*#ifdef HAVE_FCHMOD
229n/aextern int fchmod(int, mode_t);
230n/a#endif*/
231n/a/*#ifdef HAVE_LCHMOD
232n/aextern int lchmod(const char *, mode_t);
233n/a#endif*/
234n/aextern int chown(const char *, uid_t, gid_t);
235n/aextern char *getcwd(char *, int);
236n/aextern char *strerror(int);
237n/aextern int link(const char *, const char *);
238n/aextern int rename(const char *, const char *);
239n/aextern int stat(const char *, struct stat *);
240n/aextern int unlink(const char *);
241n/a#ifdef HAVE_SYMLINK
242n/aextern int symlink(const char *, const char *);
243n/a#endif /* HAVE_SYMLINK */
244n/a#ifdef HAVE_LSTAT
245n/aextern int lstat(const char *, struct stat *);
246n/a#endif /* HAVE_LSTAT */
247n/a#endif /* !HAVE_UNISTD_H */
248n/a
249n/a#endif /* !_MSC_VER */
250n/a
251n/a#ifdef HAVE_UTIME_H
252n/a#include <utime.h>
253n/a#endif /* HAVE_UTIME_H */
254n/a
255n/a#ifdef HAVE_SYS_UTIME_H
256n/a#include <sys/utime.h>
257n/a#define HAVE_UTIME_H /* pretend we do for the rest of this file */
258n/a#endif /* HAVE_SYS_UTIME_H */
259n/a
260n/a#ifdef HAVE_SYS_TIMES_H
261n/a#include <sys/times.h>
262n/a#endif /* HAVE_SYS_TIMES_H */
263n/a
264n/a#ifdef HAVE_SYS_PARAM_H
265n/a#include <sys/param.h>
266n/a#endif /* HAVE_SYS_PARAM_H */
267n/a
268n/a#ifdef HAVE_SYS_UTSNAME_H
269n/a#include <sys/utsname.h>
270n/a#endif /* HAVE_SYS_UTSNAME_H */
271n/a
272n/a#ifdef HAVE_DIRENT_H
273n/a#include <dirent.h>
274n/a#define NAMLEN(dirent) strlen((dirent)->d_name)
275n/a#else
276n/a#if defined(__WATCOMC__) && !defined(__QNX__)
277n/a#include <direct.h>
278n/a#define NAMLEN(dirent) strlen((dirent)->d_name)
279n/a#else
280n/a#define dirent direct
281n/a#define NAMLEN(dirent) (dirent)->d_namlen
282n/a#endif
283n/a#ifdef HAVE_SYS_NDIR_H
284n/a#include <sys/ndir.h>
285n/a#endif
286n/a#ifdef HAVE_SYS_DIR_H
287n/a#include <sys/dir.h>
288n/a#endif
289n/a#ifdef HAVE_NDIR_H
290n/a#include <ndir.h>
291n/a#endif
292n/a#endif
293n/a
294n/a#ifdef _MSC_VER
295n/a#ifdef HAVE_DIRECT_H
296n/a#include <direct.h>
297n/a#endif
298n/a#ifdef HAVE_IO_H
299n/a#include <io.h>
300n/a#endif
301n/a#ifdef HAVE_PROCESS_H
302n/a#include <process.h>
303n/a#endif
304n/a#ifndef VOLUME_NAME_DOS
305n/a#define VOLUME_NAME_DOS 0x0
306n/a#endif
307n/a#ifndef VOLUME_NAME_NT
308n/a#define VOLUME_NAME_NT 0x2
309n/a#endif
310n/a#ifndef IO_REPARSE_TAG_SYMLINK
311n/a#define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
312n/a#endif
313n/a#ifndef IO_REPARSE_TAG_MOUNT_POINT
314n/a#define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
315n/a#endif
316n/a#include "osdefs.h"
317n/a#include <malloc.h>
318n/a#include <windows.h>
319n/a#include <shellapi.h> /* for ShellExecute() */
320n/a#include <lmcons.h> /* for UNLEN */
321n/a#ifdef SE_CREATE_SYMBOLIC_LINK_NAME /* Available starting with Vista */
322n/a#define HAVE_SYMLINK
323n/astatic int win32_can_symlink = 0;
324n/a#endif
325n/a#endif /* _MSC_VER */
326n/a
327n/a#ifndef MAXPATHLEN
328n/a#if defined(PATH_MAX) && PATH_MAX > 1024
329n/a#define MAXPATHLEN PATH_MAX
330n/a#else
331n/a#define MAXPATHLEN 1024
332n/a#endif
333n/a#endif /* MAXPATHLEN */
334n/a
335n/a#ifdef UNION_WAIT
336n/a/* Emulate some macros on systems that have a union instead of macros */
337n/a
338n/a#ifndef WIFEXITED
339n/a#define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
340n/a#endif
341n/a
342n/a#ifndef WEXITSTATUS
343n/a#define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
344n/a#endif
345n/a
346n/a#ifndef WTERMSIG
347n/a#define WTERMSIG(u_wait) ((u_wait).w_termsig)
348n/a#endif
349n/a
350n/a#define WAIT_TYPE union wait
351n/a#define WAIT_STATUS_INT(s) (s.w_status)
352n/a
353n/a#else /* !UNION_WAIT */
354n/a#define WAIT_TYPE int
355n/a#define WAIT_STATUS_INT(s) (s)
356n/a#endif /* UNION_WAIT */
357n/a
358n/a/* Don't use the "_r" form if we don't need it (also, won't have a
359n/a prototype for it, at least on Solaris -- maybe others as well?). */
360n/a#if defined(HAVE_CTERMID_R) && defined(WITH_THREAD)
361n/a#define USE_CTERMID_R
362n/a#endif
363n/a
364n/a/* choose the appropriate stat and fstat functions and return structs */
365n/a#undef STAT
366n/a#undef FSTAT
367n/a#undef STRUCT_STAT
368n/a#ifdef MS_WINDOWS
369n/a# define STAT win32_stat
370n/a# define LSTAT win32_lstat
371n/a# define FSTAT _Py_fstat_noraise
372n/a# define STRUCT_STAT struct _Py_stat_struct
373n/a#else
374n/a# define STAT stat
375n/a# define LSTAT lstat
376n/a# define FSTAT fstat
377n/a# define STRUCT_STAT struct stat
378n/a#endif
379n/a
380n/a#if defined(MAJOR_IN_MKDEV)
381n/a#include <sys/mkdev.h>
382n/a#else
383n/a#if defined(MAJOR_IN_SYSMACROS)
384n/a#include <sys/sysmacros.h>
385n/a#endif
386n/a#if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
387n/a#include <sys/mkdev.h>
388n/a#endif
389n/a#endif
390n/a
391n/a#define DWORD_MAX 4294967295U
392n/a
393n/a#ifdef MS_WINDOWS
394n/a#define INITFUNC PyInit_nt
395n/a#define MODNAME "nt"
396n/a#else
397n/a#define INITFUNC PyInit_posix
398n/a#define MODNAME "posix"
399n/a#endif
400n/a
401n/a#ifdef MS_WINDOWS
402n/a/* defined in fileutils.c */
403n/aPyAPI_FUNC(void) _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
404n/aPyAPI_FUNC(void) _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,
405n/a ULONG, struct _Py_stat_struct *);
406n/a#endif
407n/a
408n/a#ifdef MS_WINDOWS
409n/astatic int
410n/awin32_warn_bytes_api()
411n/a{
412n/a return PyErr_WarnEx(PyExc_DeprecationWarning,
413n/a "The Windows bytes API has been deprecated, "
414n/a "use Unicode filenames instead",
415n/a 1);
416n/a}
417n/a#endif
418n/a
419n/a
420n/a#ifndef MS_WINDOWS
421n/aPyObject *
422n/a_PyLong_FromUid(uid_t uid)
423n/a{
424n/a if (uid == (uid_t)-1)
425n/a return PyLong_FromLong(-1);
426n/a return PyLong_FromUnsignedLong(uid);
427n/a}
428n/a
429n/aPyObject *
430n/a_PyLong_FromGid(gid_t gid)
431n/a{
432n/a if (gid == (gid_t)-1)
433n/a return PyLong_FromLong(-1);
434n/a return PyLong_FromUnsignedLong(gid);
435n/a}
436n/a
437n/aint
438n/a_Py_Uid_Converter(PyObject *obj, void *p)
439n/a{
440n/a uid_t uid;
441n/a PyObject *index;
442n/a int overflow;
443n/a long result;
444n/a unsigned long uresult;
445n/a
446n/a index = PyNumber_Index(obj);
447n/a if (index == NULL) {
448n/a PyErr_Format(PyExc_TypeError,
449n/a "uid should be integer, not %.200s",
450n/a Py_TYPE(obj)->tp_name);
451n/a return 0;
452n/a }
453n/a
454n/a /*
455n/a * Handling uid_t is complicated for two reasons:
456n/a * * Although uid_t is (always?) unsigned, it still
457n/a * accepts -1.
458n/a * * We don't know its size in advance--it may be
459n/a * bigger than an int, or it may be smaller than
460n/a * a long.
461n/a *
462n/a * So a bit of defensive programming is in order.
463n/a * Start with interpreting the value passed
464n/a * in as a signed long and see if it works.
465n/a */
466n/a
467n/a result = PyLong_AsLongAndOverflow(index, &overflow);
468n/a
469n/a if (!overflow) {
470n/a uid = (uid_t)result;
471n/a
472n/a if (result == -1) {
473n/a if (PyErr_Occurred())
474n/a goto fail;
475n/a /* It's a legitimate -1, we're done. */
476n/a goto success;
477n/a }
478n/a
479n/a /* Any other negative number is disallowed. */
480n/a if (result < 0)
481n/a goto underflow;
482n/a
483n/a /* Ensure the value wasn't truncated. */
484n/a if (sizeof(uid_t) < sizeof(long) &&
485n/a (long)uid != result)
486n/a goto underflow;
487n/a goto success;
488n/a }
489n/a
490n/a if (overflow < 0)
491n/a goto underflow;
492n/a
493n/a /*
494n/a * Okay, the value overflowed a signed long. If it
495n/a * fits in an *unsigned* long, it may still be okay,
496n/a * as uid_t may be unsigned long on this platform.
497n/a */
498n/a uresult = PyLong_AsUnsignedLong(index);
499n/a if (PyErr_Occurred()) {
500n/a if (PyErr_ExceptionMatches(PyExc_OverflowError))
501n/a goto overflow;
502n/a goto fail;
503n/a }
504n/a
505n/a uid = (uid_t)uresult;
506n/a
507n/a /*
508n/a * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
509n/a * but this value would get interpreted as (uid_t)-1 by chown
510n/a * and its siblings. That's not what the user meant! So we
511n/a * throw an overflow exception instead. (We already
512n/a * handled a real -1 with PyLong_AsLongAndOverflow() above.)
513n/a */
514n/a if (uid == (uid_t)-1)
515n/a goto overflow;
516n/a
517n/a /* Ensure the value wasn't truncated. */
518n/a if (sizeof(uid_t) < sizeof(long) &&
519n/a (unsigned long)uid != uresult)
520n/a goto overflow;
521n/a /* fallthrough */
522n/a
523n/asuccess:
524n/a Py_DECREF(index);
525n/a *(uid_t *)p = uid;
526n/a return 1;
527n/a
528n/aunderflow:
529n/a PyErr_SetString(PyExc_OverflowError,
530n/a "uid is less than minimum");
531n/a goto fail;
532n/a
533n/aoverflow:
534n/a PyErr_SetString(PyExc_OverflowError,
535n/a "uid is greater than maximum");
536n/a /* fallthrough */
537n/a
538n/afail:
539n/a Py_DECREF(index);
540n/a return 0;
541n/a}
542n/a
543n/aint
544n/a_Py_Gid_Converter(PyObject *obj, void *p)
545n/a{
546n/a gid_t gid;
547n/a PyObject *index;
548n/a int overflow;
549n/a long result;
550n/a unsigned long uresult;
551n/a
552n/a index = PyNumber_Index(obj);
553n/a if (index == NULL) {
554n/a PyErr_Format(PyExc_TypeError,
555n/a "gid should be integer, not %.200s",
556n/a Py_TYPE(obj)->tp_name);
557n/a return 0;
558n/a }
559n/a
560n/a /*
561n/a * Handling gid_t is complicated for two reasons:
562n/a * * Although gid_t is (always?) unsigned, it still
563n/a * accepts -1.
564n/a * * We don't know its size in advance--it may be
565n/a * bigger than an int, or it may be smaller than
566n/a * a long.
567n/a *
568n/a * So a bit of defensive programming is in order.
569n/a * Start with interpreting the value passed
570n/a * in as a signed long and see if it works.
571n/a */
572n/a
573n/a result = PyLong_AsLongAndOverflow(index, &overflow);
574n/a
575n/a if (!overflow) {
576n/a gid = (gid_t)result;
577n/a
578n/a if (result == -1) {
579n/a if (PyErr_Occurred())
580n/a goto fail;
581n/a /* It's a legitimate -1, we're done. */
582n/a goto success;
583n/a }
584n/a
585n/a /* Any other negative number is disallowed. */
586n/a if (result < 0) {
587n/a goto underflow;
588n/a }
589n/a
590n/a /* Ensure the value wasn't truncated. */
591n/a if (sizeof(gid_t) < sizeof(long) &&
592n/a (long)gid != result)
593n/a goto underflow;
594n/a goto success;
595n/a }
596n/a
597n/a if (overflow < 0)
598n/a goto underflow;
599n/a
600n/a /*
601n/a * Okay, the value overflowed a signed long. If it
602n/a * fits in an *unsigned* long, it may still be okay,
603n/a * as gid_t may be unsigned long on this platform.
604n/a */
605n/a uresult = PyLong_AsUnsignedLong(index);
606n/a if (PyErr_Occurred()) {
607n/a if (PyErr_ExceptionMatches(PyExc_OverflowError))
608n/a goto overflow;
609n/a goto fail;
610n/a }
611n/a
612n/a gid = (gid_t)uresult;
613n/a
614n/a /*
615n/a * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
616n/a * but this value would get interpreted as (gid_t)-1 by chown
617n/a * and its siblings. That's not what the user meant! So we
618n/a * throw an overflow exception instead. (We already
619n/a * handled a real -1 with PyLong_AsLongAndOverflow() above.)
620n/a */
621n/a if (gid == (gid_t)-1)
622n/a goto overflow;
623n/a
624n/a /* Ensure the value wasn't truncated. */
625n/a if (sizeof(gid_t) < sizeof(long) &&
626n/a (unsigned long)gid != uresult)
627n/a goto overflow;
628n/a /* fallthrough */
629n/a
630n/asuccess:
631n/a Py_DECREF(index);
632n/a *(gid_t *)p = gid;
633n/a return 1;
634n/a
635n/aunderflow:
636n/a PyErr_SetString(PyExc_OverflowError,
637n/a "gid is less than minimum");
638n/a goto fail;
639n/a
640n/aoverflow:
641n/a PyErr_SetString(PyExc_OverflowError,
642n/a "gid is greater than maximum");
643n/a /* fallthrough */
644n/a
645n/afail:
646n/a Py_DECREF(index);
647n/a return 0;
648n/a}
649n/a#endif /* MS_WINDOWS */
650n/a
651n/a
652n/a#define _PyLong_FromDev PyLong_FromLongLong
653n/a
654n/a
655n/a#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
656n/astatic int
657n/a_Py_Dev_Converter(PyObject *obj, void *p)
658n/a{
659n/a *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj);
660n/a if (PyErr_Occurred())
661n/a return 0;
662n/a return 1;
663n/a}
664n/a#endif /* HAVE_MKNOD && HAVE_MAKEDEV */
665n/a
666n/a
667n/a#ifdef AT_FDCWD
668n/a/*
669n/a * Why the (int) cast? Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
670n/a * without the int cast, the value gets interpreted as uint (4291925331),
671n/a * which doesn't play nicely with all the initializer lines in this file that
672n/a * look like this:
673n/a * int dir_fd = DEFAULT_DIR_FD;
674n/a */
675n/a#define DEFAULT_DIR_FD (int)AT_FDCWD
676n/a#else
677n/a#define DEFAULT_DIR_FD (-100)
678n/a#endif
679n/a
680n/astatic int
681n/a_fd_converter(PyObject *o, int *p)
682n/a{
683n/a int overflow;
684n/a long long_value;
685n/a
686n/a PyObject *index = PyNumber_Index(o);
687n/a if (index == NULL) {
688n/a return 0;
689n/a }
690n/a
691n/a assert(PyLong_Check(index));
692n/a long_value = PyLong_AsLongAndOverflow(index, &overflow);
693n/a Py_DECREF(index);
694n/a assert(!PyErr_Occurred());
695n/a if (overflow > 0 || long_value > INT_MAX) {
696n/a PyErr_SetString(PyExc_OverflowError,
697n/a "fd is greater than maximum");
698n/a return 0;
699n/a }
700n/a if (overflow < 0 || long_value < INT_MIN) {
701n/a PyErr_SetString(PyExc_OverflowError,
702n/a "fd is less than minimum");
703n/a return 0;
704n/a }
705n/a
706n/a *p = (int)long_value;
707n/a return 1;
708n/a}
709n/a
710n/astatic int
711n/adir_fd_converter(PyObject *o, void *p)
712n/a{
713n/a if (o == Py_None) {
714n/a *(int *)p = DEFAULT_DIR_FD;
715n/a return 1;
716n/a }
717n/a else if (PyIndex_Check(o)) {
718n/a return _fd_converter(o, (int *)p);
719n/a }
720n/a else {
721n/a PyErr_Format(PyExc_TypeError,
722n/a "argument should be integer or None, not %.200s",
723n/a Py_TYPE(o)->tp_name);
724n/a return 0;
725n/a }
726n/a}
727n/a
728n/a
729n/a/*
730n/a * A PyArg_ParseTuple "converter" function
731n/a * that handles filesystem paths in the manner
732n/a * preferred by the os module.
733n/a *
734n/a * path_converter accepts (Unicode) strings and their
735n/a * subclasses, and bytes and their subclasses. What
736n/a * it does with the argument depends on the platform:
737n/a *
738n/a * * On Windows, if we get a (Unicode) string we
739n/a * extract the wchar_t * and return it; if we get
740n/a * bytes we decode to wchar_t * and return that.
741n/a *
742n/a * * On all other platforms, strings are encoded
743n/a * to bytes using PyUnicode_FSConverter, then we
744n/a * extract the char * from the bytes object and
745n/a * return that.
746n/a *
747n/a * path_converter also optionally accepts signed
748n/a * integers (representing open file descriptors) instead
749n/a * of path strings.
750n/a *
751n/a * Input fields:
752n/a * path.nullable
753n/a * If nonzero, the path is permitted to be None.
754n/a * path.allow_fd
755n/a * If nonzero, the path is permitted to be a file handle
756n/a * (a signed int) instead of a string.
757n/a * path.function_name
758n/a * If non-NULL, path_converter will use that as the name
759n/a * of the function in error messages.
760n/a * (If path.function_name is NULL it omits the function name.)
761n/a * path.argument_name
762n/a * If non-NULL, path_converter will use that as the name
763n/a * of the parameter in error messages.
764n/a * (If path.argument_name is NULL it uses "path".)
765n/a *
766n/a * Output fields:
767n/a * path.wide
768n/a * Points to the path if it was expressed as Unicode
769n/a * and was not encoded. (Only used on Windows.)
770n/a * path.narrow
771n/a * Points to the path if it was expressed as bytes,
772n/a * or it was Unicode and was encoded to bytes. (On Windows,
773n/a * is a non-zero integer if the path was expressed as bytes.
774n/a * The type is deliberately incompatible to prevent misuse.)
775n/a * path.fd
776n/a * Contains a file descriptor if path.accept_fd was true
777n/a * and the caller provided a signed integer instead of any
778n/a * sort of string.
779n/a *
780n/a * WARNING: if your "path" parameter is optional, and is
781n/a * unspecified, path_converter will never get called.
782n/a * So if you set allow_fd, you *MUST* initialize path.fd = -1
783n/a * yourself!
784n/a * path.length
785n/a * The length of the path in characters, if specified as
786n/a * a string.
787n/a * path.object
788n/a * The original object passed in (if get a PathLike object,
789n/a * the result of PyOS_FSPath() is treated as the original object).
790n/a * Own a reference to the object.
791n/a * path.cleanup
792n/a * For internal use only. May point to a temporary object.
793n/a * (Pay no attention to the man behind the curtain.)
794n/a *
795n/a * At most one of path.wide or path.narrow will be non-NULL.
796n/a * If path was None and path.nullable was set,
797n/a * or if path was an integer and path.allow_fd was set,
798n/a * both path.wide and path.narrow will be NULL
799n/a * and path.length will be 0.
800n/a *
801n/a * path_converter takes care to not write to the path_t
802n/a * unless it's successful. However it must reset the
803n/a * "cleanup" field each time it's called.
804n/a *
805n/a * Use as follows:
806n/a * path_t path;
807n/a * memset(&path, 0, sizeof(path));
808n/a * PyArg_ParseTuple(args, "O&", path_converter, &path);
809n/a * // ... use values from path ...
810n/a * path_cleanup(&path);
811n/a *
812n/a * (Note that if PyArg_Parse fails you don't need to call
813n/a * path_cleanup(). However it is safe to do so.)
814n/a */
815n/atypedef struct {
816n/a const char *function_name;
817n/a const char *argument_name;
818n/a int nullable;
819n/a int allow_fd;
820n/a const wchar_t *wide;
821n/a#ifdef MS_WINDOWS
822n/a BOOL narrow;
823n/a#else
824n/a const char *narrow;
825n/a#endif
826n/a int fd;
827n/a Py_ssize_t length;
828n/a PyObject *object;
829n/a PyObject *cleanup;
830n/a} path_t;
831n/a
832n/a#ifdef MS_WINDOWS
833n/a#define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
834n/a {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL}
835n/a#else
836n/a#define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
837n/a {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL}
838n/a#endif
839n/a
840n/astatic void
841n/apath_cleanup(path_t *path)
842n/a{
843n/a Py_CLEAR(path->object);
844n/a Py_CLEAR(path->cleanup);
845n/a}
846n/a
847n/astatic int
848n/apath_converter(PyObject *o, void *p)
849n/a{
850n/a path_t *path = (path_t *)p;
851n/a PyObject *bytes = NULL;
852n/a Py_ssize_t length = 0;
853n/a int is_index, is_buffer, is_bytes, is_unicode;
854n/a const char *narrow;
855n/a#ifdef MS_WINDOWS
856n/a PyObject *wo = NULL;
857n/a const wchar_t *wide;
858n/a#endif
859n/a
860n/a#define FORMAT_EXCEPTION(exc, fmt) \
861n/a PyErr_Format(exc, "%s%s" fmt, \
862n/a path->function_name ? path->function_name : "", \
863n/a path->function_name ? ": " : "", \
864n/a path->argument_name ? path->argument_name : "path")
865n/a
866n/a /* Py_CLEANUP_SUPPORTED support */
867n/a if (o == NULL) {
868n/a path_cleanup(path);
869n/a return 1;
870n/a }
871n/a
872n/a /* Ensure it's always safe to call path_cleanup(). */
873n/a path->object = path->cleanup = NULL;
874n/a /* path->object owns a reference to the original object */
875n/a Py_INCREF(o);
876n/a
877n/a if ((o == Py_None) && path->nullable) {
878n/a path->wide = NULL;
879n/a#ifdef MS_WINDOWS
880n/a path->narrow = FALSE;
881n/a#else
882n/a path->narrow = NULL;
883n/a#endif
884n/a path->fd = -1;
885n/a goto success_exit;
886n/a }
887n/a
888n/a /* Only call this here so that we don't treat the return value of
889n/a os.fspath() as an fd or buffer. */
890n/a is_index = path->allow_fd && PyIndex_Check(o);
891n/a is_buffer = PyObject_CheckBuffer(o);
892n/a is_bytes = PyBytes_Check(o);
893n/a is_unicode = PyUnicode_Check(o);
894n/a
895n/a if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
896n/a /* Inline PyOS_FSPath() for better error messages. */
897n/a _Py_IDENTIFIER(__fspath__);
898n/a PyObject *func = NULL;
899n/a
900n/a func = _PyObject_LookupSpecial(o, &PyId___fspath__);
901n/a if (NULL == func) {
902n/a goto error_format;
903n/a }
904n/a /* still owns a reference to the original object */
905n/a Py_DECREF(o);
906n/a o = _PyObject_CallNoArg(func);
907n/a Py_DECREF(func);
908n/a if (NULL == o) {
909n/a goto error_exit;
910n/a }
911n/a else if (PyUnicode_Check(o)) {
912n/a is_unicode = 1;
913n/a }
914n/a else if (PyBytes_Check(o)) {
915n/a is_bytes = 1;
916n/a }
917n/a else {
918n/a goto error_format;
919n/a }
920n/a }
921n/a
922n/a if (is_unicode) {
923n/a#ifdef MS_WINDOWS
924n/a wide = PyUnicode_AsUnicodeAndSize(o, &length);
925n/a if (!wide) {
926n/a goto error_exit;
927n/a }
928n/a if (length > 32767) {
929n/a FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
930n/a goto error_exit;
931n/a }
932n/a if (wcslen(wide) != length) {
933n/a FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
934n/a goto error_exit;
935n/a }
936n/a
937n/a path->wide = wide;
938n/a path->narrow = FALSE;
939n/a path->fd = -1;
940n/a goto success_exit;
941n/a#else
942n/a if (!PyUnicode_FSConverter(o, &bytes)) {
943n/a goto error_exit;
944n/a }
945n/a#endif
946n/a }
947n/a else if (is_bytes) {
948n/a bytes = o;
949n/a Py_INCREF(bytes);
950n/a }
951n/a else if (is_buffer) {
952n/a if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
953n/a "%s%s%s should be %s, not %.200s",
954n/a path->function_name ? path->function_name : "",
955n/a path->function_name ? ": " : "",
956n/a path->argument_name ? path->argument_name : "path",
957n/a path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
958n/a "integer or None" :
959n/a path->allow_fd ? "string, bytes, os.PathLike or integer" :
960n/a path->nullable ? "string, bytes, os.PathLike or None" :
961n/a "string, bytes or os.PathLike",
962n/a Py_TYPE(o)->tp_name)) {
963n/a goto error_exit;
964n/a }
965n/a bytes = PyBytes_FromObject(o);
966n/a if (!bytes) {
967n/a goto error_exit;
968n/a }
969n/a }
970n/a else if (is_index) {
971n/a if (!_fd_converter(o, &path->fd)) {
972n/a goto error_exit;
973n/a }
974n/a path->wide = NULL;
975n/a#ifdef MS_WINDOWS
976n/a path->narrow = FALSE;
977n/a#else
978n/a path->narrow = NULL;
979n/a#endif
980n/a goto success_exit;
981n/a }
982n/a else {
983n/a error_format:
984n/a PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
985n/a path->function_name ? path->function_name : "",
986n/a path->function_name ? ": " : "",
987n/a path->argument_name ? path->argument_name : "path",
988n/a path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
989n/a "integer or None" :
990n/a path->allow_fd ? "string, bytes, os.PathLike or integer" :
991n/a path->nullable ? "string, bytes, os.PathLike or None" :
992n/a "string, bytes or os.PathLike",
993n/a Py_TYPE(o)->tp_name);
994n/a goto error_exit;
995n/a }
996n/a
997n/a length = PyBytes_GET_SIZE(bytes);
998n/a narrow = PyBytes_AS_STRING(bytes);
999n/a if ((size_t)length != strlen(narrow)) {
1000n/a FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1001n/a goto error_exit;
1002n/a }
1003n/a
1004n/a#ifdef MS_WINDOWS
1005n/a wo = PyUnicode_DecodeFSDefaultAndSize(
1006n/a narrow,
1007n/a length
1008n/a );
1009n/a if (!wo) {
1010n/a goto error_exit;
1011n/a }
1012n/a
1013n/a wide = PyUnicode_AsUnicodeAndSize(wo, &length);
1014n/a if (!wide) {
1015n/a goto error_exit;
1016n/a }
1017n/a if (length > 32767) {
1018n/a FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1019n/a goto error_exit;
1020n/a }
1021n/a if (wcslen(wide) != length) {
1022n/a FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1023n/a goto error_exit;
1024n/a }
1025n/a path->wide = wide;
1026n/a path->narrow = TRUE;
1027n/a path->cleanup = wo;
1028n/a Py_DECREF(bytes);
1029n/a#else
1030n/a path->wide = NULL;
1031n/a path->narrow = narrow;
1032n/a if (bytes == o) {
1033n/a /* Still a reference owned by path->object, don't have to
1034n/a worry about path->narrow is used after free. */
1035n/a Py_DECREF(bytes);
1036n/a }
1037n/a else {
1038n/a path->cleanup = bytes;
1039n/a }
1040n/a#endif
1041n/a path->fd = -1;
1042n/a
1043n/a success_exit:
1044n/a path->length = length;
1045n/a path->object = o;
1046n/a return Py_CLEANUP_SUPPORTED;
1047n/a
1048n/a error_exit:
1049n/a Py_XDECREF(o);
1050n/a Py_XDECREF(bytes);
1051n/a#ifdef MS_WINDOWS
1052n/a Py_XDECREF(wo);
1053n/a#endif
1054n/a return 0;
1055n/a}
1056n/a
1057n/astatic void
1058n/aargument_unavailable_error(const char *function_name, const char *argument_name)
1059n/a{
1060n/a PyErr_Format(PyExc_NotImplementedError,
1061n/a "%s%s%s unavailable on this platform",
1062n/a (function_name != NULL) ? function_name : "",
1063n/a (function_name != NULL) ? ": ": "",
1064n/a argument_name);
1065n/a}
1066n/a
1067n/astatic int
1068n/adir_fd_unavailable(PyObject *o, void *p)
1069n/a{
1070n/a int dir_fd;
1071n/a if (!dir_fd_converter(o, &dir_fd))
1072n/a return 0;
1073n/a if (dir_fd != DEFAULT_DIR_FD) {
1074n/a argument_unavailable_error(NULL, "dir_fd");
1075n/a return 0;
1076n/a }
1077n/a *(int *)p = dir_fd;
1078n/a return 1;
1079n/a}
1080n/a
1081n/astatic int
1082n/afd_specified(const char *function_name, int fd)
1083n/a{
1084n/a if (fd == -1)
1085n/a return 0;
1086n/a
1087n/a argument_unavailable_error(function_name, "fd");
1088n/a return 1;
1089n/a}
1090n/a
1091n/astatic int
1092n/afollow_symlinks_specified(const char *function_name, int follow_symlinks)
1093n/a{
1094n/a if (follow_symlinks)
1095n/a return 0;
1096n/a
1097n/a argument_unavailable_error(function_name, "follow_symlinks");
1098n/a return 1;
1099n/a}
1100n/a
1101n/astatic int
1102n/apath_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1103n/a{
1104n/a if (!path->wide && (dir_fd != DEFAULT_DIR_FD)
1105n/a#ifndef MS_WINDOWS
1106n/a && !path->narrow
1107n/a#endif
1108n/a ) {
1109n/a PyErr_Format(PyExc_ValueError,
1110n/a "%s: can't specify dir_fd without matching path",
1111n/a function_name);
1112n/a return 1;
1113n/a }
1114n/a return 0;
1115n/a}
1116n/a
1117n/astatic int
1118n/adir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1119n/a{
1120n/a if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1121n/a PyErr_Format(PyExc_ValueError,
1122n/a "%s: can't specify both dir_fd and fd",
1123n/a function_name);
1124n/a return 1;
1125n/a }
1126n/a return 0;
1127n/a}
1128n/a
1129n/astatic int
1130n/afd_and_follow_symlinks_invalid(const char *function_name, int fd,
1131n/a int follow_symlinks)
1132n/a{
1133n/a if ((fd > 0) && (!follow_symlinks)) {
1134n/a PyErr_Format(PyExc_ValueError,
1135n/a "%s: cannot use fd and follow_symlinks together",
1136n/a function_name);
1137n/a return 1;
1138n/a }
1139n/a return 0;
1140n/a}
1141n/a
1142n/astatic int
1143n/adir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1144n/a int follow_symlinks)
1145n/a{
1146n/a if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1147n/a PyErr_Format(PyExc_ValueError,
1148n/a "%s: cannot use dir_fd and follow_symlinks together",
1149n/a function_name);
1150n/a return 1;
1151n/a }
1152n/a return 0;
1153n/a}
1154n/a
1155n/a#ifdef MS_WINDOWS
1156n/a typedef long long Py_off_t;
1157n/a#else
1158n/a typedef off_t Py_off_t;
1159n/a#endif
1160n/a
1161n/astatic int
1162n/aPy_off_t_converter(PyObject *arg, void *addr)
1163n/a{
1164n/a#ifdef HAVE_LARGEFILE_SUPPORT
1165n/a *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1166n/a#else
1167n/a *((Py_off_t *)addr) = PyLong_AsLong(arg);
1168n/a#endif
1169n/a if (PyErr_Occurred())
1170n/a return 0;
1171n/a return 1;
1172n/a}
1173n/a
1174n/astatic PyObject *
1175n/aPyLong_FromPy_off_t(Py_off_t offset)
1176n/a{
1177n/a#ifdef HAVE_LARGEFILE_SUPPORT
1178n/a return PyLong_FromLongLong(offset);
1179n/a#else
1180n/a return PyLong_FromLong(offset);
1181n/a#endif
1182n/a}
1183n/a
1184n/a#ifdef MS_WINDOWS
1185n/a
1186n/astatic int
1187n/awin32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
1188n/a{
1189n/a char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
1190n/a _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
1191n/a DWORD n_bytes_returned;
1192n/a
1193n/a if (0 == DeviceIoControl(
1194n/a reparse_point_handle,
1195n/a FSCTL_GET_REPARSE_POINT,
1196n/a NULL, 0, /* in buffer */
1197n/a target_buffer, sizeof(target_buffer),
1198n/a &n_bytes_returned,
1199n/a NULL)) /* we're not using OVERLAPPED_IO */
1200n/a return FALSE;
1201n/a
1202n/a if (reparse_tag)
1203n/a *reparse_tag = rdb->ReparseTag;
1204n/a
1205n/a return TRUE;
1206n/a}
1207n/a
1208n/a#endif /* MS_WINDOWS */
1209n/a
1210n/a/* Return a dictionary corresponding to the POSIX environment table */
1211n/a#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1212n/a/* On Darwin/MacOSX a shared library or framework has no access to
1213n/a** environ directly, we must obtain it with _NSGetEnviron(). See also
1214n/a** man environ(7).
1215n/a*/
1216n/a#include <crt_externs.h>
1217n/astatic char **environ;
1218n/a#elif !defined(_MSC_VER) && ( !defined(__WATCOMC__) || defined(__QNX__) )
1219n/aextern char **environ;
1220n/a#endif /* !_MSC_VER */
1221n/a
1222n/astatic PyObject *
1223n/aconvertenviron(void)
1224n/a{
1225n/a PyObject *d;
1226n/a#ifdef MS_WINDOWS
1227n/a wchar_t **e;
1228n/a#else
1229n/a char **e;
1230n/a#endif
1231n/a
1232n/a d = PyDict_New();
1233n/a if (d == NULL)
1234n/a return NULL;
1235n/a#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1236n/a if (environ == NULL)
1237n/a environ = *_NSGetEnviron();
1238n/a#endif
1239n/a#ifdef MS_WINDOWS
1240n/a /* _wenviron must be initialized in this way if the program is started
1241n/a through main() instead of wmain(). */
1242n/a _wgetenv(L"");
1243n/a if (_wenviron == NULL)
1244n/a return d;
1245n/a /* This part ignores errors */
1246n/a for (e = _wenviron; *e != NULL; e++) {
1247n/a PyObject *k;
1248n/a PyObject *v;
1249n/a const wchar_t *p = wcschr(*e, L'=');
1250n/a if (p == NULL)
1251n/a continue;
1252n/a k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1253n/a if (k == NULL) {
1254n/a PyErr_Clear();
1255n/a continue;
1256n/a }
1257n/a v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
1258n/a if (v == NULL) {
1259n/a PyErr_Clear();
1260n/a Py_DECREF(k);
1261n/a continue;
1262n/a }
1263n/a if (PyDict_GetItem(d, k) == NULL) {
1264n/a if (PyDict_SetItem(d, k, v) != 0)
1265n/a PyErr_Clear();
1266n/a }
1267n/a Py_DECREF(k);
1268n/a Py_DECREF(v);
1269n/a }
1270n/a#else
1271n/a if (environ == NULL)
1272n/a return d;
1273n/a /* This part ignores errors */
1274n/a for (e = environ; *e != NULL; e++) {
1275n/a PyObject *k;
1276n/a PyObject *v;
1277n/a const char *p = strchr(*e, '=');
1278n/a if (p == NULL)
1279n/a continue;
1280n/a k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1281n/a if (k == NULL) {
1282n/a PyErr_Clear();
1283n/a continue;
1284n/a }
1285n/a v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1286n/a if (v == NULL) {
1287n/a PyErr_Clear();
1288n/a Py_DECREF(k);
1289n/a continue;
1290n/a }
1291n/a if (PyDict_GetItem(d, k) == NULL) {
1292n/a if (PyDict_SetItem(d, k, v) != 0)
1293n/a PyErr_Clear();
1294n/a }
1295n/a Py_DECREF(k);
1296n/a Py_DECREF(v);
1297n/a }
1298n/a#endif
1299n/a return d;
1300n/a}
1301n/a
1302n/a/* Set a POSIX-specific error from errno, and return NULL */
1303n/a
1304n/astatic PyObject *
1305n/aposix_error(void)
1306n/a{
1307n/a return PyErr_SetFromErrno(PyExc_OSError);
1308n/a}
1309n/a
1310n/a#ifdef MS_WINDOWS
1311n/astatic PyObject *
1312n/awin32_error(const char* function, const char* filename)
1313n/a{
1314n/a /* XXX We should pass the function name along in the future.
1315n/a (winreg.c also wants to pass the function name.)
1316n/a This would however require an additional param to the
1317n/a Windows error object, which is non-trivial.
1318n/a */
1319n/a errno = GetLastError();
1320n/a if (filename)
1321n/a return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1322n/a else
1323n/a return PyErr_SetFromWindowsErr(errno);
1324n/a}
1325n/a
1326n/astatic PyObject *
1327n/awin32_error_object(const char* function, PyObject* filename)
1328n/a{
1329n/a /* XXX - see win32_error for comments on 'function' */
1330n/a errno = GetLastError();
1331n/a if (filename)
1332n/a return PyErr_SetExcFromWindowsErrWithFilenameObject(
1333n/a PyExc_OSError,
1334n/a errno,
1335n/a filename);
1336n/a else
1337n/a return PyErr_SetFromWindowsErr(errno);
1338n/a}
1339n/a
1340n/a#endif /* MS_WINDOWS */
1341n/a
1342n/astatic PyObject *
1343n/apath_object_error(PyObject *path)
1344n/a{
1345n/a#ifdef MS_WINDOWS
1346n/a return PyErr_SetExcFromWindowsErrWithFilenameObject(
1347n/a PyExc_OSError, 0, path);
1348n/a#else
1349n/a return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1350n/a#endif
1351n/a}
1352n/a
1353n/astatic PyObject *
1354n/apath_object_error2(PyObject *path, PyObject *path2)
1355n/a{
1356n/a#ifdef MS_WINDOWS
1357n/a return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1358n/a PyExc_OSError, 0, path, path2);
1359n/a#else
1360n/a return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1361n/a#endif
1362n/a}
1363n/a
1364n/astatic PyObject *
1365n/apath_error(path_t *path)
1366n/a{
1367n/a return path_object_error(path->object);
1368n/a}
1369n/a
1370n/astatic PyObject *
1371n/apath_error2(path_t *path, path_t *path2)
1372n/a{
1373n/a return path_object_error2(path->object, path2->object);
1374n/a}
1375n/a
1376n/a
1377n/a/* POSIX generic methods */
1378n/a
1379n/astatic int
1380n/afildes_converter(PyObject *o, void *p)
1381n/a{
1382n/a int fd;
1383n/a int *pointer = (int *)p;
1384n/a fd = PyObject_AsFileDescriptor(o);
1385n/a if (fd < 0)
1386n/a return 0;
1387n/a *pointer = fd;
1388n/a return 1;
1389n/a}
1390n/a
1391n/astatic PyObject *
1392n/aposix_fildes_fd(int fd, int (*func)(int))
1393n/a{
1394n/a int res;
1395n/a int async_err = 0;
1396n/a
1397n/a do {
1398n/a Py_BEGIN_ALLOW_THREADS
1399n/a _Py_BEGIN_SUPPRESS_IPH
1400n/a res = (*func)(fd);
1401n/a _Py_END_SUPPRESS_IPH
1402n/a Py_END_ALLOW_THREADS
1403n/a } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1404n/a if (res != 0)
1405n/a return (!async_err) ? posix_error() : NULL;
1406n/a Py_RETURN_NONE;
1407n/a}
1408n/a
1409n/a
1410n/a#ifdef MS_WINDOWS
1411n/a/* This is a reimplementation of the C library's chdir function,
1412n/a but one that produces Win32 errors instead of DOS error codes.
1413n/a chdir is essentially a wrapper around SetCurrentDirectory; however,
1414n/a it also needs to set "magic" environment variables indicating
1415n/a the per-drive current directory, which are of the form =<drive>: */
1416n/astatic BOOL __stdcall
1417n/awin32_wchdir(LPCWSTR path)
1418n/a{
1419n/a wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1420n/a int result;
1421n/a wchar_t env[4] = L"=x:";
1422n/a
1423n/a if(!SetCurrentDirectoryW(path))
1424n/a return FALSE;
1425n/a result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1426n/a if (!result)
1427n/a return FALSE;
1428n/a if (result > Py_ARRAY_LENGTH(path_buf)) {
1429n/a new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1430n/a if (!new_path) {
1431n/a SetLastError(ERROR_OUTOFMEMORY);
1432n/a return FALSE;
1433n/a }
1434n/a result = GetCurrentDirectoryW(result, new_path);
1435n/a if (!result) {
1436n/a PyMem_RawFree(new_path);
1437n/a return FALSE;
1438n/a }
1439n/a }
1440n/a if (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1441n/a wcsncmp(new_path, L"//", 2) == 0)
1442n/a /* UNC path, nothing to do. */
1443n/a return TRUE;
1444n/a env[1] = new_path[0];
1445n/a result = SetEnvironmentVariableW(env, new_path);
1446n/a if (new_path != path_buf)
1447n/a PyMem_RawFree(new_path);
1448n/a return result;
1449n/a}
1450n/a#endif
1451n/a
1452n/a#ifdef MS_WINDOWS
1453n/a/* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1454n/a - time stamps are restricted to second resolution
1455n/a - file modification times suffer from forth-and-back conversions between
1456n/a UTC and local time
1457n/a Therefore, we implement our own stat, based on the Win32 API directly.
1458n/a*/
1459n/a#define HAVE_STAT_NSEC 1
1460n/a#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
1461n/a
1462n/astatic void
1463n/afind_data_to_file_info(WIN32_FIND_DATAW *pFileData,
1464n/a BY_HANDLE_FILE_INFORMATION *info,
1465n/a ULONG *reparse_tag)
1466n/a{
1467n/a memset(info, 0, sizeof(*info));
1468n/a info->dwFileAttributes = pFileData->dwFileAttributes;
1469n/a info->ftCreationTime = pFileData->ftCreationTime;
1470n/a info->ftLastAccessTime = pFileData->ftLastAccessTime;
1471n/a info->ftLastWriteTime = pFileData->ftLastWriteTime;
1472n/a info->nFileSizeHigh = pFileData->nFileSizeHigh;
1473n/a info->nFileSizeLow = pFileData->nFileSizeLow;
1474n/a/* info->nNumberOfLinks = 1; */
1475n/a if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1476n/a *reparse_tag = pFileData->dwReserved0;
1477n/a else
1478n/a *reparse_tag = 0;
1479n/a}
1480n/a
1481n/astatic BOOL
1482n/aattributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1483n/a{
1484n/a HANDLE hFindFile;
1485n/a WIN32_FIND_DATAW FileData;
1486n/a hFindFile = FindFirstFileW(pszFile, &FileData);
1487n/a if (hFindFile == INVALID_HANDLE_VALUE)
1488n/a return FALSE;
1489n/a FindClose(hFindFile);
1490n/a find_data_to_file_info(&FileData, info, reparse_tag);
1491n/a return TRUE;
1492n/a}
1493n/a
1494n/astatic BOOL
1495n/aget_target_path(HANDLE hdl, wchar_t **target_path)
1496n/a{
1497n/a int buf_size, result_length;
1498n/a wchar_t *buf;
1499n/a
1500n/a /* We have a good handle to the target, use it to determine
1501n/a the target path name (then we'll call lstat on it). */
1502n/a buf_size = GetFinalPathNameByHandleW(hdl, 0, 0,
1503n/a VOLUME_NAME_DOS);
1504n/a if(!buf_size)
1505n/a return FALSE;
1506n/a
1507n/a buf = (wchar_t *)PyMem_RawMalloc((buf_size + 1) * sizeof(wchar_t));
1508n/a if (!buf) {
1509n/a SetLastError(ERROR_OUTOFMEMORY);
1510n/a return FALSE;
1511n/a }
1512n/a
1513n/a result_length = GetFinalPathNameByHandleW(hdl,
1514n/a buf, buf_size, VOLUME_NAME_DOS);
1515n/a
1516n/a if(!result_length) {
1517n/a PyMem_RawFree(buf);
1518n/a return FALSE;
1519n/a }
1520n/a
1521n/a if(!CloseHandle(hdl)) {
1522n/a PyMem_RawFree(buf);
1523n/a return FALSE;
1524n/a }
1525n/a
1526n/a buf[result_length] = 0;
1527n/a
1528n/a *target_path = buf;
1529n/a return TRUE;
1530n/a}
1531n/a
1532n/astatic int
1533n/awin32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
1534n/a BOOL traverse)
1535n/a{
1536n/a int code;
1537n/a HANDLE hFile, hFile2;
1538n/a BY_HANDLE_FILE_INFORMATION info;
1539n/a ULONG reparse_tag = 0;
1540n/a wchar_t *target_path;
1541n/a const wchar_t *dot;
1542n/a
1543n/a hFile = CreateFileW(
1544n/a path,
1545n/a FILE_READ_ATTRIBUTES, /* desired access */
1546n/a 0, /* share mode */
1547n/a NULL, /* security attributes */
1548n/a OPEN_EXISTING,
1549n/a /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
1550n/a /* FILE_FLAG_OPEN_REPARSE_POINT does not follow the symlink.
1551n/a Because of this, calls like GetFinalPathNameByHandle will return
1552n/a the symlink path again and not the actual final path. */
1553n/a FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS|
1554n/a FILE_FLAG_OPEN_REPARSE_POINT,
1555n/a NULL);
1556n/a
1557n/a if (hFile == INVALID_HANDLE_VALUE) {
1558n/a /* Either the target doesn't exist, or we don't have access to
1559n/a get a handle to it. If the former, we need to return an error.
1560n/a If the latter, we can use attributes_from_dir. */
1561n/a DWORD lastError = GetLastError();
1562n/a if (lastError != ERROR_ACCESS_DENIED &&
1563n/a lastError != ERROR_SHARING_VIOLATION)
1564n/a return -1;
1565n/a /* Could not get attributes on open file. Fall back to
1566n/a reading the directory. */
1567n/a if (!attributes_from_dir(path, &info, &reparse_tag))
1568n/a /* Very strange. This should not fail now */
1569n/a return -1;
1570n/a if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1571n/a if (traverse) {
1572n/a /* Should traverse, but could not open reparse point handle */
1573n/a SetLastError(lastError);
1574n/a return -1;
1575n/a }
1576n/a }
1577n/a } else {
1578n/a if (!GetFileInformationByHandle(hFile, &info)) {
1579n/a CloseHandle(hFile);
1580n/a return -1;
1581n/a }
1582n/a if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1583n/a if (!win32_get_reparse_tag(hFile, &reparse_tag))
1584n/a return -1;
1585n/a
1586n/a /* Close the outer open file handle now that we're about to
1587n/a reopen it with different flags. */
1588n/a if (!CloseHandle(hFile))
1589n/a return -1;
1590n/a
1591n/a if (traverse) {
1592n/a /* In order to call GetFinalPathNameByHandle we need to open
1593n/a the file without the reparse handling flag set. */
1594n/a hFile2 = CreateFileW(
1595n/a path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ,
1596n/a NULL, OPEN_EXISTING,
1597n/a FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS,
1598n/a NULL);
1599n/a if (hFile2 == INVALID_HANDLE_VALUE)
1600n/a return -1;
1601n/a
1602n/a if (!get_target_path(hFile2, &target_path))
1603n/a return -1;
1604n/a
1605n/a code = win32_xstat_impl(target_path, result, FALSE);
1606n/a PyMem_RawFree(target_path);
1607n/a return code;
1608n/a }
1609n/a } else
1610n/a CloseHandle(hFile);
1611n/a }
1612n/a _Py_attribute_data_to_stat(&info, reparse_tag, result);
1613n/a
1614n/a /* Set S_IEXEC if it is an .exe, .bat, ... */
1615n/a dot = wcsrchr(path, '.');
1616n/a if (dot) {
1617n/a if (_wcsicmp(dot, L".bat") == 0 || _wcsicmp(dot, L".cmd") == 0 ||
1618n/a _wcsicmp(dot, L".exe") == 0 || _wcsicmp(dot, L".com") == 0)
1619n/a result->st_mode |= 0111;
1620n/a }
1621n/a return 0;
1622n/a}
1623n/a
1624n/astatic int
1625n/awin32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
1626n/a{
1627n/a /* Protocol violation: we explicitly clear errno, instead of
1628n/a setting it to a POSIX error. Callers should use GetLastError. */
1629n/a int code = win32_xstat_impl(path, result, traverse);
1630n/a errno = 0;
1631n/a return code;
1632n/a}
1633n/a/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
1634n/a
1635n/a In Posix, stat automatically traverses symlinks and returns the stat
1636n/a structure for the target. In Windows, the equivalent GetFileAttributes by
1637n/a default does not traverse symlinks and instead returns attributes for
1638n/a the symlink.
1639n/a
1640n/a Therefore, win32_lstat will get the attributes traditionally, and
1641n/a win32_stat will first explicitly resolve the symlink target and then will
1642n/a call win32_lstat on that result. */
1643n/a
1644n/astatic int
1645n/awin32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
1646n/a{
1647n/a return win32_xstat(path, result, FALSE);
1648n/a}
1649n/a
1650n/astatic int
1651n/awin32_stat(const wchar_t* path, struct _Py_stat_struct *result)
1652n/a{
1653n/a return win32_xstat(path, result, TRUE);
1654n/a}
1655n/a
1656n/a#endif /* MS_WINDOWS */
1657n/a
1658n/aPyDoc_STRVAR(stat_result__doc__,
1659n/a"stat_result: Result from stat, fstat, or lstat.\n\n\
1660n/aThis object may be accessed either as a tuple of\n\
1661n/a (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
1662n/aor via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
1663n/a\n\
1664n/aPosix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
1665n/aor st_flags, they are available as attributes only.\n\
1666n/a\n\
1667n/aSee os.stat for more information.");
1668n/a
1669n/astatic PyStructSequence_Field stat_result_fields[] = {
1670n/a {"st_mode", "protection bits"},
1671n/a {"st_ino", "inode"},
1672n/a {"st_dev", "device"},
1673n/a {"st_nlink", "number of hard links"},
1674n/a {"st_uid", "user ID of owner"},
1675n/a {"st_gid", "group ID of owner"},
1676n/a {"st_size", "total size, in bytes"},
1677n/a /* The NULL is replaced with PyStructSequence_UnnamedField later. */
1678n/a {NULL, "integer time of last access"},
1679n/a {NULL, "integer time of last modification"},
1680n/a {NULL, "integer time of last change"},
1681n/a {"st_atime", "time of last access"},
1682n/a {"st_mtime", "time of last modification"},
1683n/a {"st_ctime", "time of last change"},
1684n/a {"st_atime_ns", "time of last access in nanoseconds"},
1685n/a {"st_mtime_ns", "time of last modification in nanoseconds"},
1686n/a {"st_ctime_ns", "time of last change in nanoseconds"},
1687n/a#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1688n/a {"st_blksize", "blocksize for filesystem I/O"},
1689n/a#endif
1690n/a#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1691n/a {"st_blocks", "number of blocks allocated"},
1692n/a#endif
1693n/a#ifdef HAVE_STRUCT_STAT_ST_RDEV
1694n/a {"st_rdev", "device type (if inode device)"},
1695n/a#endif
1696n/a#ifdef HAVE_STRUCT_STAT_ST_FLAGS
1697n/a {"st_flags", "user defined flags for file"},
1698n/a#endif
1699n/a#ifdef HAVE_STRUCT_STAT_ST_GEN
1700n/a {"st_gen", "generation number"},
1701n/a#endif
1702n/a#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1703n/a {"st_birthtime", "time of creation"},
1704n/a#endif
1705n/a#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
1706n/a {"st_file_attributes", "Windows file attribute bits"},
1707n/a#endif
1708n/a {0}
1709n/a};
1710n/a
1711n/a#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1712n/a#define ST_BLKSIZE_IDX 16
1713n/a#else
1714n/a#define ST_BLKSIZE_IDX 15
1715n/a#endif
1716n/a
1717n/a#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1718n/a#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
1719n/a#else
1720n/a#define ST_BLOCKS_IDX ST_BLKSIZE_IDX
1721n/a#endif
1722n/a
1723n/a#ifdef HAVE_STRUCT_STAT_ST_RDEV
1724n/a#define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
1725n/a#else
1726n/a#define ST_RDEV_IDX ST_BLOCKS_IDX
1727n/a#endif
1728n/a
1729n/a#ifdef HAVE_STRUCT_STAT_ST_FLAGS
1730n/a#define ST_FLAGS_IDX (ST_RDEV_IDX+1)
1731n/a#else
1732n/a#define ST_FLAGS_IDX ST_RDEV_IDX
1733n/a#endif
1734n/a
1735n/a#ifdef HAVE_STRUCT_STAT_ST_GEN
1736n/a#define ST_GEN_IDX (ST_FLAGS_IDX+1)
1737n/a#else
1738n/a#define ST_GEN_IDX ST_FLAGS_IDX
1739n/a#endif
1740n/a
1741n/a#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1742n/a#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
1743n/a#else
1744n/a#define ST_BIRTHTIME_IDX ST_GEN_IDX
1745n/a#endif
1746n/a
1747n/a#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
1748n/a#define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1)
1749n/a#else
1750n/a#define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX
1751n/a#endif
1752n/a
1753n/astatic PyStructSequence_Desc stat_result_desc = {
1754n/a "stat_result", /* name */
1755n/a stat_result__doc__, /* doc */
1756n/a stat_result_fields,
1757n/a 10
1758n/a};
1759n/a
1760n/aPyDoc_STRVAR(statvfs_result__doc__,
1761n/a"statvfs_result: Result from statvfs or fstatvfs.\n\n\
1762n/aThis object may be accessed either as a tuple of\n\
1763n/a (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
1764n/aor via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
1765n/a\n\
1766n/aSee os.statvfs for more information.");
1767n/a
1768n/astatic PyStructSequence_Field statvfs_result_fields[] = {
1769n/a {"f_bsize", },
1770n/a {"f_frsize", },
1771n/a {"f_blocks", },
1772n/a {"f_bfree", },
1773n/a {"f_bavail", },
1774n/a {"f_files", },
1775n/a {"f_ffree", },
1776n/a {"f_favail", },
1777n/a {"f_flag", },
1778n/a {"f_namemax",},
1779n/a {0}
1780n/a};
1781n/a
1782n/astatic PyStructSequence_Desc statvfs_result_desc = {
1783n/a "statvfs_result", /* name */
1784n/a statvfs_result__doc__, /* doc */
1785n/a statvfs_result_fields,
1786n/a 10
1787n/a};
1788n/a
1789n/a#if defined(HAVE_WAITID) && !defined(__APPLE__)
1790n/aPyDoc_STRVAR(waitid_result__doc__,
1791n/a"waitid_result: Result from waitid.\n\n\
1792n/aThis object may be accessed either as a tuple of\n\
1793n/a (si_pid, si_uid, si_signo, si_status, si_code),\n\
1794n/aor via the attributes si_pid, si_uid, and so on.\n\
1795n/a\n\
1796n/aSee os.waitid for more information.");
1797n/a
1798n/astatic PyStructSequence_Field waitid_result_fields[] = {
1799n/a {"si_pid", },
1800n/a {"si_uid", },
1801n/a {"si_signo", },
1802n/a {"si_status", },
1803n/a {"si_code", },
1804n/a {0}
1805n/a};
1806n/a
1807n/astatic PyStructSequence_Desc waitid_result_desc = {
1808n/a "waitid_result", /* name */
1809n/a waitid_result__doc__, /* doc */
1810n/a waitid_result_fields,
1811n/a 5
1812n/a};
1813n/astatic PyTypeObject WaitidResultType;
1814n/a#endif
1815n/a
1816n/astatic int initialized;
1817n/astatic PyTypeObject StatResultType;
1818n/astatic PyTypeObject StatVFSResultType;
1819n/a#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER)
1820n/astatic PyTypeObject SchedParamType;
1821n/a#endif
1822n/astatic newfunc structseq_new;
1823n/a
1824n/astatic PyObject *
1825n/astatresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1826n/a{
1827n/a PyStructSequence *result;
1828n/a int i;
1829n/a
1830n/a result = (PyStructSequence*)structseq_new(type, args, kwds);
1831n/a if (!result)
1832n/a return NULL;
1833n/a /* If we have been initialized from a tuple,
1834n/a st_?time might be set to None. Initialize it
1835n/a from the int slots. */
1836n/a for (i = 7; i <= 9; i++) {
1837n/a if (result->ob_item[i+3] == Py_None) {
1838n/a Py_DECREF(Py_None);
1839n/a Py_INCREF(result->ob_item[i]);
1840n/a result->ob_item[i+3] = result->ob_item[i];
1841n/a }
1842n/a }
1843n/a return (PyObject*)result;
1844n/a}
1845n/a
1846n/a
1847n/a
1848n/a/* If true, st_?time is float. */
1849n/astatic int _stat_float_times = 1;
1850n/a
1851n/aPyDoc_STRVAR(stat_float_times__doc__,
1852n/a"stat_float_times([newval]) -> oldval\n\n\
1853n/aDetermine whether os.[lf]stat represents time stamps as float objects.\n\
1854n/a\n\
1855n/aIf value is True, future calls to stat() return floats; if it is False,\n\
1856n/afuture calls return ints.\n\
1857n/aIf value is omitted, return the current setting.\n");
1858n/a
1859n/a/* AC 3.5: the public default value should be None, not ready for that yet */
1860n/astatic PyObject*
1861n/astat_float_times(PyObject* self, PyObject *args)
1862n/a{
1863n/a int newval = -1;
1864n/a if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval))
1865n/a return NULL;
1866n/a if (PyErr_WarnEx(PyExc_DeprecationWarning,
1867n/a "stat_float_times() is deprecated",
1868n/a 1))
1869n/a return NULL;
1870n/a if (newval == -1)
1871n/a /* Return old value */
1872n/a return PyBool_FromLong(_stat_float_times);
1873n/a _stat_float_times = newval;
1874n/a Py_RETURN_NONE;
1875n/a}
1876n/a
1877n/astatic PyObject *billion = NULL;
1878n/a
1879n/astatic void
1880n/afill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
1881n/a{
1882n/a PyObject *s = _PyLong_FromTime_t(sec);
1883n/a PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
1884n/a PyObject *s_in_ns = NULL;
1885n/a PyObject *ns_total = NULL;
1886n/a PyObject *float_s = NULL;
1887n/a
1888n/a if (!(s && ns_fractional))
1889n/a goto exit;
1890n/a
1891n/a s_in_ns = PyNumber_Multiply(s, billion);
1892n/a if (!s_in_ns)
1893n/a goto exit;
1894n/a
1895n/a ns_total = PyNumber_Add(s_in_ns, ns_fractional);
1896n/a if (!ns_total)
1897n/a goto exit;
1898n/a
1899n/a if (_stat_float_times) {
1900n/a float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
1901n/a if (!float_s)
1902n/a goto exit;
1903n/a }
1904n/a else {
1905n/a float_s = s;
1906n/a Py_INCREF(float_s);
1907n/a }
1908n/a
1909n/a PyStructSequence_SET_ITEM(v, index, s);
1910n/a PyStructSequence_SET_ITEM(v, index+3, float_s);
1911n/a PyStructSequence_SET_ITEM(v, index+6, ns_total);
1912n/a s = NULL;
1913n/a float_s = NULL;
1914n/a ns_total = NULL;
1915n/aexit:
1916n/a Py_XDECREF(s);
1917n/a Py_XDECREF(ns_fractional);
1918n/a Py_XDECREF(s_in_ns);
1919n/a Py_XDECREF(ns_total);
1920n/a Py_XDECREF(float_s);
1921n/a}
1922n/a
1923n/a/* pack a system stat C structure into the Python stat tuple
1924n/a (used by posix_stat() and posix_fstat()) */
1925n/astatic PyObject*
1926n/a_pystat_fromstructstat(STRUCT_STAT *st)
1927n/a{
1928n/a unsigned long ansec, mnsec, cnsec;
1929n/a PyObject *v = PyStructSequence_New(&StatResultType);
1930n/a if (v == NULL)
1931n/a return NULL;
1932n/a
1933n/a PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
1934n/a#ifdef HAVE_LARGEFILE_SUPPORT
1935n/a PyStructSequence_SET_ITEM(v, 1,
1936n/a PyLong_FromLongLong((long long)st->st_ino));
1937n/a#else
1938n/a PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long)st->st_ino));
1939n/a#endif
1940n/a#ifdef MS_WINDOWS
1941n/a PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));
1942n/a#else
1943n/a PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));
1944n/a#endif
1945n/a PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
1946n/a#if defined(MS_WINDOWS)
1947n/a PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0));
1948n/a PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0));
1949n/a#else
1950n/a PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));
1951n/a PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid));
1952n/a#endif
1953n/a#ifdef HAVE_LARGEFILE_SUPPORT
1954n/a PyStructSequence_SET_ITEM(v, 6,
1955n/a PyLong_FromLongLong((long long)st->st_size));
1956n/a#else
1957n/a PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong(st->st_size));
1958n/a#endif
1959n/a
1960n/a#if defined(HAVE_STAT_TV_NSEC)
1961n/a ansec = st->st_atim.tv_nsec;
1962n/a mnsec = st->st_mtim.tv_nsec;
1963n/a cnsec = st->st_ctim.tv_nsec;
1964n/a#elif defined(HAVE_STAT_TV_NSEC2)
1965n/a ansec = st->st_atimespec.tv_nsec;
1966n/a mnsec = st->st_mtimespec.tv_nsec;
1967n/a cnsec = st->st_ctimespec.tv_nsec;
1968n/a#elif defined(HAVE_STAT_NSEC)
1969n/a ansec = st->st_atime_nsec;
1970n/a mnsec = st->st_mtime_nsec;
1971n/a cnsec = st->st_ctime_nsec;
1972n/a#else
1973n/a ansec = mnsec = cnsec = 0;
1974n/a#endif
1975n/a fill_time(v, 7, st->st_atime, ansec);
1976n/a fill_time(v, 8, st->st_mtime, mnsec);
1977n/a fill_time(v, 9, st->st_ctime, cnsec);
1978n/a
1979n/a#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1980n/a PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
1981n/a PyLong_FromLong((long)st->st_blksize));
1982n/a#endif
1983n/a#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1984n/a PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
1985n/a PyLong_FromLong((long)st->st_blocks));
1986n/a#endif
1987n/a#ifdef HAVE_STRUCT_STAT_ST_RDEV
1988n/a PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
1989n/a PyLong_FromLong((long)st->st_rdev));
1990n/a#endif
1991n/a#ifdef HAVE_STRUCT_STAT_ST_GEN
1992n/a PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
1993n/a PyLong_FromLong((long)st->st_gen));
1994n/a#endif
1995n/a#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1996n/a {
1997n/a PyObject *val;
1998n/a unsigned long bsec,bnsec;
1999n/a bsec = (long)st->st_birthtime;
2000n/a#ifdef HAVE_STAT_TV_NSEC2
2001n/a bnsec = st->st_birthtimespec.tv_nsec;
2002n/a#else
2003n/a bnsec = 0;
2004n/a#endif
2005n/a if (_stat_float_times) {
2006n/a val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
2007n/a } else {
2008n/a val = PyLong_FromLong((long)bsec);
2009n/a }
2010n/a PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
2011n/a val);
2012n/a }
2013n/a#endif
2014n/a#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2015n/a PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
2016n/a PyLong_FromLong((long)st->st_flags));
2017n/a#endif
2018n/a#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2019n/a PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,
2020n/a PyLong_FromUnsignedLong(st->st_file_attributes));
2021n/a#endif
2022n/a
2023n/a if (PyErr_Occurred()) {
2024n/a Py_DECREF(v);
2025n/a return NULL;
2026n/a }
2027n/a
2028n/a return v;
2029n/a}
2030n/a
2031n/a/* POSIX methods */
2032n/a
2033n/a
2034n/astatic PyObject *
2035n/aposix_do_stat(const char *function_name, path_t *path,
2036n/a int dir_fd, int follow_symlinks)
2037n/a{
2038n/a STRUCT_STAT st;
2039n/a int result;
2040n/a
2041n/a#if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2042n/a if (follow_symlinks_specified(function_name, follow_symlinks))
2043n/a return NULL;
2044n/a#endif
2045n/a
2046n/a if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2047n/a dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2048n/a fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2049n/a return NULL;
2050n/a
2051n/a Py_BEGIN_ALLOW_THREADS
2052n/a if (path->fd != -1)
2053n/a result = FSTAT(path->fd, &st);
2054n/a#ifdef MS_WINDOWS
2055n/a else if (follow_symlinks)
2056n/a result = win32_stat(path->wide, &st);
2057n/a else
2058n/a result = win32_lstat(path->wide, &st);
2059n/a#else
2060n/a else
2061n/a#if defined(HAVE_LSTAT)
2062n/a if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2063n/a result = LSTAT(path->narrow, &st);
2064n/a else
2065n/a#endif /* HAVE_LSTAT */
2066n/a#ifdef HAVE_FSTATAT
2067n/a if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks)
2068n/a result = fstatat(dir_fd, path->narrow, &st,
2069n/a follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2070n/a else
2071n/a#endif /* HAVE_FSTATAT */
2072n/a result = STAT(path->narrow, &st);
2073n/a#endif /* MS_WINDOWS */
2074n/a Py_END_ALLOW_THREADS
2075n/a
2076n/a if (result != 0) {
2077n/a return path_error(path);
2078n/a }
2079n/a
2080n/a return _pystat_fromstructstat(&st);
2081n/a}
2082n/a
2083n/a/*[python input]
2084n/a
2085n/afor s in """
2086n/a
2087n/aFACCESSAT
2088n/aFCHMODAT
2089n/aFCHOWNAT
2090n/aFSTATAT
2091n/aLINKAT
2092n/aMKDIRAT
2093n/aMKFIFOAT
2094n/aMKNODAT
2095n/aOPENAT
2096n/aREADLINKAT
2097n/aSYMLINKAT
2098n/aUNLINKAT
2099n/a
2100n/a""".strip().split():
2101n/a s = s.strip()
2102n/a print("""
2103n/a#ifdef HAVE_{s}
2104n/a #define {s}_DIR_FD_CONVERTER dir_fd_converter
2105n/a#else
2106n/a #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2107n/a#endif
2108n/a""".rstrip().format(s=s))
2109n/a
2110n/afor s in """
2111n/a
2112n/aFCHDIR
2113n/aFCHMOD
2114n/aFCHOWN
2115n/aFDOPENDIR
2116n/aFEXECVE
2117n/aFPATHCONF
2118n/aFSTATVFS
2119n/aFTRUNCATE
2120n/a
2121n/a""".strip().split():
2122n/a s = s.strip()
2123n/a print("""
2124n/a#ifdef HAVE_{s}
2125n/a #define PATH_HAVE_{s} 1
2126n/a#else
2127n/a #define PATH_HAVE_{s} 0
2128n/a#endif
2129n/a
2130n/a""".rstrip().format(s=s))
2131n/a[python start generated code]*/
2132n/a
2133n/a#ifdef HAVE_FACCESSAT
2134n/a #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2135n/a#else
2136n/a #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2137n/a#endif
2138n/a
2139n/a#ifdef HAVE_FCHMODAT
2140n/a #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2141n/a#else
2142n/a #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2143n/a#endif
2144n/a
2145n/a#ifdef HAVE_FCHOWNAT
2146n/a #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2147n/a#else
2148n/a #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2149n/a#endif
2150n/a
2151n/a#ifdef HAVE_FSTATAT
2152n/a #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2153n/a#else
2154n/a #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2155n/a#endif
2156n/a
2157n/a#ifdef HAVE_LINKAT
2158n/a #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2159n/a#else
2160n/a #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2161n/a#endif
2162n/a
2163n/a#ifdef HAVE_MKDIRAT
2164n/a #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
2165n/a#else
2166n/a #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
2167n/a#endif
2168n/a
2169n/a#ifdef HAVE_MKFIFOAT
2170n/a #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
2171n/a#else
2172n/a #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
2173n/a#endif
2174n/a
2175n/a#ifdef HAVE_MKNODAT
2176n/a #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
2177n/a#else
2178n/a #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
2179n/a#endif
2180n/a
2181n/a#ifdef HAVE_OPENAT
2182n/a #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
2183n/a#else
2184n/a #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
2185n/a#endif
2186n/a
2187n/a#ifdef HAVE_READLINKAT
2188n/a #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
2189n/a#else
2190n/a #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2191n/a#endif
2192n/a
2193n/a#ifdef HAVE_SYMLINKAT
2194n/a #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
2195n/a#else
2196n/a #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2197n/a#endif
2198n/a
2199n/a#ifdef HAVE_UNLINKAT
2200n/a #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
2201n/a#else
2202n/a #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2203n/a#endif
2204n/a
2205n/a#ifdef HAVE_FCHDIR
2206n/a #define PATH_HAVE_FCHDIR 1
2207n/a#else
2208n/a #define PATH_HAVE_FCHDIR 0
2209n/a#endif
2210n/a
2211n/a#ifdef HAVE_FCHMOD
2212n/a #define PATH_HAVE_FCHMOD 1
2213n/a#else
2214n/a #define PATH_HAVE_FCHMOD 0
2215n/a#endif
2216n/a
2217n/a#ifdef HAVE_FCHOWN
2218n/a #define PATH_HAVE_FCHOWN 1
2219n/a#else
2220n/a #define PATH_HAVE_FCHOWN 0
2221n/a#endif
2222n/a
2223n/a#ifdef HAVE_FDOPENDIR
2224n/a #define PATH_HAVE_FDOPENDIR 1
2225n/a#else
2226n/a #define PATH_HAVE_FDOPENDIR 0
2227n/a#endif
2228n/a
2229n/a#ifdef HAVE_FEXECVE
2230n/a #define PATH_HAVE_FEXECVE 1
2231n/a#else
2232n/a #define PATH_HAVE_FEXECVE 0
2233n/a#endif
2234n/a
2235n/a#ifdef HAVE_FPATHCONF
2236n/a #define PATH_HAVE_FPATHCONF 1
2237n/a#else
2238n/a #define PATH_HAVE_FPATHCONF 0
2239n/a#endif
2240n/a
2241n/a#ifdef HAVE_FSTATVFS
2242n/a #define PATH_HAVE_FSTATVFS 1
2243n/a#else
2244n/a #define PATH_HAVE_FSTATVFS 0
2245n/a#endif
2246n/a
2247n/a#ifdef HAVE_FTRUNCATE
2248n/a #define PATH_HAVE_FTRUNCATE 1
2249n/a#else
2250n/a #define PATH_HAVE_FTRUNCATE 0
2251n/a#endif
2252n/a/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
2253n/a
2254n/a#ifdef MS_WINDOWS
2255n/a #undef PATH_HAVE_FTRUNCATE
2256n/a #define PATH_HAVE_FTRUNCATE 1
2257n/a#endif
2258n/a
2259n/a/*[python input]
2260n/a
2261n/aclass path_t_converter(CConverter):
2262n/a
2263n/a type = "path_t"
2264n/a impl_by_reference = True
2265n/a parse_by_reference = True
2266n/a
2267n/a converter = 'path_converter'
2268n/a
2269n/a def converter_init(self, *, allow_fd=False, nullable=False):
2270n/a # right now path_t doesn't support default values.
2271n/a # to support a default value, you'll need to override initialize().
2272n/a if self.default not in (unspecified, None):
2273n/a fail("Can't specify a default to the path_t converter!")
2274n/a
2275n/a if self.c_default not in (None, 'Py_None'):
2276n/a raise RuntimeError("Can't specify a c_default to the path_t converter!")
2277n/a
2278n/a self.nullable = nullable
2279n/a self.allow_fd = allow_fd
2280n/a
2281n/a def pre_render(self):
2282n/a def strify(value):
2283n/a if isinstance(value, str):
2284n/a return value
2285n/a return str(int(bool(value)))
2286n/a
2287n/a # add self.py_name here when merging with posixmodule conversion
2288n/a self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format(
2289n/a self.function.name,
2290n/a self.name,
2291n/a strify(self.nullable),
2292n/a strify(self.allow_fd),
2293n/a )
2294n/a
2295n/a def cleanup(self):
2296n/a return "path_cleanup(&" + self.name + ");\n"
2297n/a
2298n/a
2299n/aclass dir_fd_converter(CConverter):
2300n/a type = 'int'
2301n/a
2302n/a def converter_init(self, requires=None):
2303n/a if self.default in (unspecified, None):
2304n/a self.c_default = 'DEFAULT_DIR_FD'
2305n/a if isinstance(requires, str):
2306n/a self.converter = requires.upper() + '_DIR_FD_CONVERTER'
2307n/a else:
2308n/a self.converter = 'dir_fd_converter'
2309n/a
2310n/aclass fildes_converter(CConverter):
2311n/a type = 'int'
2312n/a converter = 'fildes_converter'
2313n/a
2314n/aclass uid_t_converter(CConverter):
2315n/a type = "uid_t"
2316n/a converter = '_Py_Uid_Converter'
2317n/a
2318n/aclass gid_t_converter(CConverter):
2319n/a type = "gid_t"
2320n/a converter = '_Py_Gid_Converter'
2321n/a
2322n/aclass dev_t_converter(CConverter):
2323n/a type = 'dev_t'
2324n/a converter = '_Py_Dev_Converter'
2325n/a
2326n/aclass dev_t_return_converter(unsigned_long_return_converter):
2327n/a type = 'dev_t'
2328n/a conversion_fn = '_PyLong_FromDev'
2329n/a unsigned_cast = '(dev_t)'
2330n/a
2331n/aclass FSConverter_converter(CConverter):
2332n/a type = 'PyObject *'
2333n/a converter = 'PyUnicode_FSConverter'
2334n/a def converter_init(self):
2335n/a if self.default is not unspecified:
2336n/a fail("FSConverter_converter does not support default values")
2337n/a self.c_default = 'NULL'
2338n/a
2339n/a def cleanup(self):
2340n/a return "Py_XDECREF(" + self.name + ");\n"
2341n/a
2342n/aclass pid_t_converter(CConverter):
2343n/a type = 'pid_t'
2344n/a format_unit = '" _Py_PARSE_PID "'
2345n/a
2346n/aclass idtype_t_converter(int_converter):
2347n/a type = 'idtype_t'
2348n/a
2349n/aclass id_t_converter(CConverter):
2350n/a type = 'id_t'
2351n/a format_unit = '" _Py_PARSE_PID "'
2352n/a
2353n/aclass intptr_t_converter(CConverter):
2354n/a type = 'intptr_t'
2355n/a format_unit = '" _Py_PARSE_INTPTR "'
2356n/a
2357n/aclass Py_off_t_converter(CConverter):
2358n/a type = 'Py_off_t'
2359n/a converter = 'Py_off_t_converter'
2360n/a
2361n/aclass Py_off_t_return_converter(long_return_converter):
2362n/a type = 'Py_off_t'
2363n/a conversion_fn = 'PyLong_FromPy_off_t'
2364n/a
2365n/aclass path_confname_converter(CConverter):
2366n/a type="int"
2367n/a converter="conv_path_confname"
2368n/a
2369n/aclass confstr_confname_converter(path_confname_converter):
2370n/a converter='conv_confstr_confname'
2371n/a
2372n/aclass sysconf_confname_converter(path_confname_converter):
2373n/a converter="conv_sysconf_confname"
2374n/a
2375n/aclass sched_param_converter(CConverter):
2376n/a type = 'struct sched_param'
2377n/a converter = 'convert_sched_param'
2378n/a impl_by_reference = True;
2379n/a
2380n/a[python start generated code]*/
2381n/a/*[python end generated code: output=da39a3ee5e6b4b0d input=418fce0e01144461]*/
2382n/a
2383n/a/*[clinic input]
2384n/a
2385n/aos.stat
2386n/a
2387n/a path : path_t(allow_fd=True)
2388n/a Path to be examined; can be string, bytes, path-like object or
2389n/a open-file-descriptor int.
2390n/a
2391n/a *
2392n/a
2393n/a dir_fd : dir_fd(requires='fstatat') = None
2394n/a If not None, it should be a file descriptor open to a directory,
2395n/a and path should be a relative string; path will then be relative to
2396n/a that directory.
2397n/a
2398n/a follow_symlinks: bool = True
2399n/a If False, and the last element of the path is a symbolic link,
2400n/a stat will examine the symbolic link itself instead of the file
2401n/a the link points to.
2402n/a
2403n/aPerform a stat system call on the given path.
2404n/a
2405n/adir_fd and follow_symlinks may not be implemented
2406n/a on your platform. If they are unavailable, using them will raise a
2407n/a NotImplementedError.
2408n/a
2409n/aIt's an error to use dir_fd or follow_symlinks when specifying path as
2410n/a an open file descriptor.
2411n/a
2412n/a[clinic start generated code]*/
2413n/a
2414n/astatic PyObject *
2415n/aos_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
2416n/a/*[clinic end generated code: output=7d4976e6f18a59c5 input=270bd64e7bb3c8f7]*/
2417n/a{
2418n/a return posix_do_stat("stat", path, dir_fd, follow_symlinks);
2419n/a}
2420n/a
2421n/a
2422n/a/*[clinic input]
2423n/aos.lstat
2424n/a
2425n/a path : path_t
2426n/a
2427n/a *
2428n/a
2429n/a dir_fd : dir_fd(requires='fstatat') = None
2430n/a
2431n/aPerform a stat system call on the given path, without following symbolic links.
2432n/a
2433n/aLike stat(), but do not follow symbolic links.
2434n/aEquivalent to stat(path, follow_symlinks=False).
2435n/a[clinic start generated code]*/
2436n/a
2437n/astatic PyObject *
2438n/aos_lstat_impl(PyObject *module, path_t *path, int dir_fd)
2439n/a/*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
2440n/a{
2441n/a int follow_symlinks = 0;
2442n/a return posix_do_stat("lstat", path, dir_fd, follow_symlinks);
2443n/a}
2444n/a
2445n/a
2446n/a/*[clinic input]
2447n/aos.access -> bool
2448n/a
2449n/a path: path_t
2450n/a Path to be tested; can be string or bytes
2451n/a
2452n/a mode: int
2453n/a Operating-system mode bitfield. Can be F_OK to test existence,
2454n/a or the inclusive-OR of R_OK, W_OK, and X_OK.
2455n/a
2456n/a *
2457n/a
2458n/a dir_fd : dir_fd(requires='faccessat') = None
2459n/a If not None, it should be a file descriptor open to a directory,
2460n/a and path should be relative; path will then be relative to that
2461n/a directory.
2462n/a
2463n/a effective_ids: bool = False
2464n/a If True, access will use the effective uid/gid instead of
2465n/a the real uid/gid.
2466n/a
2467n/a follow_symlinks: bool = True
2468n/a If False, and the last element of the path is a symbolic link,
2469n/a access will examine the symbolic link itself instead of the file
2470n/a the link points to.
2471n/a
2472n/aUse the real uid/gid to test for access to a path.
2473n/a
2474n/a{parameters}
2475n/adir_fd, effective_ids, and follow_symlinks may not be implemented
2476n/a on your platform. If they are unavailable, using them will raise a
2477n/a NotImplementedError.
2478n/a
2479n/aNote that most operations will use the effective uid/gid, therefore this
2480n/a routine can be used in a suid/sgid environment to test if the invoking user
2481n/a has the specified access to the path.
2482n/a
2483n/a[clinic start generated code]*/
2484n/a
2485n/astatic int
2486n/aos_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
2487n/a int effective_ids, int follow_symlinks)
2488n/a/*[clinic end generated code: output=cf84158bc90b1a77 input=8e8c3a6ba791fee3]*/
2489n/a{
2490n/a int return_value;
2491n/a
2492n/a#ifdef MS_WINDOWS
2493n/a DWORD attr;
2494n/a#else
2495n/a int result;
2496n/a#endif
2497n/a
2498n/a#ifndef HAVE_FACCESSAT
2499n/a if (follow_symlinks_specified("access", follow_symlinks))
2500n/a return -1;
2501n/a
2502n/a if (effective_ids) {
2503n/a argument_unavailable_error("access", "effective_ids");
2504n/a return -1;
2505n/a }
2506n/a#endif
2507n/a
2508n/a#ifdef MS_WINDOWS
2509n/a Py_BEGIN_ALLOW_THREADS
2510n/a attr = GetFileAttributesW(path->wide);
2511n/a Py_END_ALLOW_THREADS
2512n/a
2513n/a /*
2514n/a * Access is possible if
2515n/a * * we didn't get a -1, and
2516n/a * * write access wasn't requested,
2517n/a * * or the file isn't read-only,
2518n/a * * or it's a directory.
2519n/a * (Directories cannot be read-only on Windows.)
2520n/a */
2521n/a return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
2522n/a (!(mode & 2) ||
2523n/a !(attr & FILE_ATTRIBUTE_READONLY) ||
2524n/a (attr & FILE_ATTRIBUTE_DIRECTORY));
2525n/a#else
2526n/a
2527n/a Py_BEGIN_ALLOW_THREADS
2528n/a#ifdef HAVE_FACCESSAT
2529n/a if ((dir_fd != DEFAULT_DIR_FD) ||
2530n/a effective_ids ||
2531n/a !follow_symlinks) {
2532n/a int flags = 0;
2533n/a if (!follow_symlinks)
2534n/a flags |= AT_SYMLINK_NOFOLLOW;
2535n/a if (effective_ids)
2536n/a flags |= AT_EACCESS;
2537n/a result = faccessat(dir_fd, path->narrow, mode, flags);
2538n/a }
2539n/a else
2540n/a#endif
2541n/a result = access(path->narrow, mode);
2542n/a Py_END_ALLOW_THREADS
2543n/a return_value = !result;
2544n/a#endif
2545n/a
2546n/a return return_value;
2547n/a}
2548n/a
2549n/a#ifndef F_OK
2550n/a#define F_OK 0
2551n/a#endif
2552n/a#ifndef R_OK
2553n/a#define R_OK 4
2554n/a#endif
2555n/a#ifndef W_OK
2556n/a#define W_OK 2
2557n/a#endif
2558n/a#ifndef X_OK
2559n/a#define X_OK 1
2560n/a#endif
2561n/a
2562n/a
2563n/a#ifdef HAVE_TTYNAME
2564n/a/*[clinic input]
2565n/aos.ttyname -> DecodeFSDefault
2566n/a
2567n/a fd: int
2568n/a Integer file descriptor handle.
2569n/a
2570n/a /
2571n/a
2572n/aReturn the name of the terminal device connected to 'fd'.
2573n/a[clinic start generated code]*/
2574n/a
2575n/astatic char *
2576n/aos_ttyname_impl(PyObject *module, int fd)
2577n/a/*[clinic end generated code: output=ed16ad216d813591 input=5f72ca83e76b3b45]*/
2578n/a{
2579n/a char *ret;
2580n/a
2581n/a ret = ttyname(fd);
2582n/a if (ret == NULL)
2583n/a posix_error();
2584n/a return ret;
2585n/a}
2586n/a#endif
2587n/a
2588n/a#ifdef HAVE_CTERMID
2589n/a/*[clinic input]
2590n/aos.ctermid
2591n/a
2592n/aReturn the name of the controlling terminal for this process.
2593n/a[clinic start generated code]*/
2594n/a
2595n/astatic PyObject *
2596n/aos_ctermid_impl(PyObject *module)
2597n/a/*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
2598n/a{
2599n/a char *ret;
2600n/a char buffer[L_ctermid];
2601n/a
2602n/a#ifdef USE_CTERMID_R
2603n/a ret = ctermid_r(buffer);
2604n/a#else
2605n/a ret = ctermid(buffer);
2606n/a#endif
2607n/a if (ret == NULL)
2608n/a return posix_error();
2609n/a return PyUnicode_DecodeFSDefault(buffer);
2610n/a}
2611n/a#endif /* HAVE_CTERMID */
2612n/a
2613n/a
2614n/a/*[clinic input]
2615n/aos.chdir
2616n/a
2617n/a path: path_t(allow_fd='PATH_HAVE_FCHDIR')
2618n/a
2619n/aChange the current working directory to the specified path.
2620n/a
2621n/apath may always be specified as a string.
2622n/aOn some platforms, path may also be specified as an open file descriptor.
2623n/a If this functionality is unavailable, using it raises an exception.
2624n/a[clinic start generated code]*/
2625n/a
2626n/astatic PyObject *
2627n/aos_chdir_impl(PyObject *module, path_t *path)
2628n/a/*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
2629n/a{
2630n/a int result;
2631n/a
2632n/a Py_BEGIN_ALLOW_THREADS
2633n/a#ifdef MS_WINDOWS
2634n/a /* on unix, success = 0, on windows, success = !0 */
2635n/a result = !win32_wchdir(path->wide);
2636n/a#else
2637n/a#ifdef HAVE_FCHDIR
2638n/a if (path->fd != -1)
2639n/a result = fchdir(path->fd);
2640n/a else
2641n/a#endif
2642n/a result = chdir(path->narrow);
2643n/a#endif
2644n/a Py_END_ALLOW_THREADS
2645n/a
2646n/a if (result) {
2647n/a return path_error(path);
2648n/a }
2649n/a
2650n/a Py_RETURN_NONE;
2651n/a}
2652n/a
2653n/a
2654n/a#ifdef HAVE_FCHDIR
2655n/a/*[clinic input]
2656n/aos.fchdir
2657n/a
2658n/a fd: fildes
2659n/a
2660n/aChange to the directory of the given file descriptor.
2661n/a
2662n/afd must be opened on a directory, not a file.
2663n/aEquivalent to os.chdir(fd).
2664n/a
2665n/a[clinic start generated code]*/
2666n/a
2667n/astatic PyObject *
2668n/aos_fchdir_impl(PyObject *module, int fd)
2669n/a/*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
2670n/a{
2671n/a return posix_fildes_fd(fd, fchdir);
2672n/a}
2673n/a#endif /* HAVE_FCHDIR */
2674n/a
2675n/a
2676n/a/*[clinic input]
2677n/aos.chmod
2678n/a
2679n/a path: path_t(allow_fd='PATH_HAVE_FCHMOD')
2680n/a Path to be modified. May always be specified as a str or bytes.
2681n/a On some platforms, path may also be specified as an open file descriptor.
2682n/a If this functionality is unavailable, using it raises an exception.
2683n/a
2684n/a mode: int
2685n/a Operating-system mode bitfield.
2686n/a
2687n/a *
2688n/a
2689n/a dir_fd : dir_fd(requires='fchmodat') = None
2690n/a If not None, it should be a file descriptor open to a directory,
2691n/a and path should be relative; path will then be relative to that
2692n/a directory.
2693n/a
2694n/a follow_symlinks: bool = True
2695n/a If False, and the last element of the path is a symbolic link,
2696n/a chmod will modify the symbolic link itself instead of the file
2697n/a the link points to.
2698n/a
2699n/aChange the access permissions of a file.
2700n/a
2701n/aIt is an error to use dir_fd or follow_symlinks when specifying path as
2702n/a an open file descriptor.
2703n/adir_fd and follow_symlinks may not be implemented on your platform.
2704n/a If they are unavailable, using them will raise a NotImplementedError.
2705n/a
2706n/a[clinic start generated code]*/
2707n/a
2708n/astatic PyObject *
2709n/aos_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
2710n/a int follow_symlinks)
2711n/a/*[clinic end generated code: output=5cf6a94915cc7bff input=7f1618e5e15cc196]*/
2712n/a{
2713n/a int result;
2714n/a
2715n/a#ifdef MS_WINDOWS
2716n/a DWORD attr;
2717n/a#endif
2718n/a
2719n/a#ifdef HAVE_FCHMODAT
2720n/a int fchmodat_nofollow_unsupported = 0;
2721n/a#endif
2722n/a
2723n/a#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
2724n/a if (follow_symlinks_specified("chmod", follow_symlinks))
2725n/a return NULL;
2726n/a#endif
2727n/a
2728n/a#ifdef MS_WINDOWS
2729n/a Py_BEGIN_ALLOW_THREADS
2730n/a attr = GetFileAttributesW(path->wide);
2731n/a if (attr == INVALID_FILE_ATTRIBUTES)
2732n/a result = 0;
2733n/a else {
2734n/a if (mode & _S_IWRITE)
2735n/a attr &= ~FILE_ATTRIBUTE_READONLY;
2736n/a else
2737n/a attr |= FILE_ATTRIBUTE_READONLY;
2738n/a result = SetFileAttributesW(path->wide, attr);
2739n/a }
2740n/a Py_END_ALLOW_THREADS
2741n/a
2742n/a if (!result) {
2743n/a return path_error(path);
2744n/a }
2745n/a#else /* MS_WINDOWS */
2746n/a Py_BEGIN_ALLOW_THREADS
2747n/a#ifdef HAVE_FCHMOD
2748n/a if (path->fd != -1)
2749n/a result = fchmod(path->fd, mode);
2750n/a else
2751n/a#endif
2752n/a#ifdef HAVE_LCHMOD
2753n/a if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2754n/a result = lchmod(path->narrow, mode);
2755n/a else
2756n/a#endif
2757n/a#ifdef HAVE_FCHMODAT
2758n/a if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2759n/a /*
2760n/a * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
2761n/a * The documentation specifically shows how to use it,
2762n/a * and then says it isn't implemented yet.
2763n/a * (true on linux with glibc 2.15, and openindiana 3.x)
2764n/a *
2765n/a * Once it is supported, os.chmod will automatically
2766n/a * support dir_fd and follow_symlinks=False. (Hopefully.)
2767n/a * Until then, we need to be careful what exception we raise.
2768n/a */
2769n/a result = fchmodat(dir_fd, path->narrow, mode,
2770n/a follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2771n/a /*
2772n/a * But wait! We can't throw the exception without allowing threads,
2773n/a * and we can't do that in this nested scope. (Macro trickery, sigh.)
2774n/a */
2775n/a fchmodat_nofollow_unsupported =
2776n/a result &&
2777n/a ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
2778n/a !follow_symlinks;
2779n/a }
2780n/a else
2781n/a#endif
2782n/a result = chmod(path->narrow, mode);
2783n/a Py_END_ALLOW_THREADS
2784n/a
2785n/a if (result) {
2786n/a#ifdef HAVE_FCHMODAT
2787n/a if (fchmodat_nofollow_unsupported) {
2788n/a if (dir_fd != DEFAULT_DIR_FD)
2789n/a dir_fd_and_follow_symlinks_invalid("chmod",
2790n/a dir_fd, follow_symlinks);
2791n/a else
2792n/a follow_symlinks_specified("chmod", follow_symlinks);
2793n/a }
2794n/a else
2795n/a#endif
2796n/a return path_error(path);
2797n/a }
2798n/a#endif
2799n/a
2800n/a Py_RETURN_NONE;
2801n/a}
2802n/a
2803n/a
2804n/a#ifdef HAVE_FCHMOD
2805n/a/*[clinic input]
2806n/aos.fchmod
2807n/a
2808n/a fd: int
2809n/a mode: int
2810n/a
2811n/aChange the access permissions of the file given by file descriptor fd.
2812n/a
2813n/aEquivalent to os.chmod(fd, mode).
2814n/a[clinic start generated code]*/
2815n/a
2816n/astatic PyObject *
2817n/aos_fchmod_impl(PyObject *module, int fd, int mode)
2818n/a/*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/
2819n/a{
2820n/a int res;
2821n/a int async_err = 0;
2822n/a
2823n/a do {
2824n/a Py_BEGIN_ALLOW_THREADS
2825n/a res = fchmod(fd, mode);
2826n/a Py_END_ALLOW_THREADS
2827n/a } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
2828n/a if (res != 0)
2829n/a return (!async_err) ? posix_error() : NULL;
2830n/a
2831n/a Py_RETURN_NONE;
2832n/a}
2833n/a#endif /* HAVE_FCHMOD */
2834n/a
2835n/a
2836n/a#ifdef HAVE_LCHMOD
2837n/a/*[clinic input]
2838n/aos.lchmod
2839n/a
2840n/a path: path_t
2841n/a mode: int
2842n/a
2843n/aChange the access permissions of a file, without following symbolic links.
2844n/a
2845n/aIf path is a symlink, this affects the link itself rather than the target.
2846n/aEquivalent to chmod(path, mode, follow_symlinks=False)."
2847n/a[clinic start generated code]*/
2848n/a
2849n/astatic PyObject *
2850n/aos_lchmod_impl(PyObject *module, path_t *path, int mode)
2851n/a/*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
2852n/a{
2853n/a int res;
2854n/a Py_BEGIN_ALLOW_THREADS
2855n/a res = lchmod(path->narrow, mode);
2856n/a Py_END_ALLOW_THREADS
2857n/a if (res < 0) {
2858n/a path_error(path);
2859n/a return NULL;
2860n/a }
2861n/a Py_RETURN_NONE;
2862n/a}
2863n/a#endif /* HAVE_LCHMOD */
2864n/a
2865n/a
2866n/a#ifdef HAVE_CHFLAGS
2867n/a/*[clinic input]
2868n/aos.chflags
2869n/a
2870n/a path: path_t
2871n/a flags: unsigned_long(bitwise=True)
2872n/a follow_symlinks: bool=True
2873n/a
2874n/aSet file flags.
2875n/a
2876n/aIf follow_symlinks is False, and the last element of the path is a symbolic
2877n/a link, chflags will change flags on the symbolic link itself instead of the
2878n/a file the link points to.
2879n/afollow_symlinks may not be implemented on your platform. If it is
2880n/aunavailable, using it will raise a NotImplementedError.
2881n/a
2882n/a[clinic start generated code]*/
2883n/a
2884n/astatic PyObject *
2885n/aos_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
2886n/a int follow_symlinks)
2887n/a/*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
2888n/a{
2889n/a int result;
2890n/a
2891n/a#ifndef HAVE_LCHFLAGS
2892n/a if (follow_symlinks_specified("chflags", follow_symlinks))
2893n/a return NULL;
2894n/a#endif
2895n/a
2896n/a Py_BEGIN_ALLOW_THREADS
2897n/a#ifdef HAVE_LCHFLAGS
2898n/a if (!follow_symlinks)
2899n/a result = lchflags(path->narrow, flags);
2900n/a else
2901n/a#endif
2902n/a result = chflags(path->narrow, flags);
2903n/a Py_END_ALLOW_THREADS
2904n/a
2905n/a if (result)
2906n/a return path_error(path);
2907n/a
2908n/a Py_RETURN_NONE;
2909n/a}
2910n/a#endif /* HAVE_CHFLAGS */
2911n/a
2912n/a
2913n/a#ifdef HAVE_LCHFLAGS
2914n/a/*[clinic input]
2915n/aos.lchflags
2916n/a
2917n/a path: path_t
2918n/a flags: unsigned_long(bitwise=True)
2919n/a
2920n/aSet file flags.
2921n/a
2922n/aThis function will not follow symbolic links.
2923n/aEquivalent to chflags(path, flags, follow_symlinks=False).
2924n/a[clinic start generated code]*/
2925n/a
2926n/astatic PyObject *
2927n/aos_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
2928n/a/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
2929n/a{
2930n/a int res;
2931n/a Py_BEGIN_ALLOW_THREADS
2932n/a res = lchflags(path->narrow, flags);
2933n/a Py_END_ALLOW_THREADS
2934n/a if (res < 0) {
2935n/a return path_error(path);
2936n/a }
2937n/a Py_RETURN_NONE;
2938n/a}
2939n/a#endif /* HAVE_LCHFLAGS */
2940n/a
2941n/a
2942n/a#ifdef HAVE_CHROOT
2943n/a/*[clinic input]
2944n/aos.chroot
2945n/a path: path_t
2946n/a
2947n/aChange root directory to path.
2948n/a
2949n/a[clinic start generated code]*/
2950n/a
2951n/astatic PyObject *
2952n/aos_chroot_impl(PyObject *module, path_t *path)
2953n/a/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
2954n/a{
2955n/a int res;
2956n/a Py_BEGIN_ALLOW_THREADS
2957n/a res = chroot(path->narrow);
2958n/a Py_END_ALLOW_THREADS
2959n/a if (res < 0)
2960n/a return path_error(path);
2961n/a Py_RETURN_NONE;
2962n/a}
2963n/a#endif /* HAVE_CHROOT */
2964n/a
2965n/a
2966n/a#ifdef HAVE_FSYNC
2967n/a/*[clinic input]
2968n/aos.fsync
2969n/a
2970n/a fd: fildes
2971n/a
2972n/aForce write of fd to disk.
2973n/a[clinic start generated code]*/
2974n/a
2975n/astatic PyObject *
2976n/aos_fsync_impl(PyObject *module, int fd)
2977n/a/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
2978n/a{
2979n/a return posix_fildes_fd(fd, fsync);
2980n/a}
2981n/a#endif /* HAVE_FSYNC */
2982n/a
2983n/a
2984n/a#ifdef HAVE_SYNC
2985n/a/*[clinic input]
2986n/aos.sync
2987n/a
2988n/aForce write of everything to disk.
2989n/a[clinic start generated code]*/
2990n/a
2991n/astatic PyObject *
2992n/aos_sync_impl(PyObject *module)
2993n/a/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
2994n/a{
2995n/a Py_BEGIN_ALLOW_THREADS
2996n/a sync();
2997n/a Py_END_ALLOW_THREADS
2998n/a Py_RETURN_NONE;
2999n/a}
3000n/a#endif /* HAVE_SYNC */
3001n/a
3002n/a
3003n/a#ifdef HAVE_FDATASYNC
3004n/a#ifdef __hpux
3005n/aextern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
3006n/a#endif
3007n/a
3008n/a/*[clinic input]
3009n/aos.fdatasync
3010n/a
3011n/a fd: fildes
3012n/a
3013n/aForce write of fd to disk without forcing update of metadata.
3014n/a[clinic start generated code]*/
3015n/a
3016n/astatic PyObject *
3017n/aos_fdatasync_impl(PyObject *module, int fd)
3018n/a/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
3019n/a{
3020n/a return posix_fildes_fd(fd, fdatasync);
3021n/a}
3022n/a#endif /* HAVE_FDATASYNC */
3023n/a
3024n/a
3025n/a#ifdef HAVE_CHOWN
3026n/a/*[clinic input]
3027n/aos.chown
3028n/a
3029n/a path : path_t(allow_fd='PATH_HAVE_FCHOWN')
3030n/a Path to be examined; can be string, bytes, or open-file-descriptor int.
3031n/a
3032n/a uid: uid_t
3033n/a
3034n/a gid: gid_t
3035n/a
3036n/a *
3037n/a
3038n/a dir_fd : dir_fd(requires='fchownat') = None
3039n/a If not None, it should be a file descriptor open to a directory,
3040n/a and path should be relative; path will then be relative to that
3041n/a directory.
3042n/a
3043n/a follow_symlinks: bool = True
3044n/a If False, and the last element of the path is a symbolic link,
3045n/a stat will examine the symbolic link itself instead of the file
3046n/a the link points to.
3047n/a
3048n/aChange the owner and group id of path to the numeric uid and gid.\
3049n/a
3050n/apath may always be specified as a string.
3051n/aOn some platforms, path may also be specified as an open file descriptor.
3052n/a If this functionality is unavailable, using it raises an exception.
3053n/aIf dir_fd is not None, it should be a file descriptor open to a directory,
3054n/a and path should be relative; path will then be relative to that directory.
3055n/aIf follow_symlinks is False, and the last element of the path is a symbolic
3056n/a link, chown will modify the symbolic link itself instead of the file the
3057n/a link points to.
3058n/aIt is an error to use dir_fd or follow_symlinks when specifying path as
3059n/a an open file descriptor.
3060n/adir_fd and follow_symlinks may not be implemented on your platform.
3061n/a If they are unavailable, using them will raise a NotImplementedError.
3062n/a
3063n/a[clinic start generated code]*/
3064n/a
3065n/astatic PyObject *
3066n/aos_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
3067n/a int dir_fd, int follow_symlinks)
3068n/a/*[clinic end generated code: output=4beadab0db5f70cd input=a61cc35574814d5d]*/
3069n/a{
3070n/a int result;
3071n/a
3072n/a#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
3073n/a if (follow_symlinks_specified("chown", follow_symlinks))
3074n/a return NULL;
3075n/a#endif
3076n/a if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
3077n/a fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
3078n/a return NULL;
3079n/a
3080n/a#ifdef __APPLE__
3081n/a /*
3082n/a * This is for Mac OS X 10.3, which doesn't have lchown.
3083n/a * (But we still have an lchown symbol because of weak-linking.)
3084n/a * It doesn't have fchownat either. So there's no possibility
3085n/a * of a graceful failover.
3086n/a */
3087n/a if ((!follow_symlinks) && (lchown == NULL)) {
3088n/a follow_symlinks_specified("chown", follow_symlinks);
3089n/a return NULL;
3090n/a }
3091n/a#endif
3092n/a
3093n/a Py_BEGIN_ALLOW_THREADS
3094n/a#ifdef HAVE_FCHOWN
3095n/a if (path->fd != -1)
3096n/a result = fchown(path->fd, uid, gid);
3097n/a else
3098n/a#endif
3099n/a#ifdef HAVE_LCHOWN
3100n/a if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3101n/a result = lchown(path->narrow, uid, gid);
3102n/a else
3103n/a#endif
3104n/a#ifdef HAVE_FCHOWNAT
3105n/a if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))
3106n/a result = fchownat(dir_fd, path->narrow, uid, gid,
3107n/a follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3108n/a else
3109n/a#endif
3110n/a result = chown(path->narrow, uid, gid);
3111n/a Py_END_ALLOW_THREADS
3112n/a
3113n/a if (result)
3114n/a return path_error(path);
3115n/a
3116n/a Py_RETURN_NONE;
3117n/a}
3118n/a#endif /* HAVE_CHOWN */
3119n/a
3120n/a
3121n/a#ifdef HAVE_FCHOWN
3122n/a/*[clinic input]
3123n/aos.fchown
3124n/a
3125n/a fd: int
3126n/a uid: uid_t
3127n/a gid: gid_t
3128n/a
3129n/aChange the owner and group id of the file specified by file descriptor.
3130n/a
3131n/aEquivalent to os.chown(fd, uid, gid).
3132n/a
3133n/a[clinic start generated code]*/
3134n/a
3135n/astatic PyObject *
3136n/aos_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
3137n/a/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
3138n/a{
3139n/a int res;
3140n/a int async_err = 0;
3141n/a
3142n/a do {
3143n/a Py_BEGIN_ALLOW_THREADS
3144n/a res = fchown(fd, uid, gid);
3145n/a Py_END_ALLOW_THREADS
3146n/a } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3147n/a if (res != 0)
3148n/a return (!async_err) ? posix_error() : NULL;
3149n/a
3150n/a Py_RETURN_NONE;
3151n/a}
3152n/a#endif /* HAVE_FCHOWN */
3153n/a
3154n/a
3155n/a#ifdef HAVE_LCHOWN
3156n/a/*[clinic input]
3157n/aos.lchown
3158n/a
3159n/a path : path_t
3160n/a uid: uid_t
3161n/a gid: gid_t
3162n/a
3163n/aChange the owner and group id of path to the numeric uid and gid.
3164n/a
3165n/aThis function will not follow symbolic links.
3166n/aEquivalent to os.chown(path, uid, gid, follow_symlinks=False).
3167n/a[clinic start generated code]*/
3168n/a
3169n/astatic PyObject *
3170n/aos_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
3171n/a/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
3172n/a{
3173n/a int res;
3174n/a Py_BEGIN_ALLOW_THREADS
3175n/a res = lchown(path->narrow, uid, gid);
3176n/a Py_END_ALLOW_THREADS
3177n/a if (res < 0) {
3178n/a return path_error(path);
3179n/a }
3180n/a Py_RETURN_NONE;
3181n/a}
3182n/a#endif /* HAVE_LCHOWN */
3183n/a
3184n/a
3185n/astatic PyObject *
3186n/aposix_getcwd(int use_bytes)
3187n/a{
3188n/a char *buf, *tmpbuf;
3189n/a char *cwd;
3190n/a const size_t chunk = 1024;
3191n/a size_t buflen = 0;
3192n/a PyObject *obj;
3193n/a
3194n/a#ifdef MS_WINDOWS
3195n/a if (!use_bytes) {
3196n/a wchar_t wbuf[MAXPATHLEN];
3197n/a wchar_t *wbuf2 = wbuf;
3198n/a PyObject *resobj;
3199n/a DWORD len;
3200n/a Py_BEGIN_ALLOW_THREADS
3201n/a len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
3202n/a /* If the buffer is large enough, len does not include the
3203n/a terminating \0. If the buffer is too small, len includes
3204n/a the space needed for the terminator. */
3205n/a if (len >= Py_ARRAY_LENGTH(wbuf)) {
3206n/a wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
3207n/a if (wbuf2)
3208n/a len = GetCurrentDirectoryW(len, wbuf2);
3209n/a }
3210n/a Py_END_ALLOW_THREADS
3211n/a if (!wbuf2) {
3212n/a PyErr_NoMemory();
3213n/a return NULL;
3214n/a }
3215n/a if (!len) {
3216n/a if (wbuf2 != wbuf)
3217n/a PyMem_RawFree(wbuf2);
3218n/a return PyErr_SetFromWindowsErr(0);
3219n/a }
3220n/a resobj = PyUnicode_FromWideChar(wbuf2, len);
3221n/a if (wbuf2 != wbuf)
3222n/a PyMem_RawFree(wbuf2);
3223n/a return resobj;
3224n/a }
3225n/a
3226n/a if (win32_warn_bytes_api())
3227n/a return NULL;
3228n/a#endif
3229n/a
3230n/a buf = cwd = NULL;
3231n/a Py_BEGIN_ALLOW_THREADS
3232n/a do {
3233n/a buflen += chunk;
3234n/a#ifdef MS_WINDOWS
3235n/a if (buflen > INT_MAX) {
3236n/a PyErr_NoMemory();
3237n/a break;
3238n/a }
3239n/a#endif
3240n/a tmpbuf = PyMem_RawRealloc(buf, buflen);
3241n/a if (tmpbuf == NULL)
3242n/a break;
3243n/a
3244n/a buf = tmpbuf;
3245n/a#ifdef MS_WINDOWS
3246n/a cwd = getcwd(buf, (int)buflen);
3247n/a#else
3248n/a cwd = getcwd(buf, buflen);
3249n/a#endif
3250n/a } while (cwd == NULL && errno == ERANGE);
3251n/a Py_END_ALLOW_THREADS
3252n/a
3253n/a if (cwd == NULL) {
3254n/a PyMem_RawFree(buf);
3255n/a return posix_error();
3256n/a }
3257n/a
3258n/a if (use_bytes)
3259n/a obj = PyBytes_FromStringAndSize(buf, strlen(buf));
3260n/a else
3261n/a obj = PyUnicode_DecodeFSDefault(buf);
3262n/a PyMem_RawFree(buf);
3263n/a
3264n/a return obj;
3265n/a}
3266n/a
3267n/a
3268n/a/*[clinic input]
3269n/aos.getcwd
3270n/a
3271n/aReturn a unicode string representing the current working directory.
3272n/a[clinic start generated code]*/
3273n/a
3274n/astatic PyObject *
3275n/aos_getcwd_impl(PyObject *module)
3276n/a/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
3277n/a{
3278n/a return posix_getcwd(0);
3279n/a}
3280n/a
3281n/a
3282n/a/*[clinic input]
3283n/aos.getcwdb
3284n/a
3285n/aReturn a bytes string representing the current working directory.
3286n/a[clinic start generated code]*/
3287n/a
3288n/astatic PyObject *
3289n/aos_getcwdb_impl(PyObject *module)
3290n/a/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
3291n/a{
3292n/a return posix_getcwd(1);
3293n/a}
3294n/a
3295n/a
3296n/a#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
3297n/a#define HAVE_LINK 1
3298n/a#endif
3299n/a
3300n/a#ifdef HAVE_LINK
3301n/a/*[clinic input]
3302n/a
3303n/aos.link
3304n/a
3305n/a src : path_t
3306n/a dst : path_t
3307n/a *
3308n/a src_dir_fd : dir_fd = None
3309n/a dst_dir_fd : dir_fd = None
3310n/a follow_symlinks: bool = True
3311n/a
3312n/aCreate a hard link to a file.
3313n/a
3314n/aIf either src_dir_fd or dst_dir_fd is not None, it should be a file
3315n/a descriptor open to a directory, and the respective path string (src or dst)
3316n/a should be relative; the path will then be relative to that directory.
3317n/aIf follow_symlinks is False, and the last element of src is a symbolic
3318n/a link, link will create a link to the symbolic link itself instead of the
3319n/a file the link points to.
3320n/asrc_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
3321n/a platform. If they are unavailable, using them will raise a
3322n/a NotImplementedError.
3323n/a[clinic start generated code]*/
3324n/a
3325n/astatic PyObject *
3326n/aos_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
3327n/a int dst_dir_fd, int follow_symlinks)
3328n/a/*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/
3329n/a{
3330n/a#ifdef MS_WINDOWS
3331n/a BOOL result = FALSE;
3332n/a#else
3333n/a int result;
3334n/a#endif
3335n/a
3336n/a#ifndef HAVE_LINKAT
3337n/a if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
3338n/a argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
3339n/a return NULL;
3340n/a }
3341n/a#endif
3342n/a
3343n/a#ifndef MS_WINDOWS
3344n/a if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
3345n/a PyErr_SetString(PyExc_NotImplementedError,
3346n/a "link: src and dst must be the same type");
3347n/a return NULL;
3348n/a }
3349n/a#endif
3350n/a
3351n/a#ifdef MS_WINDOWS
3352n/a Py_BEGIN_ALLOW_THREADS
3353n/a result = CreateHardLinkW(dst->wide, src->wide, NULL);
3354n/a Py_END_ALLOW_THREADS
3355n/a
3356n/a if (!result)
3357n/a return path_error2(src, dst);
3358n/a#else
3359n/a Py_BEGIN_ALLOW_THREADS
3360n/a#ifdef HAVE_LINKAT
3361n/a if ((src_dir_fd != DEFAULT_DIR_FD) ||
3362n/a (dst_dir_fd != DEFAULT_DIR_FD) ||
3363n/a (!follow_symlinks))
3364n/a result = linkat(src_dir_fd, src->narrow,
3365n/a dst_dir_fd, dst->narrow,
3366n/a follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
3367n/a else
3368n/a#endif /* HAVE_LINKAT */
3369n/a result = link(src->narrow, dst->narrow);
3370n/a Py_END_ALLOW_THREADS
3371n/a
3372n/a if (result)
3373n/a return path_error2(src, dst);
3374n/a#endif /* MS_WINDOWS */
3375n/a
3376n/a Py_RETURN_NONE;
3377n/a}
3378n/a#endif
3379n/a
3380n/a
3381n/a#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
3382n/astatic PyObject *
3383n/a_listdir_windows_no_opendir(path_t *path, PyObject *list)
3384n/a{
3385n/a PyObject *v;
3386n/a HANDLE hFindFile = INVALID_HANDLE_VALUE;
3387n/a BOOL result;
3388n/a wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
3389n/a /* only claim to have space for MAX_PATH */
3390n/a Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
3391n/a wchar_t *wnamebuf = NULL;
3392n/a
3393n/a WIN32_FIND_DATAW wFileData;
3394n/a const wchar_t *po_wchars;
3395n/a
3396n/a if (!path->wide) { /* Default arg: "." */
3397n/a po_wchars = L".";
3398n/a len = 1;
3399n/a } else {
3400n/a po_wchars = path->wide;
3401n/a len = wcslen(path->wide);
3402n/a }
3403n/a /* The +5 is so we can append "\\*.*\0" */
3404n/a wnamebuf = PyMem_New(wchar_t, len + 5);
3405n/a if (!wnamebuf) {
3406n/a PyErr_NoMemory();
3407n/a goto exit;
3408n/a }
3409n/a wcscpy(wnamebuf, po_wchars);
3410n/a if (len > 0) {
3411n/a wchar_t wch = wnamebuf[len-1];
3412n/a if (wch != SEP && wch != ALTSEP && wch != L':')
3413n/a wnamebuf[len++] = SEP;
3414n/a wcscpy(wnamebuf + len, L"*.*");
3415n/a }
3416n/a if ((list = PyList_New(0)) == NULL) {
3417n/a goto exit;
3418n/a }
3419n/a Py_BEGIN_ALLOW_THREADS
3420n/a hFindFile = FindFirstFileW(wnamebuf, &wFileData);
3421n/a Py_END_ALLOW_THREADS
3422n/a if (hFindFile == INVALID_HANDLE_VALUE) {
3423n/a int error = GetLastError();
3424n/a if (error == ERROR_FILE_NOT_FOUND)
3425n/a goto exit;
3426n/a Py_DECREF(list);
3427n/a list = path_error(path);
3428n/a goto exit;
3429n/a }
3430n/a do {
3431n/a /* Skip over . and .. */
3432n/a if (wcscmp(wFileData.cFileName, L".") != 0 &&
3433n/a wcscmp(wFileData.cFileName, L"..") != 0) {
3434n/a v = PyUnicode_FromWideChar(wFileData.cFileName,
3435n/a wcslen(wFileData.cFileName));
3436n/a if (path->narrow && v) {
3437n/a Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
3438n/a }
3439n/a if (v == NULL) {
3440n/a Py_DECREF(list);
3441n/a list = NULL;
3442n/a break;
3443n/a }
3444n/a if (PyList_Append(list, v) != 0) {
3445n/a Py_DECREF(v);
3446n/a Py_DECREF(list);
3447n/a list = NULL;
3448n/a break;
3449n/a }
3450n/a Py_DECREF(v);
3451n/a }
3452n/a Py_BEGIN_ALLOW_THREADS
3453n/a result = FindNextFileW(hFindFile, &wFileData);
3454n/a Py_END_ALLOW_THREADS
3455n/a /* FindNextFile sets error to ERROR_NO_MORE_FILES if
3456n/a it got to the end of the directory. */
3457n/a if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
3458n/a Py_DECREF(list);
3459n/a list = path_error(path);
3460n/a goto exit;
3461n/a }
3462n/a } while (result == TRUE);
3463n/a
3464n/aexit:
3465n/a if (hFindFile != INVALID_HANDLE_VALUE) {
3466n/a if (FindClose(hFindFile) == FALSE) {
3467n/a if (list != NULL) {
3468n/a Py_DECREF(list);
3469n/a list = path_error(path);
3470n/a }
3471n/a }
3472n/a }
3473n/a PyMem_Free(wnamebuf);
3474n/a
3475n/a return list;
3476n/a} /* end of _listdir_windows_no_opendir */
3477n/a
3478n/a#else /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
3479n/a
3480n/astatic PyObject *
3481n/a_posix_listdir(path_t *path, PyObject *list)
3482n/a{
3483n/a PyObject *v;
3484n/a DIR *dirp = NULL;
3485n/a struct dirent *ep;
3486n/a int return_str; /* if false, return bytes */
3487n/a#ifdef HAVE_FDOPENDIR
3488n/a int fd = -1;
3489n/a#endif
3490n/a
3491n/a errno = 0;
3492n/a#ifdef HAVE_FDOPENDIR
3493n/a if (path->fd != -1) {
3494n/a /* closedir() closes the FD, so we duplicate it */
3495n/a fd = _Py_dup(path->fd);
3496n/a if (fd == -1)
3497n/a return NULL;
3498n/a
3499n/a return_str = 1;
3500n/a
3501n/a Py_BEGIN_ALLOW_THREADS
3502n/a dirp = fdopendir(fd);
3503n/a Py_END_ALLOW_THREADS
3504n/a }
3505n/a else
3506n/a#endif
3507n/a {
3508n/a const char *name;
3509n/a if (path->narrow) {
3510n/a name = path->narrow;
3511n/a /* only return bytes if they specified a bytes object */
3512n/a return_str = !(PyBytes_Check(path->object));
3513n/a }
3514n/a else {
3515n/a name = ".";
3516n/a return_str = 1;
3517n/a }
3518n/a
3519n/a Py_BEGIN_ALLOW_THREADS
3520n/a dirp = opendir(name);
3521n/a Py_END_ALLOW_THREADS
3522n/a }
3523n/a
3524n/a if (dirp == NULL) {
3525n/a list = path_error(path);
3526n/a#ifdef HAVE_FDOPENDIR
3527n/a if (fd != -1) {
3528n/a Py_BEGIN_ALLOW_THREADS
3529n/a close(fd);
3530n/a Py_END_ALLOW_THREADS
3531n/a }
3532n/a#endif
3533n/a goto exit;
3534n/a }
3535n/a if ((list = PyList_New(0)) == NULL) {
3536n/a goto exit;
3537n/a }
3538n/a for (;;) {
3539n/a errno = 0;
3540n/a Py_BEGIN_ALLOW_THREADS
3541n/a ep = readdir(dirp);
3542n/a Py_END_ALLOW_THREADS
3543n/a if (ep == NULL) {
3544n/a if (errno == 0) {
3545n/a break;
3546n/a } else {
3547n/a Py_DECREF(list);
3548n/a list = path_error(path);
3549n/a goto exit;
3550n/a }
3551n/a }
3552n/a if (ep->d_name[0] == '.' &&
3553n/a (NAMLEN(ep) == 1 ||
3554n/a (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
3555n/a continue;
3556n/a if (return_str)
3557n/a v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
3558n/a else
3559n/a v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
3560n/a if (v == NULL) {
3561n/a Py_CLEAR(list);
3562n/a break;
3563n/a }
3564n/a if (PyList_Append(list, v) != 0) {
3565n/a Py_DECREF(v);
3566n/a Py_CLEAR(list);
3567n/a break;
3568n/a }
3569n/a Py_DECREF(v);
3570n/a }
3571n/a
3572n/aexit:
3573n/a if (dirp != NULL) {
3574n/a Py_BEGIN_ALLOW_THREADS
3575n/a#ifdef HAVE_FDOPENDIR
3576n/a if (fd > -1)
3577n/a rewinddir(dirp);
3578n/a#endif
3579n/a closedir(dirp);
3580n/a Py_END_ALLOW_THREADS
3581n/a }
3582n/a
3583n/a return list;
3584n/a} /* end of _posix_listdir */
3585n/a#endif /* which OS */
3586n/a
3587n/a
3588n/a/*[clinic input]
3589n/aos.listdir
3590n/a
3591n/a path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
3592n/a
3593n/aReturn a list containing the names of the files in the directory.
3594n/a
3595n/apath can be specified as either str or bytes. If path is bytes,
3596n/a the filenames returned will also be bytes; in all other circumstances
3597n/a the filenames returned will be str.
3598n/aIf path is None, uses the path='.'.
3599n/aOn some platforms, path may also be specified as an open file descriptor;\
3600n/a the file descriptor must refer to a directory.
3601n/a If this functionality is unavailable, using it raises NotImplementedError.
3602n/a
3603n/aThe list is in arbitrary order. It does not include the special
3604n/aentries '.' and '..' even if they are present in the directory.
3605n/a
3606n/a
3607n/a[clinic start generated code]*/
3608n/a
3609n/astatic PyObject *
3610n/aos_listdir_impl(PyObject *module, path_t *path)
3611n/a/*[clinic end generated code: output=293045673fcd1a75 input=09e300416e3cd729]*/
3612n/a{
3613n/a#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
3614n/a return _listdir_windows_no_opendir(path, NULL);
3615n/a#else
3616n/a return _posix_listdir(path, NULL);
3617n/a#endif
3618n/a}
3619n/a
3620n/a#ifdef MS_WINDOWS
3621n/a/* A helper function for abspath on win32 */
3622n/a/*[clinic input]
3623n/aos._getfullpathname
3624n/a
3625n/a path: path_t
3626n/a /
3627n/a
3628n/a[clinic start generated code]*/
3629n/a
3630n/astatic PyObject *
3631n/aos__getfullpathname_impl(PyObject *module, path_t *path)
3632n/a/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
3633n/a{
3634n/a wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
3635n/a wchar_t *wtemp;
3636n/a DWORD result;
3637n/a PyObject *v;
3638n/a
3639n/a result = GetFullPathNameW(path->wide,
3640n/a Py_ARRAY_LENGTH(woutbuf),
3641n/a woutbuf, &wtemp);
3642n/a if (result > Py_ARRAY_LENGTH(woutbuf)) {
3643n/a woutbufp = PyMem_New(wchar_t, result);
3644n/a if (!woutbufp)
3645n/a return PyErr_NoMemory();
3646n/a result = GetFullPathNameW(path->wide, result, woutbufp, &wtemp);
3647n/a }
3648n/a if (result) {
3649n/a v = PyUnicode_FromWideChar(woutbufp, wcslen(woutbufp));
3650n/a if (path->narrow)
3651n/a Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
3652n/a } else
3653n/a v = win32_error_object("GetFullPathNameW", path->object);
3654n/a if (woutbufp != woutbuf)
3655n/a PyMem_Free(woutbufp);
3656n/a return v;
3657n/a}
3658n/a
3659n/a
3660n/a/*[clinic input]
3661n/aos._getfinalpathname
3662n/a
3663n/a path: unicode
3664n/a /
3665n/a
3666n/aA helper function for samepath on windows.
3667n/a[clinic start generated code]*/
3668n/a
3669n/astatic PyObject *
3670n/aos__getfinalpathname_impl(PyObject *module, PyObject *path)
3671n/a/*[clinic end generated code: output=9bd78d0e52782e75 input=71d5e89334891bf4]*/
3672n/a{
3673n/a HANDLE hFile;
3674n/a int buf_size;
3675n/a wchar_t *target_path;
3676n/a int result_length;
3677n/a PyObject *result;
3678n/a const wchar_t *path_wchar;
3679n/a
3680n/a path_wchar = PyUnicode_AsUnicode(path);
3681n/a if (path_wchar == NULL)
3682n/a return NULL;
3683n/a
3684n/a hFile = CreateFileW(
3685n/a path_wchar,
3686n/a 0, /* desired access */
3687n/a 0, /* share mode */
3688n/a NULL, /* security attributes */
3689n/a OPEN_EXISTING,
3690n/a /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
3691n/a FILE_FLAG_BACKUP_SEMANTICS,
3692n/a NULL);
3693n/a
3694n/a if(hFile == INVALID_HANDLE_VALUE)
3695n/a return win32_error_object("CreateFileW", path);
3696n/a
3697n/a /* We have a good handle to the target, use it to determine the
3698n/a target path name. */
3699n/a buf_size = GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_NT);
3700n/a
3701n/a if(!buf_size)
3702n/a return win32_error_object("GetFinalPathNameByHandle", path);
3703n/a
3704n/a target_path = PyMem_New(wchar_t, buf_size+1);
3705n/a if(!target_path)
3706n/a return PyErr_NoMemory();
3707n/a
3708n/a result_length = GetFinalPathNameByHandleW(hFile, target_path,
3709n/a buf_size, VOLUME_NAME_DOS);
3710n/a if(!result_length)
3711n/a return win32_error_object("GetFinalPathNamyByHandle", path);
3712n/a
3713n/a if(!CloseHandle(hFile))
3714n/a return win32_error_object("CloseHandle", path);
3715n/a
3716n/a target_path[result_length] = 0;
3717n/a result = PyUnicode_FromWideChar(target_path, result_length);
3718n/a PyMem_Free(target_path);
3719n/a return result;
3720n/a}
3721n/a
3722n/a/*[clinic input]
3723n/aos._isdir
3724n/a
3725n/a path: path_t
3726n/a /
3727n/a
3728n/aReturn true if the pathname refers to an existing directory.
3729n/a[clinic start generated code]*/
3730n/a
3731n/astatic PyObject *
3732n/aos__isdir_impl(PyObject *module, path_t *path)
3733n/a/*[clinic end generated code: output=75f56f32720836cb input=5e0800149c0ad95f]*/
3734n/a{
3735n/a DWORD attributes;
3736n/a
3737n/a Py_BEGIN_ALLOW_THREADS
3738n/a attributes = GetFileAttributesW(path->wide);
3739n/a Py_END_ALLOW_THREADS
3740n/a
3741n/a if (attributes == INVALID_FILE_ATTRIBUTES)
3742n/a Py_RETURN_FALSE;
3743n/a
3744n/a if (attributes & FILE_ATTRIBUTE_DIRECTORY)
3745n/a Py_RETURN_TRUE;
3746n/a else
3747n/a Py_RETURN_FALSE;
3748n/a}
3749n/a
3750n/a
3751n/a/*[clinic input]
3752n/aos._getvolumepathname
3753n/a
3754n/a path: unicode
3755n/a
3756n/aA helper function for ismount on Win32.
3757n/a[clinic start generated code]*/
3758n/a
3759n/astatic PyObject *
3760n/aos__getvolumepathname_impl(PyObject *module, PyObject *path)
3761n/a/*[clinic end generated code: output=cbdcbd1059ceef4c input=7eacadc40acbda6b]*/
3762n/a{
3763n/a PyObject *result;
3764n/a const wchar_t *path_wchar;
3765n/a wchar_t *mountpath=NULL;
3766n/a size_t buflen;
3767n/a BOOL ret;
3768n/a
3769n/a path_wchar = PyUnicode_AsUnicodeAndSize(path, &buflen);
3770n/a if (path_wchar == NULL)
3771n/a return NULL;
3772n/a buflen += 1;
3773n/a
3774n/a /* Volume path should be shorter than entire path */
3775n/a buflen = Py_MAX(buflen, MAX_PATH);
3776n/a
3777n/a if (buflen > DWORD_MAX) {
3778n/a PyErr_SetString(PyExc_OverflowError, "path too long");
3779n/a return NULL;
3780n/a }
3781n/a
3782n/a mountpath = PyMem_New(wchar_t, buflen);
3783n/a if (mountpath == NULL)
3784n/a return PyErr_NoMemory();
3785n/a
3786n/a Py_BEGIN_ALLOW_THREADS
3787n/a ret = GetVolumePathNameW(path_wchar, mountpath,
3788n/a Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
3789n/a Py_END_ALLOW_THREADS
3790n/a
3791n/a if (!ret) {
3792n/a result = win32_error_object("_getvolumepathname", path);
3793n/a goto exit;
3794n/a }
3795n/a result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
3796n/a
3797n/aexit:
3798n/a PyMem_Free(mountpath);
3799n/a return result;
3800n/a}
3801n/a
3802n/a#endif /* MS_WINDOWS */
3803n/a
3804n/a
3805n/a/*[clinic input]
3806n/aos.mkdir
3807n/a
3808n/a path : path_t
3809n/a
3810n/a mode: int = 0o777
3811n/a
3812n/a *
3813n/a
3814n/a dir_fd : dir_fd(requires='mkdirat') = None
3815n/a
3816n/a# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
3817n/a
3818n/aCreate a directory.
3819n/a
3820n/aIf dir_fd is not None, it should be a file descriptor open to a directory,
3821n/a and path should be relative; path will then be relative to that directory.
3822n/adir_fd may not be implemented on your platform.
3823n/a If it is unavailable, using it will raise a NotImplementedError.
3824n/a
3825n/aThe mode argument is ignored on Windows.
3826n/a[clinic start generated code]*/
3827n/a
3828n/astatic PyObject *
3829n/aos_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
3830n/a/*[clinic end generated code: output=a70446903abe821f input=e965f68377e9b1ce]*/
3831n/a{
3832n/a int result;
3833n/a
3834n/a#ifdef MS_WINDOWS
3835n/a Py_BEGIN_ALLOW_THREADS
3836n/a result = CreateDirectoryW(path->wide, NULL);
3837n/a Py_END_ALLOW_THREADS
3838n/a
3839n/a if (!result)
3840n/a return path_error(path);
3841n/a#else
3842n/a Py_BEGIN_ALLOW_THREADS
3843n/a#if HAVE_MKDIRAT
3844n/a if (dir_fd != DEFAULT_DIR_FD)
3845n/a result = mkdirat(dir_fd, path->narrow, mode);
3846n/a else
3847n/a#endif
3848n/a#if ( defined(__WATCOMC__) || defined(PYCC_VACPP) ) && !defined(__QNX__)
3849n/a result = mkdir(path->narrow);
3850n/a#else
3851n/a result = mkdir(path->narrow, mode);
3852n/a#endif
3853n/a Py_END_ALLOW_THREADS
3854n/a if (result < 0)
3855n/a return path_error(path);
3856n/a#endif /* MS_WINDOWS */
3857n/a Py_RETURN_NONE;
3858n/a}
3859n/a
3860n/a
3861n/a/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
3862n/a#if defined(HAVE_SYS_RESOURCE_H)
3863n/a#include <sys/resource.h>
3864n/a#endif
3865n/a
3866n/a
3867n/a#ifdef HAVE_NICE
3868n/a/*[clinic input]
3869n/aos.nice
3870n/a
3871n/a increment: int
3872n/a /
3873n/a
3874n/aAdd increment to the priority of process and return the new priority.
3875n/a[clinic start generated code]*/
3876n/a
3877n/astatic PyObject *
3878n/aos_nice_impl(PyObject *module, int increment)
3879n/a/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
3880n/a{
3881n/a int value;
3882n/a
3883n/a /* There are two flavours of 'nice': one that returns the new
3884n/a priority (as required by almost all standards out there) and the
3885n/a Linux/FreeBSD/BSDI one, which returns '0' on success and advices
3886n/a the use of getpriority() to get the new priority.
3887n/a
3888n/a If we are of the nice family that returns the new priority, we
3889n/a need to clear errno before the call, and check if errno is filled
3890n/a before calling posix_error() on a returnvalue of -1, because the
3891n/a -1 may be the actual new priority! */
3892n/a
3893n/a errno = 0;
3894n/a value = nice(increment);
3895n/a#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
3896n/a if (value == 0)
3897n/a value = getpriority(PRIO_PROCESS, 0);
3898n/a#endif
3899n/a if (value == -1 && errno != 0)
3900n/a /* either nice() or getpriority() returned an error */
3901n/a return posix_error();
3902n/a return PyLong_FromLong((long) value);
3903n/a}
3904n/a#endif /* HAVE_NICE */
3905n/a
3906n/a
3907n/a#ifdef HAVE_GETPRIORITY
3908n/a/*[clinic input]
3909n/aos.getpriority
3910n/a
3911n/a which: int
3912n/a who: int
3913n/a
3914n/aReturn program scheduling priority.
3915n/a[clinic start generated code]*/
3916n/a
3917n/astatic PyObject *
3918n/aos_getpriority_impl(PyObject *module, int which, int who)
3919n/a/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
3920n/a{
3921n/a int retval;
3922n/a
3923n/a errno = 0;
3924n/a retval = getpriority(which, who);
3925n/a if (errno != 0)
3926n/a return posix_error();
3927n/a return PyLong_FromLong((long)retval);
3928n/a}
3929n/a#endif /* HAVE_GETPRIORITY */
3930n/a
3931n/a
3932n/a#ifdef HAVE_SETPRIORITY
3933n/a/*[clinic input]
3934n/aos.setpriority
3935n/a
3936n/a which: int
3937n/a who: int
3938n/a priority: int
3939n/a
3940n/aSet program scheduling priority.
3941n/a[clinic start generated code]*/
3942n/a
3943n/astatic PyObject *
3944n/aos_setpriority_impl(PyObject *module, int which, int who, int priority)
3945n/a/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
3946n/a{
3947n/a int retval;
3948n/a
3949n/a retval = setpriority(which, who, priority);
3950n/a if (retval == -1)
3951n/a return posix_error();
3952n/a Py_RETURN_NONE;
3953n/a}
3954n/a#endif /* HAVE_SETPRIORITY */
3955n/a
3956n/a
3957n/astatic PyObject *
3958n/ainternal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
3959n/a{
3960n/a const char *function_name = is_replace ? "replace" : "rename";
3961n/a int dir_fd_specified;
3962n/a
3963n/a#ifdef MS_WINDOWS
3964n/a BOOL result;
3965n/a int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
3966n/a#else
3967n/a int result;
3968n/a#endif
3969n/a
3970n/a dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
3971n/a (dst_dir_fd != DEFAULT_DIR_FD);
3972n/a#ifndef HAVE_RENAMEAT
3973n/a if (dir_fd_specified) {
3974n/a argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
3975n/a return NULL;
3976n/a }
3977n/a#endif
3978n/a
3979n/a#ifdef MS_WINDOWS
3980n/a Py_BEGIN_ALLOW_THREADS
3981n/a result = MoveFileExW(src->wide, dst->wide, flags);
3982n/a Py_END_ALLOW_THREADS
3983n/a
3984n/a if (!result)
3985n/a return path_error2(src, dst);
3986n/a
3987n/a#else
3988n/a if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
3989n/a PyErr_Format(PyExc_ValueError,
3990n/a "%s: src and dst must be the same type", function_name);
3991n/a return NULL;
3992n/a }
3993n/a
3994n/a Py_BEGIN_ALLOW_THREADS
3995n/a#ifdef HAVE_RENAMEAT
3996n/a if (dir_fd_specified)
3997n/a result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
3998n/a else
3999n/a#endif
4000n/a result = rename(src->narrow, dst->narrow);
4001n/a Py_END_ALLOW_THREADS
4002n/a
4003n/a if (result)
4004n/a return path_error2(src, dst);
4005n/a#endif
4006n/a Py_RETURN_NONE;
4007n/a}
4008n/a
4009n/a
4010n/a/*[clinic input]
4011n/aos.rename
4012n/a
4013n/a src : path_t
4014n/a dst : path_t
4015n/a *
4016n/a src_dir_fd : dir_fd = None
4017n/a dst_dir_fd : dir_fd = None
4018n/a
4019n/aRename a file or directory.
4020n/a
4021n/aIf either src_dir_fd or dst_dir_fd is not None, it should be a file
4022n/a descriptor open to a directory, and the respective path string (src or dst)
4023n/a should be relative; the path will then be relative to that directory.
4024n/asrc_dir_fd and dst_dir_fd, may not be implemented on your platform.
4025n/a If they are unavailable, using them will raise a NotImplementedError.
4026n/a[clinic start generated code]*/
4027n/a
4028n/astatic PyObject *
4029n/aos_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4030n/a int dst_dir_fd)
4031n/a/*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
4032n/a{
4033n/a return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
4034n/a}
4035n/a
4036n/a
4037n/a/*[clinic input]
4038n/aos.replace = os.rename
4039n/a
4040n/aRename a file or directory, overwriting the destination.
4041n/a
4042n/aIf either src_dir_fd or dst_dir_fd is not None, it should be a file
4043n/a descriptor open to a directory, and the respective path string (src or dst)
4044n/a should be relative; the path will then be relative to that directory.
4045n/asrc_dir_fd and dst_dir_fd, may not be implemented on your platform.
4046n/a If they are unavailable, using them will raise a NotImplementedError."
4047n/a[clinic start generated code]*/
4048n/a
4049n/astatic PyObject *
4050n/aos_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4051n/a int dst_dir_fd)
4052n/a/*[clinic end generated code: output=1968c02e7857422b input=25515dfb107c8421]*/
4053n/a{
4054n/a return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
4055n/a}
4056n/a
4057n/a
4058n/a/*[clinic input]
4059n/aos.rmdir
4060n/a
4061n/a path: path_t
4062n/a *
4063n/a dir_fd: dir_fd(requires='unlinkat') = None
4064n/a
4065n/aRemove a directory.
4066n/a
4067n/aIf dir_fd is not None, it should be a file descriptor open to a directory,
4068n/a and path should be relative; path will then be relative to that directory.
4069n/adir_fd may not be implemented on your platform.
4070n/a If it is unavailable, using it will raise a NotImplementedError.
4071n/a[clinic start generated code]*/
4072n/a
4073n/astatic PyObject *
4074n/aos_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
4075n/a/*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
4076n/a{
4077n/a int result;
4078n/a
4079n/a Py_BEGIN_ALLOW_THREADS
4080n/a#ifdef MS_WINDOWS
4081n/a /* Windows, success=1, UNIX, success=0 */
4082n/a result = !RemoveDirectoryW(path->wide);
4083n/a#else
4084n/a#ifdef HAVE_UNLINKAT
4085n/a if (dir_fd != DEFAULT_DIR_FD)
4086n/a result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
4087n/a else
4088n/a#endif
4089n/a result = rmdir(path->narrow);
4090n/a#endif
4091n/a Py_END_ALLOW_THREADS
4092n/a
4093n/a if (result)
4094n/a return path_error(path);
4095n/a
4096n/a Py_RETURN_NONE;
4097n/a}
4098n/a
4099n/a
4100n/a#ifdef HAVE_SYSTEM
4101n/a#ifdef MS_WINDOWS
4102n/a/*[clinic input]
4103n/aos.system -> long
4104n/a
4105n/a command: Py_UNICODE
4106n/a
4107n/aExecute the command in a subshell.
4108n/a[clinic start generated code]*/
4109n/a
4110n/astatic long
4111n/aos_system_impl(PyObject *module, Py_UNICODE *command)
4112n/a/*[clinic end generated code: output=96c4dffee36dfb48 input=303f5ce97df606b0]*/
4113n/a{
4114n/a long result;
4115n/a Py_BEGIN_ALLOW_THREADS
4116n/a _Py_BEGIN_SUPPRESS_IPH
4117n/a result = _wsystem(command);
4118n/a _Py_END_SUPPRESS_IPH
4119n/a Py_END_ALLOW_THREADS
4120n/a return result;
4121n/a}
4122n/a#else /* MS_WINDOWS */
4123n/a/*[clinic input]
4124n/aos.system -> long
4125n/a
4126n/a command: FSConverter
4127n/a
4128n/aExecute the command in a subshell.
4129n/a[clinic start generated code]*/
4130n/a
4131n/astatic long
4132n/aos_system_impl(PyObject *module, PyObject *command)
4133n/a/*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
4134n/a{
4135n/a long result;
4136n/a const char *bytes = PyBytes_AsString(command);
4137n/a Py_BEGIN_ALLOW_THREADS
4138n/a result = system(bytes);
4139n/a Py_END_ALLOW_THREADS
4140n/a return result;
4141n/a}
4142n/a#endif
4143n/a#endif /* HAVE_SYSTEM */
4144n/a
4145n/a
4146n/a/*[clinic input]
4147n/aos.umask
4148n/a
4149n/a mask: int
4150n/a /
4151n/a
4152n/aSet the current numeric umask and return the previous umask.
4153n/a[clinic start generated code]*/
4154n/a
4155n/astatic PyObject *
4156n/aos_umask_impl(PyObject *module, int mask)
4157n/a/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
4158n/a{
4159n/a int i = (int)umask(mask);
4160n/a if (i < 0)
4161n/a return posix_error();
4162n/a return PyLong_FromLong((long)i);
4163n/a}
4164n/a
4165n/a#ifdef MS_WINDOWS
4166n/a
4167n/a/* override the default DeleteFileW behavior so that directory
4168n/asymlinks can be removed with this function, the same as with
4169n/aUnix symlinks */
4170n/aBOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
4171n/a{
4172n/a WIN32_FILE_ATTRIBUTE_DATA info;
4173n/a WIN32_FIND_DATAW find_data;
4174n/a HANDLE find_data_handle;
4175n/a int is_directory = 0;
4176n/a int is_link = 0;
4177n/a
4178n/a if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
4179n/a is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
4180n/a
4181n/a /* Get WIN32_FIND_DATA structure for the path to determine if
4182n/a it is a symlink */
4183n/a if(is_directory &&
4184n/a info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
4185n/a find_data_handle = FindFirstFileW(lpFileName, &find_data);
4186n/a
4187n/a if(find_data_handle != INVALID_HANDLE_VALUE) {
4188n/a /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
4189n/a IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
4190n/a is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
4191n/a find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
4192n/a FindClose(find_data_handle);
4193n/a }
4194n/a }
4195n/a }
4196n/a
4197n/a if (is_directory && is_link)
4198n/a return RemoveDirectoryW(lpFileName);
4199n/a
4200n/a return DeleteFileW(lpFileName);
4201n/a}
4202n/a#endif /* MS_WINDOWS */
4203n/a
4204n/a
4205n/a/*[clinic input]
4206n/aos.unlink
4207n/a
4208n/a path: path_t
4209n/a *
4210n/a dir_fd: dir_fd(requires='unlinkat')=None
4211n/a
4212n/aRemove a file (same as remove()).
4213n/a
4214n/aIf dir_fd is not None, it should be a file descriptor open to a directory,
4215n/a and path should be relative; path will then be relative to that directory.
4216n/adir_fd may not be implemented on your platform.
4217n/a If it is unavailable, using it will raise a NotImplementedError.
4218n/a
4219n/a[clinic start generated code]*/
4220n/a
4221n/astatic PyObject *
4222n/aos_unlink_impl(PyObject *module, path_t *path, int dir_fd)
4223n/a/*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
4224n/a{
4225n/a int result;
4226n/a
4227n/a Py_BEGIN_ALLOW_THREADS
4228n/a _Py_BEGIN_SUPPRESS_IPH
4229n/a#ifdef MS_WINDOWS
4230n/a /* Windows, success=1, UNIX, success=0 */
4231n/a result = !Py_DeleteFileW(path->wide);
4232n/a#else
4233n/a#ifdef HAVE_UNLINKAT
4234n/a if (dir_fd != DEFAULT_DIR_FD)
4235n/a result = unlinkat(dir_fd, path->narrow, 0);
4236n/a else
4237n/a#endif /* HAVE_UNLINKAT */
4238n/a result = unlink(path->narrow);
4239n/a#endif
4240n/a _Py_END_SUPPRESS_IPH
4241n/a Py_END_ALLOW_THREADS
4242n/a
4243n/a if (result)
4244n/a return path_error(path);
4245n/a
4246n/a Py_RETURN_NONE;
4247n/a}
4248n/a
4249n/a
4250n/a/*[clinic input]
4251n/aos.remove = os.unlink
4252n/a
4253n/aRemove a file (same as unlink()).
4254n/a
4255n/aIf dir_fd is not None, it should be a file descriptor open to a directory,
4256n/a and path should be relative; path will then be relative to that directory.
4257n/adir_fd may not be implemented on your platform.
4258n/a If it is unavailable, using it will raise a NotImplementedError.
4259n/a[clinic start generated code]*/
4260n/a
4261n/astatic PyObject *
4262n/aos_remove_impl(PyObject *module, path_t *path, int dir_fd)
4263n/a/*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
4264n/a{
4265n/a return os_unlink_impl(module, path, dir_fd);
4266n/a}
4267n/a
4268n/a
4269n/astatic PyStructSequence_Field uname_result_fields[] = {
4270n/a {"sysname", "operating system name"},
4271n/a {"nodename", "name of machine on network (implementation-defined)"},
4272n/a {"release", "operating system release"},
4273n/a {"version", "operating system version"},
4274n/a {"machine", "hardware identifier"},
4275n/a {NULL}
4276n/a};
4277n/a
4278n/aPyDoc_STRVAR(uname_result__doc__,
4279n/a"uname_result: Result from os.uname().\n\n\
4280n/aThis object may be accessed either as a tuple of\n\
4281n/a (sysname, nodename, release, version, machine),\n\
4282n/aor via the attributes sysname, nodename, release, version, and machine.\n\
4283n/a\n\
4284n/aSee os.uname for more information.");
4285n/a
4286n/astatic PyStructSequence_Desc uname_result_desc = {
4287n/a "uname_result", /* name */
4288n/a uname_result__doc__, /* doc */
4289n/a uname_result_fields,
4290n/a 5
4291n/a};
4292n/a
4293n/astatic PyTypeObject UnameResultType;
4294n/a
4295n/a
4296n/a#ifdef HAVE_UNAME
4297n/a/*[clinic input]
4298n/aos.uname
4299n/a
4300n/aReturn an object identifying the current operating system.
4301n/a
4302n/aThe object behaves like a named tuple with the following fields:
4303n/a (sysname, nodename, release, version, machine)
4304n/a
4305n/a[clinic start generated code]*/
4306n/a
4307n/astatic PyObject *
4308n/aos_uname_impl(PyObject *module)
4309n/a/*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
4310n/a{
4311n/a struct utsname u;
4312n/a int res;
4313n/a PyObject *value;
4314n/a
4315n/a Py_BEGIN_ALLOW_THREADS
4316n/a res = uname(&u);
4317n/a Py_END_ALLOW_THREADS
4318n/a if (res < 0)
4319n/a return posix_error();
4320n/a
4321n/a value = PyStructSequence_New(&UnameResultType);
4322n/a if (value == NULL)
4323n/a return NULL;
4324n/a
4325n/a#define SET(i, field) \
4326n/a { \
4327n/a PyObject *o = PyUnicode_DecodeFSDefault(field); \
4328n/a if (!o) { \
4329n/a Py_DECREF(value); \
4330n/a return NULL; \
4331n/a } \
4332n/a PyStructSequence_SET_ITEM(value, i, o); \
4333n/a } \
4334n/a
4335n/a SET(0, u.sysname);
4336n/a SET(1, u.nodename);
4337n/a SET(2, u.release);
4338n/a SET(3, u.version);
4339n/a SET(4, u.machine);
4340n/a
4341n/a#undef SET
4342n/a
4343n/a return value;
4344n/a}
4345n/a#endif /* HAVE_UNAME */
4346n/a
4347n/a
4348n/a
4349n/atypedef struct {
4350n/a int now;
4351n/a time_t atime_s;
4352n/a long atime_ns;
4353n/a time_t mtime_s;
4354n/a long mtime_ns;
4355n/a} utime_t;
4356n/a
4357n/a/*
4358n/a * these macros assume that "ut" is a pointer to a utime_t
4359n/a * they also intentionally leak the declaration of a pointer named "time"
4360n/a */
4361n/a#define UTIME_TO_TIMESPEC \
4362n/a struct timespec ts[2]; \
4363n/a struct timespec *time; \
4364n/a if (ut->now) \
4365n/a time = NULL; \
4366n/a else { \
4367n/a ts[0].tv_sec = ut->atime_s; \
4368n/a ts[0].tv_nsec = ut->atime_ns; \
4369n/a ts[1].tv_sec = ut->mtime_s; \
4370n/a ts[1].tv_nsec = ut->mtime_ns; \
4371n/a time = ts; \
4372n/a } \
4373n/a
4374n/a#define UTIME_TO_TIMEVAL \
4375n/a struct timeval tv[2]; \
4376n/a struct timeval *time; \
4377n/a if (ut->now) \
4378n/a time = NULL; \
4379n/a else { \
4380n/a tv[0].tv_sec = ut->atime_s; \
4381n/a tv[0].tv_usec = ut->atime_ns / 1000; \
4382n/a tv[1].tv_sec = ut->mtime_s; \
4383n/a tv[1].tv_usec = ut->mtime_ns / 1000; \
4384n/a time = tv; \
4385n/a } \
4386n/a
4387n/a#define UTIME_TO_UTIMBUF \
4388n/a struct utimbuf u; \
4389n/a struct utimbuf *time; \
4390n/a if (ut->now) \
4391n/a time = NULL; \
4392n/a else { \
4393n/a u.actime = ut->atime_s; \
4394n/a u.modtime = ut->mtime_s; \
4395n/a time = &u; \
4396n/a }
4397n/a
4398n/a#define UTIME_TO_TIME_T \
4399n/a time_t timet[2]; \
4400n/a time_t *time; \
4401n/a if (ut->now) \
4402n/a time = NULL; \
4403n/a else { \
4404n/a timet[0] = ut->atime_s; \
4405n/a timet[1] = ut->mtime_s; \
4406n/a time = timet; \
4407n/a } \
4408n/a
4409n/a
4410n/a#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
4411n/a
4412n/astatic int
4413n/autime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
4414n/a{
4415n/a#ifdef HAVE_UTIMENSAT
4416n/a int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
4417n/a UTIME_TO_TIMESPEC;
4418n/a return utimensat(dir_fd, path, time, flags);
4419n/a#elif defined(HAVE_FUTIMESAT)
4420n/a UTIME_TO_TIMEVAL;
4421n/a /*
4422n/a * follow_symlinks will never be false here;
4423n/a * we only allow !follow_symlinks and dir_fd together
4424n/a * if we have utimensat()
4425n/a */
4426n/a assert(follow_symlinks);
4427n/a return futimesat(dir_fd, path, time);
4428n/a#endif
4429n/a}
4430n/a
4431n/a #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
4432n/a#else
4433n/a #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
4434n/a#endif
4435n/a
4436n/a#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
4437n/a
4438n/astatic int
4439n/autime_fd(utime_t *ut, int fd)
4440n/a{
4441n/a#ifdef HAVE_FUTIMENS
4442n/a UTIME_TO_TIMESPEC;
4443n/a return futimens(fd, time);
4444n/a#else
4445n/a UTIME_TO_TIMEVAL;
4446n/a return futimes(fd, time);
4447n/a#endif
4448n/a}
4449n/a
4450n/a #define PATH_UTIME_HAVE_FD 1
4451n/a#else
4452n/a #define PATH_UTIME_HAVE_FD 0
4453n/a#endif
4454n/a
4455n/a#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
4456n/a# define UTIME_HAVE_NOFOLLOW_SYMLINKS
4457n/a#endif
4458n/a
4459n/a#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
4460n/a
4461n/astatic int
4462n/autime_nofollow_symlinks(utime_t *ut, const char *path)
4463n/a{
4464n/a#ifdef HAVE_UTIMENSAT
4465n/a UTIME_TO_TIMESPEC;
4466n/a return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
4467n/a#else
4468n/a UTIME_TO_TIMEVAL;
4469n/a return lutimes(path, time);
4470n/a#endif
4471n/a}
4472n/a
4473n/a#endif
4474n/a
4475n/a#ifndef MS_WINDOWS
4476n/a
4477n/astatic int
4478n/autime_default(utime_t *ut, const char *path)
4479n/a{
4480n/a#ifdef HAVE_UTIMENSAT
4481n/a UTIME_TO_TIMESPEC;
4482n/a return utimensat(DEFAULT_DIR_FD, path, time, 0);
4483n/a#elif defined(HAVE_UTIMES)
4484n/a UTIME_TO_TIMEVAL;
4485n/a return utimes(path, time);
4486n/a#elif defined(HAVE_UTIME_H)
4487n/a UTIME_TO_UTIMBUF;
4488n/a return utime(path, time);
4489n/a#else
4490n/a UTIME_TO_TIME_T;
4491n/a return utime(path, time);
4492n/a#endif
4493n/a}
4494n/a
4495n/a#endif
4496n/a
4497n/astatic int
4498n/asplit_py_long_to_s_and_ns(PyObject *py_long, time_t *s, long *ns)
4499n/a{
4500n/a int result = 0;
4501n/a PyObject *divmod;
4502n/a divmod = PyNumber_Divmod(py_long, billion);
4503n/a if (!divmod)
4504n/a goto exit;
4505n/a *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
4506n/a if ((*s == -1) && PyErr_Occurred())
4507n/a goto exit;
4508n/a *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
4509n/a if ((*ns == -1) && PyErr_Occurred())
4510n/a goto exit;
4511n/a
4512n/a result = 1;
4513n/aexit:
4514n/a Py_XDECREF(divmod);
4515n/a return result;
4516n/a}
4517n/a
4518n/a
4519n/a/*[clinic input]
4520n/aos.utime
4521n/a
4522n/a path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
4523n/a times: object = NULL
4524n/a *
4525n/a ns: object = NULL
4526n/a dir_fd: dir_fd(requires='futimensat') = None
4527n/a follow_symlinks: bool=True
4528n/a
4529n/a# "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
4530n/a
4531n/aSet the access and modified time of path.
4532n/a
4533n/apath may always be specified as a string.
4534n/aOn some platforms, path may also be specified as an open file descriptor.
4535n/a If this functionality is unavailable, using it raises an exception.
4536n/a
4537n/aIf times is not None, it must be a tuple (atime, mtime);
4538n/a atime and mtime should be expressed as float seconds since the epoch.
4539n/aIf ns is specified, it must be a tuple (atime_ns, mtime_ns);
4540n/a atime_ns and mtime_ns should be expressed as integer nanoseconds
4541n/a since the epoch.
4542n/aIf times is None and ns is unspecified, utime uses the current time.
4543n/aSpecifying tuples for both times and ns is an error.
4544n/a
4545n/aIf dir_fd is not None, it should be a file descriptor open to a directory,
4546n/a and path should be relative; path will then be relative to that directory.
4547n/aIf follow_symlinks is False, and the last element of the path is a symbolic
4548n/a link, utime will modify the symbolic link itself instead of the file the
4549n/a link points to.
4550n/aIt is an error to use dir_fd or follow_symlinks when specifying path
4551n/a as an open file descriptor.
4552n/adir_fd and follow_symlinks may not be available on your platform.
4553n/a If they are unavailable, using them will raise a NotImplementedError.
4554n/a
4555n/a[clinic start generated code]*/
4556n/a
4557n/astatic PyObject *
4558n/aos_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
4559n/a int dir_fd, int follow_symlinks)
4560n/a/*[clinic end generated code: output=cfcac69d027b82cf input=081cdc54ca685385]*/
4561n/a{
4562n/a#ifdef MS_WINDOWS
4563n/a HANDLE hFile;
4564n/a FILETIME atime, mtime;
4565n/a#else
4566n/a int result;
4567n/a#endif
4568n/a
4569n/a PyObject *return_value = NULL;
4570n/a utime_t utime;
4571n/a
4572n/a memset(&utime, 0, sizeof(utime_t));
4573n/a
4574n/a if (times && (times != Py_None) && ns) {
4575n/a PyErr_SetString(PyExc_ValueError,
4576n/a "utime: you may specify either 'times'"
4577n/a " or 'ns' but not both");
4578n/a goto exit;
4579n/a }
4580n/a
4581n/a if (times && (times != Py_None)) {
4582n/a time_t a_sec, m_sec;
4583n/a long a_nsec, m_nsec;
4584n/a if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
4585n/a PyErr_SetString(PyExc_TypeError,
4586n/a "utime: 'times' must be either"
4587n/a " a tuple of two ints or None");
4588n/a goto exit;
4589n/a }
4590n/a utime.now = 0;
4591n/a if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
4592n/a &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
4593n/a _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
4594n/a &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
4595n/a goto exit;
4596n/a }
4597n/a utime.atime_s = a_sec;
4598n/a utime.atime_ns = a_nsec;
4599n/a utime.mtime_s = m_sec;
4600n/a utime.mtime_ns = m_nsec;
4601n/a }
4602n/a else if (ns) {
4603n/a if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
4604n/a PyErr_SetString(PyExc_TypeError,
4605n/a "utime: 'ns' must be a tuple of two ints");
4606n/a goto exit;
4607n/a }
4608n/a utime.now = 0;
4609n/a if (!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 0),
4610n/a &utime.atime_s, &utime.atime_ns) ||
4611n/a !split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 1),
4612n/a &utime.mtime_s, &utime.mtime_ns)) {
4613n/a goto exit;
4614n/a }
4615n/a }
4616n/a else {
4617n/a /* times and ns are both None/unspecified. use "now". */
4618n/a utime.now = 1;
4619n/a }
4620n/a
4621n/a#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
4622n/a if (follow_symlinks_specified("utime", follow_symlinks))
4623n/a goto exit;
4624n/a#endif
4625n/a
4626n/a if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
4627n/a dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
4628n/a fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
4629n/a goto exit;
4630n/a
4631n/a#if !defined(HAVE_UTIMENSAT)
4632n/a if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
4633n/a PyErr_SetString(PyExc_ValueError,
4634n/a "utime: cannot use dir_fd and follow_symlinks "
4635n/a "together on this platform");
4636n/a goto exit;
4637n/a }
4638n/a#endif
4639n/a
4640n/a#ifdef MS_WINDOWS
4641n/a Py_BEGIN_ALLOW_THREADS
4642n/a hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
4643n/a NULL, OPEN_EXISTING,
4644n/a FILE_FLAG_BACKUP_SEMANTICS, NULL);
4645n/a Py_END_ALLOW_THREADS
4646n/a if (hFile == INVALID_HANDLE_VALUE) {
4647n/a path_error(path);
4648n/a goto exit;
4649n/a }
4650n/a
4651n/a if (utime.now) {
4652n/a GetSystemTimeAsFileTime(&mtime);
4653n/a atime = mtime;
4654n/a }
4655n/a else {
4656n/a _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
4657n/a _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
4658n/a }
4659n/a if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
4660n/a /* Avoid putting the file name into the error here,
4661n/a as that may confuse the user into believing that
4662n/a something is wrong with the file, when it also
4663n/a could be the time stamp that gives a problem. */
4664n/a PyErr_SetFromWindowsErr(0);
4665n/a goto exit;
4666n/a }
4667n/a#else /* MS_WINDOWS */
4668n/a Py_BEGIN_ALLOW_THREADS
4669n/a
4670n/a#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
4671n/a if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4672n/a result = utime_nofollow_symlinks(&utime, path->narrow);
4673n/a else
4674n/a#endif
4675n/a
4676n/a#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
4677n/a if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))
4678n/a result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
4679n/a else
4680n/a#endif
4681n/a
4682n/a#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
4683n/a if (path->fd != -1)
4684n/a result = utime_fd(&utime, path->fd);
4685n/a else
4686n/a#endif
4687n/a
4688n/a result = utime_default(&utime, path->narrow);
4689n/a
4690n/a Py_END_ALLOW_THREADS
4691n/a
4692n/a if (result < 0) {
4693n/a /* see previous comment about not putting filename in error here */
4694n/a return_value = posix_error();
4695n/a goto exit;
4696n/a }
4697n/a
4698n/a#endif /* MS_WINDOWS */
4699n/a
4700n/a Py_INCREF(Py_None);
4701n/a return_value = Py_None;
4702n/a
4703n/aexit:
4704n/a#ifdef MS_WINDOWS
4705n/a if (hFile != INVALID_HANDLE_VALUE)
4706n/a CloseHandle(hFile);
4707n/a#endif
4708n/a return return_value;
4709n/a}
4710n/a
4711n/a/* Process operations */
4712n/a
4713n/a
4714n/a/*[clinic input]
4715n/aos._exit
4716n/a
4717n/a status: int
4718n/a
4719n/aExit to the system with specified status, without normal exit processing.
4720n/a[clinic start generated code]*/
4721n/a
4722n/astatic PyObject *
4723n/aos__exit_impl(PyObject *module, int status)
4724n/a/*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
4725n/a{
4726n/a _exit(status);
4727n/a return NULL; /* Make gcc -Wall happy */
4728n/a}
4729n/a
4730n/a#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
4731n/a#define EXECV_CHAR wchar_t
4732n/a#else
4733n/a#define EXECV_CHAR char
4734n/a#endif
4735n/a
4736n/a#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV)
4737n/astatic void
4738n/afree_string_array(EXECV_CHAR **array, Py_ssize_t count)
4739n/a{
4740n/a Py_ssize_t i;
4741n/a for (i = 0; i < count; i++)
4742n/a PyMem_Free(array[i]);
4743n/a PyMem_DEL(array);
4744n/a}
4745n/a
4746n/astatic int
4747n/afsconvert_strdup(PyObject *o, EXECV_CHAR **out)
4748n/a{
4749n/a Py_ssize_t size;
4750n/a PyObject *ub;
4751n/a int result = 0;
4752n/a#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
4753n/a if (!PyUnicode_FSDecoder(o, &ub))
4754n/a return 0;
4755n/a *out = PyUnicode_AsWideCharString(ub, &size);
4756n/a if (*out)
4757n/a result = 1;
4758n/a#else
4759n/a if (!PyUnicode_FSConverter(o, &ub))
4760n/a return 0;
4761n/a size = PyBytes_GET_SIZE(ub);
4762n/a *out = PyMem_Malloc(size + 1);
4763n/a if (*out) {
4764n/a memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
4765n/a result = 1;
4766n/a } else
4767n/a PyErr_NoMemory();
4768n/a#endif
4769n/a Py_DECREF(ub);
4770n/a return result;
4771n/a}
4772n/a#endif
4773n/a
4774n/a#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE)
4775n/astatic EXECV_CHAR**
4776n/aparse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
4777n/a{
4778n/a Py_ssize_t i, pos, envc;
4779n/a PyObject *keys=NULL, *vals=NULL;
4780n/a PyObject *key, *val, *key2, *val2, *keyval;
4781n/a EXECV_CHAR **envlist;
4782n/a
4783n/a i = PyMapping_Size(env);
4784n/a if (i < 0)
4785n/a return NULL;
4786n/a envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
4787n/a if (envlist == NULL) {
4788n/a PyErr_NoMemory();
4789n/a return NULL;
4790n/a }
4791n/a envc = 0;
4792n/a keys = PyMapping_Keys(env);
4793n/a if (!keys)
4794n/a goto error;
4795n/a vals = PyMapping_Values(env);
4796n/a if (!vals)
4797n/a goto error;
4798n/a if (!PyList_Check(keys) || !PyList_Check(vals)) {
4799n/a PyErr_Format(PyExc_TypeError,
4800n/a "env.keys() or env.values() is not a list");
4801n/a goto error;
4802n/a }
4803n/a
4804n/a for (pos = 0; pos < i; pos++) {
4805n/a key = PyList_GetItem(keys, pos);
4806n/a val = PyList_GetItem(vals, pos);
4807n/a if (!key || !val)
4808n/a goto error;
4809n/a
4810n/a#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
4811n/a if (!PyUnicode_FSDecoder(key, &key2))
4812n/a goto error;
4813n/a if (!PyUnicode_FSDecoder(val, &val2)) {
4814n/a Py_DECREF(key2);
4815n/a goto error;
4816n/a }
4817n/a keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
4818n/a#else
4819n/a if (!PyUnicode_FSConverter(key, &key2))
4820n/a goto error;
4821n/a if (!PyUnicode_FSConverter(val, &val2)) {
4822n/a Py_DECREF(key2);
4823n/a goto error;
4824n/a }
4825n/a keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
4826n/a PyBytes_AS_STRING(val2));
4827n/a#endif
4828n/a Py_DECREF(key2);
4829n/a Py_DECREF(val2);
4830n/a if (!keyval)
4831n/a goto error;
4832n/a
4833n/a if (!fsconvert_strdup(keyval, &envlist[envc++])) {
4834n/a Py_DECREF(keyval);
4835n/a goto error;
4836n/a }
4837n/a
4838n/a Py_DECREF(keyval);
4839n/a }
4840n/a Py_DECREF(vals);
4841n/a Py_DECREF(keys);
4842n/a
4843n/a envlist[envc] = 0;
4844n/a *envc_ptr = envc;
4845n/a return envlist;
4846n/a
4847n/aerror:
4848n/a Py_XDECREF(keys);
4849n/a Py_XDECREF(vals);
4850n/a free_string_array(envlist, envc);
4851n/a return NULL;
4852n/a}
4853n/a
4854n/astatic EXECV_CHAR**
4855n/aparse_arglist(PyObject* argv, Py_ssize_t *argc)
4856n/a{
4857n/a int i;
4858n/a EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
4859n/a if (argvlist == NULL) {
4860n/a PyErr_NoMemory();
4861n/a return NULL;
4862n/a }
4863n/a for (i = 0; i < *argc; i++) {
4864n/a PyObject* item = PySequence_ITEM(argv, i);
4865n/a if (item == NULL)
4866n/a goto fail;
4867n/a if (!fsconvert_strdup(item, &argvlist[i])) {
4868n/a Py_DECREF(item);
4869n/a goto fail;
4870n/a }
4871n/a Py_DECREF(item);
4872n/a }
4873n/a argvlist[*argc] = NULL;
4874n/a return argvlist;
4875n/afail:
4876n/a *argc = i;
4877n/a free_string_array(argvlist, *argc);
4878n/a return NULL;
4879n/a}
4880n/a
4881n/a#endif
4882n/a
4883n/a
4884n/a#ifdef HAVE_EXECV
4885n/a/*[clinic input]
4886n/aos.execv
4887n/a
4888n/a path: path_t
4889n/a Path of executable file.
4890n/a argv: object
4891n/a Tuple or list of strings.
4892n/a /
4893n/a
4894n/aExecute an executable path with arguments, replacing current process.
4895n/a[clinic start generated code]*/
4896n/a
4897n/astatic PyObject *
4898n/aos_execv_impl(PyObject *module, path_t *path, PyObject *argv)
4899n/a/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
4900n/a{
4901n/a EXECV_CHAR **argvlist;
4902n/a Py_ssize_t argc;
4903n/a
4904n/a /* execv has two arguments: (path, argv), where
4905n/a argv is a list or tuple of strings. */
4906n/a
4907n/a if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
4908n/a PyErr_SetString(PyExc_TypeError,
4909n/a "execv() arg 2 must be a tuple or list");
4910n/a return NULL;
4911n/a }
4912n/a argc = PySequence_Size(argv);
4913n/a if (argc < 1) {
4914n/a PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
4915n/a return NULL;
4916n/a }
4917n/a
4918n/a argvlist = parse_arglist(argv, &argc);
4919n/a if (argvlist == NULL) {
4920n/a return NULL;
4921n/a }
4922n/a if (!argvlist[0][0]) {
4923n/a PyErr_SetString(PyExc_ValueError,
4924n/a "execv() arg 2 first element cannot be empty");
4925n/a free_string_array(argvlist, argc);
4926n/a return NULL;
4927n/a }
4928n/a
4929n/a _Py_BEGIN_SUPPRESS_IPH
4930n/a#ifdef HAVE_WEXECV
4931n/a _wexecv(path->wide, argvlist);
4932n/a#else
4933n/a execv(path->narrow, argvlist);
4934n/a#endif
4935n/a _Py_END_SUPPRESS_IPH
4936n/a
4937n/a /* If we get here it's definitely an error */
4938n/a
4939n/a free_string_array(argvlist, argc);
4940n/a return posix_error();
4941n/a}
4942n/a
4943n/a
4944n/a/*[clinic input]
4945n/aos.execve
4946n/a
4947n/a path: path_t(allow_fd='PATH_HAVE_FEXECVE')
4948n/a Path of executable file.
4949n/a argv: object
4950n/a Tuple or list of strings.
4951n/a env: object
4952n/a Dictionary of strings mapping to strings.
4953n/a
4954n/aExecute an executable path with arguments, replacing current process.
4955n/a[clinic start generated code]*/
4956n/a
4957n/astatic PyObject *
4958n/aos_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
4959n/a/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
4960n/a{
4961n/a EXECV_CHAR **argvlist = NULL;
4962n/a EXECV_CHAR **envlist;
4963n/a Py_ssize_t argc, envc;
4964n/a
4965n/a /* execve has three arguments: (path, argv, env), where
4966n/a argv is a list or tuple of strings and env is a dictionary
4967n/a like posix.environ. */
4968n/a
4969n/a if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
4970n/a PyErr_SetString(PyExc_TypeError,
4971n/a "execve: argv must be a tuple or list");
4972n/a goto fail;
4973n/a }
4974n/a argc = PySequence_Size(argv);
4975n/a if (argc < 1) {
4976n/a PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
4977n/a return NULL;
4978n/a }
4979n/a
4980n/a if (!PyMapping_Check(env)) {
4981n/a PyErr_SetString(PyExc_TypeError,
4982n/a "execve: environment must be a mapping object");
4983n/a goto fail;
4984n/a }
4985n/a
4986n/a argvlist = parse_arglist(argv, &argc);
4987n/a if (argvlist == NULL) {
4988n/a goto fail;
4989n/a }
4990n/a if (!argvlist[0][0]) {
4991n/a PyErr_SetString(PyExc_ValueError,
4992n/a "execve: argv first element cannot be empty");
4993n/a goto fail;
4994n/a }
4995n/a
4996n/a envlist = parse_envlist(env, &envc);
4997n/a if (envlist == NULL)
4998n/a goto fail;
4999n/a
5000n/a _Py_BEGIN_SUPPRESS_IPH
5001n/a#ifdef HAVE_FEXECVE
5002n/a if (path->fd > -1)
5003n/a fexecve(path->fd, argvlist, envlist);
5004n/a else
5005n/a#endif
5006n/a#ifdef HAVE_WEXECV
5007n/a _wexecve(path->wide, argvlist, envlist);
5008n/a#else
5009n/a execve(path->narrow, argvlist, envlist);
5010n/a#endif
5011n/a _Py_END_SUPPRESS_IPH
5012n/a
5013n/a /* If we get here it's definitely an error */
5014n/a
5015n/a path_error(path);
5016n/a
5017n/a free_string_array(envlist, envc);
5018n/a fail:
5019n/a if (argvlist)
5020n/a free_string_array(argvlist, argc);
5021n/a return NULL;
5022n/a}
5023n/a
5024n/a#endif /* HAVE_EXECV */
5025n/a
5026n/a
5027n/a#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV)
5028n/a/*[clinic input]
5029n/aos.spawnv
5030n/a
5031n/a mode: int
5032n/a Mode of process creation.
5033n/a path: path_t
5034n/a Path of executable file.
5035n/a argv: object
5036n/a Tuple or list of strings.
5037n/a /
5038n/a
5039n/aExecute the program specified by path in a new process.
5040n/a[clinic start generated code]*/
5041n/a
5042n/astatic PyObject *
5043n/aos_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
5044n/a/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
5045n/a{
5046n/a EXECV_CHAR **argvlist;
5047n/a int i;
5048n/a Py_ssize_t argc;
5049n/a intptr_t spawnval;
5050n/a PyObject *(*getitem)(PyObject *, Py_ssize_t);
5051n/a
5052n/a /* spawnv has three arguments: (mode, path, argv), where
5053n/a argv is a list or tuple of strings. */
5054n/a
5055n/a if (PyList_Check(argv)) {
5056n/a argc = PyList_Size(argv);
5057n/a getitem = PyList_GetItem;
5058n/a }
5059n/a else if (PyTuple_Check(argv)) {
5060n/a argc = PyTuple_Size(argv);
5061n/a getitem = PyTuple_GetItem;
5062n/a }
5063n/a else {
5064n/a PyErr_SetString(PyExc_TypeError,
5065n/a "spawnv() arg 2 must be a tuple or list");
5066n/a return NULL;
5067n/a }
5068n/a if (argc == 0) {
5069n/a PyErr_SetString(PyExc_ValueError,
5070n/a "spawnv() arg 2 cannot be empty");
5071n/a return NULL;
5072n/a }
5073n/a
5074n/a argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
5075n/a if (argvlist == NULL) {
5076n/a return PyErr_NoMemory();
5077n/a }
5078n/a for (i = 0; i < argc; i++) {
5079n/a if (!fsconvert_strdup((*getitem)(argv, i),
5080n/a &argvlist[i])) {
5081n/a free_string_array(argvlist, i);
5082n/a PyErr_SetString(
5083n/a PyExc_TypeError,
5084n/a "spawnv() arg 2 must contain only strings");
5085n/a return NULL;
5086n/a }
5087n/a if (i == 0 && !argvlist[0][0]) {
5088n/a free_string_array(argvlist, i);
5089n/a PyErr_SetString(
5090n/a PyExc_ValueError,
5091n/a "spawnv() arg 2 first element cannot be empty");
5092n/a return NULL;
5093n/a }
5094n/a }
5095n/a argvlist[argc] = NULL;
5096n/a
5097n/a if (mode == _OLD_P_OVERLAY)
5098n/a mode = _P_OVERLAY;
5099n/a
5100n/a Py_BEGIN_ALLOW_THREADS
5101n/a _Py_BEGIN_SUPPRESS_IPH
5102n/a#ifdef HAVE_WSPAWNV
5103n/a spawnval = _wspawnv(mode, path->wide, argvlist);
5104n/a#else
5105n/a spawnval = _spawnv(mode, path->narrow, argvlist);
5106n/a#endif
5107n/a _Py_END_SUPPRESS_IPH
5108n/a Py_END_ALLOW_THREADS
5109n/a
5110n/a free_string_array(argvlist, argc);
5111n/a
5112n/a if (spawnval == -1)
5113n/a return posix_error();
5114n/a else
5115n/a return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
5116n/a}
5117n/a
5118n/a
5119n/a/*[clinic input]
5120n/aos.spawnve
5121n/a
5122n/a mode: int
5123n/a Mode of process creation.
5124n/a path: path_t
5125n/a Path of executable file.
5126n/a argv: object
5127n/a Tuple or list of strings.
5128n/a env: object
5129n/a Dictionary of strings mapping to strings.
5130n/a /
5131n/a
5132n/aExecute the program specified by path in a new process.
5133n/a[clinic start generated code]*/
5134n/a
5135n/astatic PyObject *
5136n/aos_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
5137n/a PyObject *env)
5138n/a/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
5139n/a{
5140n/a EXECV_CHAR **argvlist;
5141n/a EXECV_CHAR **envlist;
5142n/a PyObject *res = NULL;
5143n/a Py_ssize_t argc, i, envc;
5144n/a intptr_t spawnval;
5145n/a PyObject *(*getitem)(PyObject *, Py_ssize_t);
5146n/a Py_ssize_t lastarg = 0;
5147n/a
5148n/a /* spawnve has four arguments: (mode, path, argv, env), where
5149n/a argv is a list or tuple of strings and env is a dictionary
5150n/a like posix.environ. */
5151n/a
5152n/a if (PyList_Check(argv)) {
5153n/a argc = PyList_Size(argv);
5154n/a getitem = PyList_GetItem;
5155n/a }
5156n/a else if (PyTuple_Check(argv)) {
5157n/a argc = PyTuple_Size(argv);
5158n/a getitem = PyTuple_GetItem;
5159n/a }
5160n/a else {
5161n/a PyErr_SetString(PyExc_TypeError,
5162n/a "spawnve() arg 2 must be a tuple or list");
5163n/a goto fail_0;
5164n/a }
5165n/a if (argc == 0) {
5166n/a PyErr_SetString(PyExc_ValueError,
5167n/a "spawnve() arg 2 cannot be empty");
5168n/a goto fail_0;
5169n/a }
5170n/a if (!PyMapping_Check(env)) {
5171n/a PyErr_SetString(PyExc_TypeError,
5172n/a "spawnve() arg 3 must be a mapping object");
5173n/a goto fail_0;
5174n/a }
5175n/a
5176n/a argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
5177n/a if (argvlist == NULL) {
5178n/a PyErr_NoMemory();
5179n/a goto fail_0;
5180n/a }
5181n/a for (i = 0; i < argc; i++) {
5182n/a if (!fsconvert_strdup((*getitem)(argv, i),
5183n/a &argvlist[i]))
5184n/a {
5185n/a lastarg = i;
5186n/a goto fail_1;
5187n/a }
5188n/a if (i == 0 && !argvlist[0][0]) {
5189n/a lastarg = i;
5190n/a PyErr_SetString(
5191n/a PyExc_ValueError,
5192n/a "spawnv() arg 2 first element cannot be empty");
5193n/a goto fail_1;
5194n/a }
5195n/a }
5196n/a lastarg = argc;
5197n/a argvlist[argc] = NULL;
5198n/a
5199n/a envlist = parse_envlist(env, &envc);
5200n/a if (envlist == NULL)
5201n/a goto fail_1;
5202n/a
5203n/a if (mode == _OLD_P_OVERLAY)
5204n/a mode = _P_OVERLAY;
5205n/a
5206n/a Py_BEGIN_ALLOW_THREADS
5207n/a _Py_BEGIN_SUPPRESS_IPH
5208n/a#ifdef HAVE_WSPAWNV
5209n/a spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
5210n/a#else
5211n/a spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
5212n/a#endif
5213n/a _Py_END_SUPPRESS_IPH
5214n/a Py_END_ALLOW_THREADS
5215n/a
5216n/a if (spawnval == -1)
5217n/a (void) posix_error();
5218n/a else
5219n/a res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
5220n/a
5221n/a while (--envc >= 0)
5222n/a PyMem_DEL(envlist[envc]);
5223n/a PyMem_DEL(envlist);
5224n/a fail_1:
5225n/a free_string_array(argvlist, lastarg);
5226n/a fail_0:
5227n/a return res;
5228n/a}
5229n/a
5230n/a#endif /* HAVE_SPAWNV */
5231n/a
5232n/a
5233n/a#ifdef HAVE_FORK1
5234n/a/*[clinic input]
5235n/aos.fork1
5236n/a
5237n/aFork a child process with a single multiplexed (i.e., not bound) thread.
5238n/a
5239n/aReturn 0 to child process and PID of child to parent process.
5240n/a[clinic start generated code]*/
5241n/a
5242n/astatic PyObject *
5243n/aos_fork1_impl(PyObject *module)
5244n/a/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
5245n/a{
5246n/a pid_t pid;
5247n/a int result = 0;
5248n/a _PyImport_AcquireLock();
5249n/a pid = fork1();
5250n/a if (pid == 0) {
5251n/a /* child: this clobbers and resets the import lock. */
5252n/a PyOS_AfterFork();
5253n/a } else {
5254n/a /* parent: release the import lock. */
5255n/a result = _PyImport_ReleaseLock();
5256n/a }
5257n/a if (pid == -1)
5258n/a return posix_error();
5259n/a if (result < 0) {
5260n/a /* Don't clobber the OSError if the fork failed. */
5261n/a PyErr_SetString(PyExc_RuntimeError,
5262n/a "not holding the import lock");
5263n/a return NULL;
5264n/a }
5265n/a return PyLong_FromPid(pid);
5266n/a}
5267n/a#endif /* HAVE_FORK1 */
5268n/a
5269n/a
5270n/a#ifdef HAVE_FORK
5271n/a/*[clinic input]
5272n/aos.fork
5273n/a
5274n/aFork a child process.
5275n/a
5276n/aReturn 0 to child process and PID of child to parent process.
5277n/a[clinic start generated code]*/
5278n/a
5279n/astatic PyObject *
5280n/aos_fork_impl(PyObject *module)
5281n/a/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
5282n/a{
5283n/a pid_t pid;
5284n/a int result = 0;
5285n/a _PyImport_AcquireLock();
5286n/a pid = fork();
5287n/a if (pid == 0) {
5288n/a /* child: this clobbers and resets the import lock. */
5289n/a PyOS_AfterFork();
5290n/a } else {
5291n/a /* parent: release the import lock. */
5292n/a result = _PyImport_ReleaseLock();
5293n/a }
5294n/a if (pid == -1)
5295n/a return posix_error();
5296n/a if (result < 0) {
5297n/a /* Don't clobber the OSError if the fork failed. */
5298n/a PyErr_SetString(PyExc_RuntimeError,
5299n/a "not holding the import lock");
5300n/a return NULL;
5301n/a }
5302n/a return PyLong_FromPid(pid);
5303n/a}
5304n/a#endif /* HAVE_FORK */
5305n/a
5306n/a
5307n/a#ifdef HAVE_SCHED_H
5308n/a#ifdef HAVE_SCHED_GET_PRIORITY_MAX
5309n/a/*[clinic input]
5310n/aos.sched_get_priority_max
5311n/a
5312n/a policy: int
5313n/a
5314n/aGet the maximum scheduling priority for policy.
5315n/a[clinic start generated code]*/
5316n/a
5317n/astatic PyObject *
5318n/aos_sched_get_priority_max_impl(PyObject *module, int policy)
5319n/a/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
5320n/a{
5321n/a int max;
5322n/a
5323n/a max = sched_get_priority_max(policy);
5324n/a if (max < 0)
5325n/a return posix_error();
5326n/a return PyLong_FromLong(max);
5327n/a}
5328n/a
5329n/a
5330n/a/*[clinic input]
5331n/aos.sched_get_priority_min
5332n/a
5333n/a policy: int
5334n/a
5335n/aGet the minimum scheduling priority for policy.
5336n/a[clinic start generated code]*/
5337n/a
5338n/astatic PyObject *
5339n/aos_sched_get_priority_min_impl(PyObject *module, int policy)
5340n/a/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
5341n/a{
5342n/a int min = sched_get_priority_min(policy);
5343n/a if (min < 0)
5344n/a return posix_error();
5345n/a return PyLong_FromLong(min);
5346n/a}
5347n/a#endif /* HAVE_SCHED_GET_PRIORITY_MAX */
5348n/a
5349n/a
5350n/a#ifdef HAVE_SCHED_SETSCHEDULER
5351n/a/*[clinic input]
5352n/aos.sched_getscheduler
5353n/a pid: pid_t
5354n/a /
5355n/a
5356n/aGet the scheduling policy for the process identifiedy by pid.
5357n/a
5358n/aPassing 0 for pid returns the scheduling policy for the calling process.
5359n/a[clinic start generated code]*/
5360n/a
5361n/astatic PyObject *
5362n/aos_sched_getscheduler_impl(PyObject *module, pid_t pid)
5363n/a/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=5f14cfd1f189e1a0]*/
5364n/a{
5365n/a int policy;
5366n/a
5367n/a policy = sched_getscheduler(pid);
5368n/a if (policy < 0)
5369n/a return posix_error();
5370n/a return PyLong_FromLong(policy);
5371n/a}
5372n/a#endif /* HAVE_SCHED_SETSCHEDULER */
5373n/a
5374n/a
5375n/a#if defined(HAVE_SCHED_SETSCHEDULER) || defined(HAVE_SCHED_SETPARAM)
5376n/a/*[clinic input]
5377n/aclass os.sched_param "PyObject *" "&SchedParamType"
5378n/a
5379n/a@classmethod
5380n/aos.sched_param.__new__
5381n/a
5382n/a sched_priority: object
5383n/a A scheduling parameter.
5384n/a
5385n/aCurrent has only one field: sched_priority");
5386n/a[clinic start generated code]*/
5387n/a
5388n/astatic PyObject *
5389n/aos_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
5390n/a/*[clinic end generated code: output=48f4067d60f48c13 input=73a4c22f7071fc62]*/
5391n/a{
5392n/a PyObject *res;
5393n/a
5394n/a res = PyStructSequence_New(type);
5395n/a if (!res)
5396n/a return NULL;
5397n/a Py_INCREF(sched_priority);
5398n/a PyStructSequence_SET_ITEM(res, 0, sched_priority);
5399n/a return res;
5400n/a}
5401n/a
5402n/a
5403n/aPyDoc_VAR(os_sched_param__doc__);
5404n/a
5405n/astatic PyStructSequence_Field sched_param_fields[] = {
5406n/a {"sched_priority", "the scheduling priority"},
5407n/a {0}
5408n/a};
5409n/a
5410n/astatic PyStructSequence_Desc sched_param_desc = {
5411n/a "sched_param", /* name */
5412n/a os_sched_param__doc__, /* doc */
5413n/a sched_param_fields,
5414n/a 1
5415n/a};
5416n/a
5417n/astatic int
5418n/aconvert_sched_param(PyObject *param, struct sched_param *res)
5419n/a{
5420n/a long priority;
5421n/a
5422n/a if (Py_TYPE(param) != &SchedParamType) {
5423n/a PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
5424n/a return 0;
5425n/a }
5426n/a priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
5427n/a if (priority == -1 && PyErr_Occurred())
5428n/a return 0;
5429n/a if (priority > INT_MAX || priority < INT_MIN) {
5430n/a PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
5431n/a return 0;
5432n/a }
5433n/a res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
5434n/a return 1;
5435n/a}
5436n/a#endif /* defined(HAVE_SCHED_SETSCHEDULER) || defined(HAVE_SCHED_SETPARAM) */
5437n/a
5438n/a
5439n/a#ifdef HAVE_SCHED_SETSCHEDULER
5440n/a/*[clinic input]
5441n/aos.sched_setscheduler
5442n/a
5443n/a pid: pid_t
5444n/a policy: int
5445n/a param: sched_param
5446n/a /
5447n/a
5448n/aSet the scheduling policy for the process identified by pid.
5449n/a
5450n/aIf pid is 0, the calling process is changed.
5451n/aparam is an instance of sched_param.
5452n/a[clinic start generated code]*/
5453n/a
5454n/astatic PyObject *
5455n/aos_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
5456n/a struct sched_param *param)
5457n/a/*[clinic end generated code: output=b0ac0a70d3b1d705 input=c581f9469a5327dd]*/
5458n/a{
5459n/a /*
5460n/a ** sched_setscheduler() returns 0 in Linux, but the previous
5461n/a ** scheduling policy under Solaris/Illumos, and others.
5462n/a ** On error, -1 is returned in all Operating Systems.
5463n/a */
5464n/a if (sched_setscheduler(pid, policy, param) == -1)
5465n/a return posix_error();
5466n/a Py_RETURN_NONE;
5467n/a}
5468n/a#endif /* HAVE_SCHED_SETSCHEDULER*/
5469n/a
5470n/a
5471n/a#ifdef HAVE_SCHED_SETPARAM
5472n/a/*[clinic input]
5473n/aos.sched_getparam
5474n/a pid: pid_t
5475n/a /
5476n/a
5477n/aReturns scheduling parameters for the process identified by pid.
5478n/a
5479n/aIf pid is 0, returns parameters for the calling process.
5480n/aReturn value is an instance of sched_param.
5481n/a[clinic start generated code]*/
5482n/a
5483n/astatic PyObject *
5484n/aos_sched_getparam_impl(PyObject *module, pid_t pid)
5485n/a/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
5486n/a{
5487n/a struct sched_param param;
5488n/a PyObject *result;
5489n/a PyObject *priority;
5490n/a
5491n/a if (sched_getparam(pid, &param))
5492n/a return posix_error();
5493n/a result = PyStructSequence_New(&SchedParamType);
5494n/a if (!result)
5495n/a return NULL;
5496n/a priority = PyLong_FromLong(param.sched_priority);
5497n/a if (!priority) {
5498n/a Py_DECREF(result);
5499n/a return NULL;
5500n/a }
5501n/a PyStructSequence_SET_ITEM(result, 0, priority);
5502n/a return result;
5503n/a}
5504n/a
5505n/a
5506n/a/*[clinic input]
5507n/aos.sched_setparam
5508n/a pid: pid_t
5509n/a param: sched_param
5510n/a /
5511n/a
5512n/aSet scheduling parameters for the process identified by pid.
5513n/a
5514n/aIf pid is 0, sets parameters for the calling process.
5515n/aparam should be an instance of sched_param.
5516n/a[clinic start generated code]*/
5517n/a
5518n/astatic PyObject *
5519n/aos_sched_setparam_impl(PyObject *module, pid_t pid,
5520n/a struct sched_param *param)
5521n/a/*[clinic end generated code: output=8af013f78a32b591 input=6b8d6dfcecdc21bd]*/
5522n/a{
5523n/a if (sched_setparam(pid, param))
5524n/a return posix_error();
5525n/a Py_RETURN_NONE;
5526n/a}
5527n/a#endif /* HAVE_SCHED_SETPARAM */
5528n/a
5529n/a
5530n/a#ifdef HAVE_SCHED_RR_GET_INTERVAL
5531n/a/*[clinic input]
5532n/aos.sched_rr_get_interval -> double
5533n/a pid: pid_t
5534n/a /
5535n/a
5536n/aReturn the round-robin quantum for the process identified by pid, in seconds.
5537n/a
5538n/aValue returned is a float.
5539n/a[clinic start generated code]*/
5540n/a
5541n/astatic double
5542n/aos_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
5543n/a/*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
5544n/a{
5545n/a struct timespec interval;
5546n/a if (sched_rr_get_interval(pid, &interval)) {
5547n/a posix_error();
5548n/a return -1.0;
5549n/a }
5550n/a return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
5551n/a}
5552n/a#endif /* HAVE_SCHED_RR_GET_INTERVAL */
5553n/a
5554n/a
5555n/a/*[clinic input]
5556n/aos.sched_yield
5557n/a
5558n/aVoluntarily relinquish the CPU.
5559n/a[clinic start generated code]*/
5560n/a
5561n/astatic PyObject *
5562n/aos_sched_yield_impl(PyObject *module)
5563n/a/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
5564n/a{
5565n/a if (sched_yield())
5566n/a return posix_error();
5567n/a Py_RETURN_NONE;
5568n/a}
5569n/a
5570n/a#ifdef HAVE_SCHED_SETAFFINITY
5571n/a/* The minimum number of CPUs allocated in a cpu_set_t */
5572n/astatic const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
5573n/a
5574n/a/*[clinic input]
5575n/aos.sched_setaffinity
5576n/a pid: pid_t
5577n/a mask : object
5578n/a /
5579n/a
5580n/aSet the CPU affinity of the process identified by pid to mask.
5581n/a
5582n/amask should be an iterable of integers identifying CPUs.
5583n/a[clinic start generated code]*/
5584n/a
5585n/astatic PyObject *
5586n/aos_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
5587n/a/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
5588n/a{
5589n/a int ncpus;
5590n/a size_t setsize;
5591n/a cpu_set_t *cpu_set = NULL;
5592n/a PyObject *iterator = NULL, *item;
5593n/a
5594n/a iterator = PyObject_GetIter(mask);
5595n/a if (iterator == NULL)
5596n/a return NULL;
5597n/a
5598n/a ncpus = NCPUS_START;
5599n/a setsize = CPU_ALLOC_SIZE(ncpus);
5600n/a cpu_set = CPU_ALLOC(ncpus);
5601n/a if (cpu_set == NULL) {
5602n/a PyErr_NoMemory();
5603n/a goto error;
5604n/a }
5605n/a CPU_ZERO_S(setsize, cpu_set);
5606n/a
5607n/a while ((item = PyIter_Next(iterator))) {
5608n/a long cpu;
5609n/a if (!PyLong_Check(item)) {
5610n/a PyErr_Format(PyExc_TypeError,
5611n/a "expected an iterator of ints, "
5612n/a "but iterator yielded %R",
5613n/a Py_TYPE(item));
5614n/a Py_DECREF(item);
5615n/a goto error;
5616n/a }
5617n/a cpu = PyLong_AsLong(item);
5618n/a Py_DECREF(item);
5619n/a if (cpu < 0) {
5620n/a if (!PyErr_Occurred())
5621n/a PyErr_SetString(PyExc_ValueError, "negative CPU number");
5622n/a goto error;
5623n/a }
5624n/a if (cpu > INT_MAX - 1) {
5625n/a PyErr_SetString(PyExc_OverflowError, "CPU number too large");
5626n/a goto error;
5627n/a }
5628n/a if (cpu >= ncpus) {
5629n/a /* Grow CPU mask to fit the CPU number */
5630n/a int newncpus = ncpus;
5631n/a cpu_set_t *newmask;
5632n/a size_t newsetsize;
5633n/a while (newncpus <= cpu) {
5634n/a if (newncpus > INT_MAX / 2)
5635n/a newncpus = cpu + 1;
5636n/a else
5637n/a newncpus = newncpus * 2;
5638n/a }
5639n/a newmask = CPU_ALLOC(newncpus);
5640n/a if (newmask == NULL) {
5641n/a PyErr_NoMemory();
5642n/a goto error;
5643n/a }
5644n/a newsetsize = CPU_ALLOC_SIZE(newncpus);
5645n/a CPU_ZERO_S(newsetsize, newmask);
5646n/a memcpy(newmask, cpu_set, setsize);
5647n/a CPU_FREE(cpu_set);
5648n/a setsize = newsetsize;
5649n/a cpu_set = newmask;
5650n/a ncpus = newncpus;
5651n/a }
5652n/a CPU_SET_S(cpu, setsize, cpu_set);
5653n/a }
5654n/a Py_CLEAR(iterator);
5655n/a
5656n/a if (sched_setaffinity(pid, setsize, cpu_set)) {
5657n/a posix_error();
5658n/a goto error;
5659n/a }
5660n/a CPU_FREE(cpu_set);
5661n/a Py_RETURN_NONE;
5662n/a
5663n/aerror:
5664n/a if (cpu_set)
5665n/a CPU_FREE(cpu_set);
5666n/a Py_XDECREF(iterator);
5667n/a return NULL;
5668n/a}
5669n/a
5670n/a
5671n/a/*[clinic input]
5672n/aos.sched_getaffinity
5673n/a pid: pid_t
5674n/a /
5675n/a
5676n/aReturn the affinity of the process identified by pid (or the current process if zero).
5677n/a
5678n/aThe affinity is returned as a set of CPU identifiers.
5679n/a[clinic start generated code]*/
5680n/a
5681n/astatic PyObject *
5682n/aos_sched_getaffinity_impl(PyObject *module, pid_t pid)
5683n/a/*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
5684n/a{
5685n/a int cpu, ncpus, count;
5686n/a size_t setsize;
5687n/a cpu_set_t *mask = NULL;
5688n/a PyObject *res = NULL;
5689n/a
5690n/a ncpus = NCPUS_START;
5691n/a while (1) {
5692n/a setsize = CPU_ALLOC_SIZE(ncpus);
5693n/a mask = CPU_ALLOC(ncpus);
5694n/a if (mask == NULL)
5695n/a return PyErr_NoMemory();
5696n/a if (sched_getaffinity(pid, setsize, mask) == 0)
5697n/a break;
5698n/a CPU_FREE(mask);
5699n/a if (errno != EINVAL)
5700n/a return posix_error();
5701n/a if (ncpus > INT_MAX / 2) {
5702n/a PyErr_SetString(PyExc_OverflowError, "could not allocate "
5703n/a "a large enough CPU set");
5704n/a return NULL;
5705n/a }
5706n/a ncpus = ncpus * 2;
5707n/a }
5708n/a
5709n/a res = PySet_New(NULL);
5710n/a if (res == NULL)
5711n/a goto error;
5712n/a for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
5713n/a if (CPU_ISSET_S(cpu, setsize, mask)) {
5714n/a PyObject *cpu_num = PyLong_FromLong(cpu);
5715n/a --count;
5716n/a if (cpu_num == NULL)
5717n/a goto error;
5718n/a if (PySet_Add(res, cpu_num)) {
5719n/a Py_DECREF(cpu_num);
5720n/a goto error;
5721n/a }
5722n/a Py_DECREF(cpu_num);
5723n/a }
5724n/a }
5725n/a CPU_FREE(mask);
5726n/a return res;
5727n/a
5728n/aerror:
5729n/a if (mask)
5730n/a CPU_FREE(mask);
5731n/a Py_XDECREF(res);
5732n/a return NULL;
5733n/a}
5734n/a
5735n/a#endif /* HAVE_SCHED_SETAFFINITY */
5736n/a
5737n/a#endif /* HAVE_SCHED_H */
5738n/a
5739n/a
5740n/a/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
5741n/a/* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
5742n/a#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
5743n/a#define DEV_PTY_FILE "/dev/ptc"
5744n/a#define HAVE_DEV_PTMX
5745n/a#else
5746n/a#define DEV_PTY_FILE "/dev/ptmx"
5747n/a#endif
5748n/a
5749n/a#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
5750n/a#ifdef HAVE_PTY_H
5751n/a#include <pty.h>
5752n/a#else
5753n/a#ifdef HAVE_LIBUTIL_H
5754n/a#include <libutil.h>
5755n/a#else
5756n/a#ifdef HAVE_UTIL_H
5757n/a#include <util.h>
5758n/a#endif /* HAVE_UTIL_H */
5759n/a#endif /* HAVE_LIBUTIL_H */
5760n/a#endif /* HAVE_PTY_H */
5761n/a#ifdef HAVE_STROPTS_H
5762n/a#include <stropts.h>
5763n/a#endif
5764n/a#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */
5765n/a
5766n/a
5767n/a#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
5768n/a/*[clinic input]
5769n/aos.openpty
5770n/a
5771n/aOpen a pseudo-terminal.
5772n/a
5773n/aReturn a tuple of (master_fd, slave_fd) containing open file descriptors
5774n/afor both the master and slave ends.
5775n/a[clinic start generated code]*/
5776n/a
5777n/astatic PyObject *
5778n/aos_openpty_impl(PyObject *module)
5779n/a/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
5780n/a{
5781n/a int master_fd = -1, slave_fd = -1;
5782n/a#ifndef HAVE_OPENPTY
5783n/a char * slave_name;
5784n/a#endif
5785n/a#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
5786n/a PyOS_sighandler_t sig_saved;
5787n/a#ifdef sun
5788n/a extern char *ptsname(int fildes);
5789n/a#endif
5790n/a#endif
5791n/a
5792n/a#ifdef HAVE_OPENPTY
5793n/a if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
5794n/a goto posix_error;
5795n/a
5796n/a if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
5797n/a goto error;
5798n/a if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
5799n/a goto error;
5800n/a
5801n/a#elif defined(HAVE__GETPTY)
5802n/a slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
5803n/a if (slave_name == NULL)
5804n/a goto posix_error;
5805n/a if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
5806n/a goto error;
5807n/a
5808n/a slave_fd = _Py_open(slave_name, O_RDWR);
5809n/a if (slave_fd < 0)
5810n/a goto error;
5811n/a
5812n/a#else
5813n/a master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
5814n/a if (master_fd < 0)
5815n/a goto posix_error;
5816n/a
5817n/a sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
5818n/a
5819n/a /* change permission of slave */
5820n/a if (grantpt(master_fd) < 0) {
5821n/a PyOS_setsig(SIGCHLD, sig_saved);
5822n/a goto posix_error;
5823n/a }
5824n/a
5825n/a /* unlock slave */
5826n/a if (unlockpt(master_fd) < 0) {
5827n/a PyOS_setsig(SIGCHLD, sig_saved);
5828n/a goto posix_error;
5829n/a }
5830n/a
5831n/a PyOS_setsig(SIGCHLD, sig_saved);
5832n/a
5833n/a slave_name = ptsname(master_fd); /* get name of slave */
5834n/a if (slave_name == NULL)
5835n/a goto posix_error;
5836n/a
5837n/a slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
5838n/a if (slave_fd == -1)
5839n/a goto error;
5840n/a
5841n/a if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
5842n/a goto posix_error;
5843n/a
5844n/a#if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
5845n/a ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
5846n/a ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
5847n/a#ifndef __hpux
5848n/a ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
5849n/a#endif /* __hpux */
5850n/a#endif /* HAVE_CYGWIN */
5851n/a#endif /* HAVE_OPENPTY */
5852n/a
5853n/a return Py_BuildValue("(ii)", master_fd, slave_fd);
5854n/a
5855n/aposix_error:
5856n/a posix_error();
5857n/aerror:
5858n/a if (master_fd != -1)
5859n/a close(master_fd);
5860n/a if (slave_fd != -1)
5861n/a close(slave_fd);
5862n/a return NULL;
5863n/a}
5864n/a#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
5865n/a
5866n/a
5867n/a#ifdef HAVE_FORKPTY
5868n/a/*[clinic input]
5869n/aos.forkpty
5870n/a
5871n/aFork a new process with a new pseudo-terminal as controlling tty.
5872n/a
5873n/aReturns a tuple of (pid, master_fd).
5874n/aLike fork(), return pid of 0 to the child process,
5875n/aand pid of child to the parent process.
5876n/aTo both, return fd of newly opened pseudo-terminal.
5877n/a[clinic start generated code]*/
5878n/a
5879n/astatic PyObject *
5880n/aos_forkpty_impl(PyObject *module)
5881n/a/*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
5882n/a{
5883n/a int master_fd = -1, result = 0;
5884n/a pid_t pid;
5885n/a
5886n/a _PyImport_AcquireLock();
5887n/a pid = forkpty(&master_fd, NULL, NULL, NULL);
5888n/a if (pid == 0) {
5889n/a /* child: this clobbers and resets the import lock. */
5890n/a PyOS_AfterFork();
5891n/a } else {
5892n/a /* parent: release the import lock. */
5893n/a result = _PyImport_ReleaseLock();
5894n/a }
5895n/a if (pid == -1)
5896n/a return posix_error();
5897n/a if (result < 0) {
5898n/a /* Don't clobber the OSError if the fork failed. */
5899n/a PyErr_SetString(PyExc_RuntimeError,
5900n/a "not holding the import lock");
5901n/a return NULL;
5902n/a }
5903n/a return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
5904n/a}
5905n/a#endif /* HAVE_FORKPTY */
5906n/a
5907n/a
5908n/a#ifdef HAVE_GETEGID
5909n/a/*[clinic input]
5910n/aos.getegid
5911n/a
5912n/aReturn the current process's effective group id.
5913n/a[clinic start generated code]*/
5914n/a
5915n/astatic PyObject *
5916n/aos_getegid_impl(PyObject *module)
5917n/a/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
5918n/a{
5919n/a return _PyLong_FromGid(getegid());
5920n/a}
5921n/a#endif /* HAVE_GETEGID */
5922n/a
5923n/a
5924n/a#ifdef HAVE_GETEUID
5925n/a/*[clinic input]
5926n/aos.geteuid
5927n/a
5928n/aReturn the current process's effective user id.
5929n/a[clinic start generated code]*/
5930n/a
5931n/astatic PyObject *
5932n/aos_geteuid_impl(PyObject *module)
5933n/a/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
5934n/a{
5935n/a return _PyLong_FromUid(geteuid());
5936n/a}
5937n/a#endif /* HAVE_GETEUID */
5938n/a
5939n/a
5940n/a#ifdef HAVE_GETGID
5941n/a/*[clinic input]
5942n/aos.getgid
5943n/a
5944n/aReturn the current process's group id.
5945n/a[clinic start generated code]*/
5946n/a
5947n/astatic PyObject *
5948n/aos_getgid_impl(PyObject *module)
5949n/a/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
5950n/a{
5951n/a return _PyLong_FromGid(getgid());
5952n/a}
5953n/a#endif /* HAVE_GETGID */
5954n/a
5955n/a
5956n/a#ifdef HAVE_GETPID
5957n/a/*[clinic input]
5958n/aos.getpid
5959n/a
5960n/aReturn the current process id.
5961n/a[clinic start generated code]*/
5962n/a
5963n/astatic PyObject *
5964n/aos_getpid_impl(PyObject *module)
5965n/a/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
5966n/a{
5967n/a return PyLong_FromPid(getpid());
5968n/a}
5969n/a#endif /* HAVE_GETPID */
5970n/a
5971n/a#ifdef HAVE_GETGROUPLIST
5972n/a
5973n/a/* AC 3.5: funny apple logic below */
5974n/aPyDoc_STRVAR(posix_getgrouplist__doc__,
5975n/a"getgrouplist(user, group) -> list of groups to which a user belongs\n\n\
5976n/aReturns a list of groups to which a user belongs.\n\n\
5977n/a user: username to lookup\n\
5978n/a group: base group id of the user");
5979n/a
5980n/astatic PyObject *
5981n/aposix_getgrouplist(PyObject *self, PyObject *args)
5982n/a{
5983n/a#ifdef NGROUPS_MAX
5984n/a#define MAX_GROUPS NGROUPS_MAX
5985n/a#else
5986n/a /* defined to be 16 on Solaris7, so this should be a small number */
5987n/a#define MAX_GROUPS 64
5988n/a#endif
5989n/a
5990n/a const char *user;
5991n/a int i, ngroups;
5992n/a PyObject *list;
5993n/a#ifdef __APPLE__
5994n/a int *groups, basegid;
5995n/a#else
5996n/a gid_t *groups, basegid;
5997n/a#endif
5998n/a ngroups = MAX_GROUPS;
5999n/a
6000n/a#ifdef __APPLE__
6001n/a if (!PyArg_ParseTuple(args, "si:getgrouplist", &user, &basegid))
6002n/a return NULL;
6003n/a#else
6004n/a if (!PyArg_ParseTuple(args, "sO&:getgrouplist", &user,
6005n/a _Py_Gid_Converter, &basegid))
6006n/a return NULL;
6007n/a#endif
6008n/a
6009n/a#ifdef __APPLE__
6010n/a groups = PyMem_New(int, ngroups);
6011n/a#else
6012n/a groups = PyMem_New(gid_t, ngroups);
6013n/a#endif
6014n/a if (groups == NULL)
6015n/a return PyErr_NoMemory();
6016n/a
6017n/a if (getgrouplist(user, basegid, groups, &ngroups) == -1) {
6018n/a PyMem_Del(groups);
6019n/a return posix_error();
6020n/a }
6021n/a
6022n/a list = PyList_New(ngroups);
6023n/a if (list == NULL) {
6024n/a PyMem_Del(groups);
6025n/a return NULL;
6026n/a }
6027n/a
6028n/a for (i = 0; i < ngroups; i++) {
6029n/a#ifdef __APPLE__
6030n/a PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
6031n/a#else
6032n/a PyObject *o = _PyLong_FromGid(groups[i]);
6033n/a#endif
6034n/a if (o == NULL) {
6035n/a Py_DECREF(list);
6036n/a PyMem_Del(groups);
6037n/a return NULL;
6038n/a }
6039n/a PyList_SET_ITEM(list, i, o);
6040n/a }
6041n/a
6042n/a PyMem_Del(groups);
6043n/a
6044n/a return list;
6045n/a}
6046n/a#endif /* HAVE_GETGROUPLIST */
6047n/a
6048n/a
6049n/a#ifdef HAVE_GETGROUPS
6050n/a/*[clinic input]
6051n/aos.getgroups
6052n/a
6053n/aReturn list of supplemental group IDs for the process.
6054n/a[clinic start generated code]*/
6055n/a
6056n/astatic PyObject *
6057n/aos_getgroups_impl(PyObject *module)
6058n/a/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
6059n/a{
6060n/a PyObject *result = NULL;
6061n/a
6062n/a#ifdef NGROUPS_MAX
6063n/a#define MAX_GROUPS NGROUPS_MAX
6064n/a#else
6065n/a /* defined to be 16 on Solaris7, so this should be a small number */
6066n/a#define MAX_GROUPS 64
6067n/a#endif
6068n/a gid_t grouplist[MAX_GROUPS];
6069n/a
6070n/a /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
6071n/a * This is a helper variable to store the intermediate result when
6072n/a * that happens.
6073n/a *
6074n/a * To keep the code readable the OSX behaviour is unconditional,
6075n/a * according to the POSIX spec this should be safe on all unix-y
6076n/a * systems.
6077n/a */
6078n/a gid_t* alt_grouplist = grouplist;
6079n/a int n;
6080n/a
6081n/a#ifdef __APPLE__
6082n/a /* Issue #17557: As of OS X 10.8, getgroups(2) no longer raises EINVAL if
6083n/a * there are more groups than can fit in grouplist. Therefore, on OS X
6084n/a * always first call getgroups with length 0 to get the actual number
6085n/a * of groups.
6086n/a */
6087n/a n = getgroups(0, NULL);
6088n/a if (n < 0) {
6089n/a return posix_error();
6090n/a } else if (n <= MAX_GROUPS) {
6091n/a /* groups will fit in existing array */
6092n/a alt_grouplist = grouplist;
6093n/a } else {
6094n/a alt_grouplist = PyMem_New(gid_t, n);
6095n/a if (alt_grouplist == NULL) {
6096n/a errno = EINVAL;
6097n/a return posix_error();
6098n/a }
6099n/a }
6100n/a
6101n/a n = getgroups(n, alt_grouplist);
6102n/a if (n == -1) {
6103n/a if (alt_grouplist != grouplist) {
6104n/a PyMem_Free(alt_grouplist);
6105n/a }
6106n/a return posix_error();
6107n/a }
6108n/a#else
6109n/a n = getgroups(MAX_GROUPS, grouplist);
6110n/a if (n < 0) {
6111n/a if (errno == EINVAL) {
6112n/a n = getgroups(0, NULL);
6113n/a if (n == -1) {
6114n/a return posix_error();
6115n/a }
6116n/a if (n == 0) {
6117n/a /* Avoid malloc(0) */
6118n/a alt_grouplist = grouplist;
6119n/a } else {
6120n/a alt_grouplist = PyMem_New(gid_t, n);
6121n/a if (alt_grouplist == NULL) {
6122n/a errno = EINVAL;
6123n/a return posix_error();
6124n/a }
6125n/a n = getgroups(n, alt_grouplist);
6126n/a if (n == -1) {
6127n/a PyMem_Free(alt_grouplist);
6128n/a return posix_error();
6129n/a }
6130n/a }
6131n/a } else {
6132n/a return posix_error();
6133n/a }
6134n/a }
6135n/a#endif
6136n/a
6137n/a result = PyList_New(n);
6138n/a if (result != NULL) {
6139n/a int i;
6140n/a for (i = 0; i < n; ++i) {
6141n/a PyObject *o = _PyLong_FromGid(alt_grouplist[i]);
6142n/a if (o == NULL) {
6143n/a Py_DECREF(result);
6144n/a result = NULL;
6145n/a break;
6146n/a }
6147n/a PyList_SET_ITEM(result, i, o);
6148n/a }
6149n/a }
6150n/a
6151n/a if (alt_grouplist != grouplist) {
6152n/a PyMem_Free(alt_grouplist);
6153n/a }
6154n/a
6155n/a return result;
6156n/a}
6157n/a#endif /* HAVE_GETGROUPS */
6158n/a
6159n/a#ifdef HAVE_INITGROUPS
6160n/aPyDoc_STRVAR(posix_initgroups__doc__,
6161n/a"initgroups(username, gid) -> None\n\n\
6162n/aCall the system initgroups() to initialize the group access list with all of\n\
6163n/athe groups of which the specified username is a member, plus the specified\n\
6164n/agroup id.");
6165n/a
6166n/a/* AC 3.5: funny apple logic */
6167n/astatic PyObject *
6168n/aposix_initgroups(PyObject *self, PyObject *args)
6169n/a{
6170n/a PyObject *oname;
6171n/a const char *username;
6172n/a int res;
6173n/a#ifdef __APPLE__
6174n/a int gid;
6175n/a#else
6176n/a gid_t gid;
6177n/a#endif
6178n/a
6179n/a#ifdef __APPLE__
6180n/a if (!PyArg_ParseTuple(args, "O&i:initgroups",
6181n/a PyUnicode_FSConverter, &oname,
6182n/a &gid))
6183n/a#else
6184n/a if (!PyArg_ParseTuple(args, "O&O&:initgroups",
6185n/a PyUnicode_FSConverter, &oname,
6186n/a _Py_Gid_Converter, &gid))
6187n/a#endif
6188n/a return NULL;
6189n/a username = PyBytes_AS_STRING(oname);
6190n/a
6191n/a res = initgroups(username, gid);
6192n/a Py_DECREF(oname);
6193n/a if (res == -1)
6194n/a return PyErr_SetFromErrno(PyExc_OSError);
6195n/a
6196n/a Py_RETURN_NONE;
6197n/a}
6198n/a#endif /* HAVE_INITGROUPS */
6199n/a
6200n/a
6201n/a#ifdef HAVE_GETPGID
6202n/a/*[clinic input]
6203n/aos.getpgid
6204n/a
6205n/a pid: pid_t
6206n/a
6207n/aCall the system call getpgid(), and return the result.
6208n/a[clinic start generated code]*/
6209n/a
6210n/astatic PyObject *
6211n/aos_getpgid_impl(PyObject *module, pid_t pid)
6212n/a/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
6213n/a{
6214n/a pid_t pgid = getpgid(pid);
6215n/a if (pgid < 0)
6216n/a return posix_error();
6217n/a return PyLong_FromPid(pgid);
6218n/a}
6219n/a#endif /* HAVE_GETPGID */
6220n/a
6221n/a
6222n/a#ifdef HAVE_GETPGRP
6223n/a/*[clinic input]
6224n/aos.getpgrp
6225n/a
6226n/aReturn the current process group id.
6227n/a[clinic start generated code]*/
6228n/a
6229n/astatic PyObject *
6230n/aos_getpgrp_impl(PyObject *module)
6231n/a/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
6232n/a{
6233n/a#ifdef GETPGRP_HAVE_ARG
6234n/a return PyLong_FromPid(getpgrp(0));
6235n/a#else /* GETPGRP_HAVE_ARG */
6236n/a return PyLong_FromPid(getpgrp());
6237n/a#endif /* GETPGRP_HAVE_ARG */
6238n/a}
6239n/a#endif /* HAVE_GETPGRP */
6240n/a
6241n/a
6242n/a#ifdef HAVE_SETPGRP
6243n/a/*[clinic input]
6244n/aos.setpgrp
6245n/a
6246n/aMake the current process the leader of its process group.
6247n/a[clinic start generated code]*/
6248n/a
6249n/astatic PyObject *
6250n/aos_setpgrp_impl(PyObject *module)
6251n/a/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
6252n/a{
6253n/a#ifdef SETPGRP_HAVE_ARG
6254n/a if (setpgrp(0, 0) < 0)
6255n/a#else /* SETPGRP_HAVE_ARG */
6256n/a if (setpgrp() < 0)
6257n/a#endif /* SETPGRP_HAVE_ARG */
6258n/a return posix_error();
6259n/a Py_RETURN_NONE;
6260n/a}
6261n/a#endif /* HAVE_SETPGRP */
6262n/a
6263n/a#ifdef HAVE_GETPPID
6264n/a
6265n/a#ifdef MS_WINDOWS
6266n/a#include <tlhelp32.h>
6267n/a
6268n/astatic PyObject*
6269n/awin32_getppid()
6270n/a{
6271n/a HANDLE snapshot;
6272n/a pid_t mypid;
6273n/a PyObject* result = NULL;
6274n/a BOOL have_record;
6275n/a PROCESSENTRY32 pe;
6276n/a
6277n/a mypid = getpid(); /* This function never fails */
6278n/a
6279n/a snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
6280n/a if (snapshot == INVALID_HANDLE_VALUE)
6281n/a return PyErr_SetFromWindowsErr(GetLastError());
6282n/a
6283n/a pe.dwSize = sizeof(pe);
6284n/a have_record = Process32First(snapshot, &pe);
6285n/a while (have_record) {
6286n/a if (mypid == (pid_t)pe.th32ProcessID) {
6287n/a /* We could cache the ulong value in a static variable. */
6288n/a result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
6289n/a break;
6290n/a }
6291n/a
6292n/a have_record = Process32Next(snapshot, &pe);
6293n/a }
6294n/a
6295n/a /* If our loop exits and our pid was not found (result will be NULL)
6296n/a * then GetLastError will return ERROR_NO_MORE_FILES. This is an
6297n/a * error anyway, so let's raise it. */
6298n/a if (!result)
6299n/a result = PyErr_SetFromWindowsErr(GetLastError());
6300n/a
6301n/a CloseHandle(snapshot);
6302n/a
6303n/a return result;
6304n/a}
6305n/a#endif /*MS_WINDOWS*/
6306n/a
6307n/a
6308n/a/*[clinic input]
6309n/aos.getppid
6310n/a
6311n/aReturn the parent's process id.
6312n/a
6313n/aIf the parent process has already exited, Windows machines will still
6314n/areturn its id; others systems will return the id of the 'init' process (1).
6315n/a[clinic start generated code]*/
6316n/a
6317n/astatic PyObject *
6318n/aos_getppid_impl(PyObject *module)
6319n/a/*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
6320n/a{
6321n/a#ifdef MS_WINDOWS
6322n/a return win32_getppid();
6323n/a#else
6324n/a return PyLong_FromPid(getppid());
6325n/a#endif
6326n/a}
6327n/a#endif /* HAVE_GETPPID */
6328n/a
6329n/a
6330n/a#ifdef HAVE_GETLOGIN
6331n/a/*[clinic input]
6332n/aos.getlogin
6333n/a
6334n/aReturn the actual login name.
6335n/a[clinic start generated code]*/
6336n/a
6337n/astatic PyObject *
6338n/aos_getlogin_impl(PyObject *module)
6339n/a/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
6340n/a{
6341n/a PyObject *result = NULL;
6342n/a#ifdef MS_WINDOWS
6343n/a wchar_t user_name[UNLEN + 1];
6344n/a DWORD num_chars = Py_ARRAY_LENGTH(user_name);
6345n/a
6346n/a if (GetUserNameW(user_name, &num_chars)) {
6347n/a /* num_chars is the number of unicode chars plus null terminator */
6348n/a result = PyUnicode_FromWideChar(user_name, num_chars - 1);
6349n/a }
6350n/a else
6351n/a result = PyErr_SetFromWindowsErr(GetLastError());
6352n/a#else
6353n/a char *name;
6354n/a int old_errno = errno;
6355n/a
6356n/a errno = 0;
6357n/a name = getlogin();
6358n/a if (name == NULL) {
6359n/a if (errno)
6360n/a posix_error();
6361n/a else
6362n/a PyErr_SetString(PyExc_OSError, "unable to determine login name");
6363n/a }
6364n/a else
6365n/a result = PyUnicode_DecodeFSDefault(name);
6366n/a errno = old_errno;
6367n/a#endif
6368n/a return result;
6369n/a}
6370n/a#endif /* HAVE_GETLOGIN */
6371n/a
6372n/a
6373n/a#ifdef HAVE_GETUID
6374n/a/*[clinic input]
6375n/aos.getuid
6376n/a
6377n/aReturn the current process's user id.
6378n/a[clinic start generated code]*/
6379n/a
6380n/astatic PyObject *
6381n/aos_getuid_impl(PyObject *module)
6382n/a/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
6383n/a{
6384n/a return _PyLong_FromUid(getuid());
6385n/a}
6386n/a#endif /* HAVE_GETUID */
6387n/a
6388n/a
6389n/a#ifdef MS_WINDOWS
6390n/a#define HAVE_KILL
6391n/a#endif /* MS_WINDOWS */
6392n/a
6393n/a#ifdef HAVE_KILL
6394n/a/*[clinic input]
6395n/aos.kill
6396n/a
6397n/a pid: pid_t
6398n/a signal: Py_ssize_t
6399n/a /
6400n/a
6401n/aKill a process with a signal.
6402n/a[clinic start generated code]*/
6403n/a
6404n/astatic PyObject *
6405n/aos_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
6406n/a/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
6407n/a#ifndef MS_WINDOWS
6408n/a{
6409n/a if (kill(pid, (int)signal) == -1)
6410n/a return posix_error();
6411n/a Py_RETURN_NONE;
6412n/a}
6413n/a#else /* !MS_WINDOWS */
6414n/a{
6415n/a PyObject *result;
6416n/a DWORD sig = (DWORD)signal;
6417n/a DWORD err;
6418n/a HANDLE handle;
6419n/a
6420n/a /* Console processes which share a common console can be sent CTRL+C or
6421n/a CTRL+BREAK events, provided they handle said events. */
6422n/a if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
6423n/a if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
6424n/a err = GetLastError();
6425n/a PyErr_SetFromWindowsErr(err);
6426n/a }
6427n/a else
6428n/a Py_RETURN_NONE;
6429n/a }
6430n/a
6431n/a /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
6432n/a attempt to open and terminate the process. */
6433n/a handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
6434n/a if (handle == NULL) {
6435n/a err = GetLastError();
6436n/a return PyErr_SetFromWindowsErr(err);
6437n/a }
6438n/a
6439n/a if (TerminateProcess(handle, sig) == 0) {
6440n/a err = GetLastError();
6441n/a result = PyErr_SetFromWindowsErr(err);
6442n/a } else {
6443n/a Py_INCREF(Py_None);
6444n/a result = Py_None;
6445n/a }
6446n/a
6447n/a CloseHandle(handle);
6448n/a return result;
6449n/a}
6450n/a#endif /* !MS_WINDOWS */
6451n/a#endif /* HAVE_KILL */
6452n/a
6453n/a
6454n/a#ifdef HAVE_KILLPG
6455n/a/*[clinic input]
6456n/aos.killpg
6457n/a
6458n/a pgid: pid_t
6459n/a signal: int
6460n/a /
6461n/a
6462n/aKill a process group with a signal.
6463n/a[clinic start generated code]*/
6464n/a
6465n/astatic PyObject *
6466n/aos_killpg_impl(PyObject *module, pid_t pgid, int signal)
6467n/a/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
6468n/a{
6469n/a /* XXX some man pages make the `pgid` parameter an int, others
6470n/a a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
6471n/a take the same type. Moreover, pid_t is always at least as wide as
6472n/a int (else compilation of this module fails), which is safe. */
6473n/a if (killpg(pgid, signal) == -1)
6474n/a return posix_error();
6475n/a Py_RETURN_NONE;
6476n/a}
6477n/a#endif /* HAVE_KILLPG */
6478n/a
6479n/a
6480n/a#ifdef HAVE_PLOCK
6481n/a#ifdef HAVE_SYS_LOCK_H
6482n/a#include <sys/lock.h>
6483n/a#endif
6484n/a
6485n/a/*[clinic input]
6486n/aos.plock
6487n/a op: int
6488n/a /
6489n/a
6490n/aLock program segments into memory.");
6491n/a[clinic start generated code]*/
6492n/a
6493n/astatic PyObject *
6494n/aos_plock_impl(PyObject *module, int op)
6495n/a/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
6496n/a{
6497n/a if (plock(op) == -1)
6498n/a return posix_error();
6499n/a Py_RETURN_NONE;
6500n/a}
6501n/a#endif /* HAVE_PLOCK */
6502n/a
6503n/a
6504n/a#ifdef HAVE_SETUID
6505n/a/*[clinic input]
6506n/aos.setuid
6507n/a
6508n/a uid: uid_t
6509n/a /
6510n/a
6511n/aSet the current process's user id.
6512n/a[clinic start generated code]*/
6513n/a
6514n/astatic PyObject *
6515n/aos_setuid_impl(PyObject *module, uid_t uid)
6516n/a/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
6517n/a{
6518n/a if (setuid(uid) < 0)
6519n/a return posix_error();
6520n/a Py_RETURN_NONE;
6521n/a}
6522n/a#endif /* HAVE_SETUID */
6523n/a
6524n/a
6525n/a#ifdef HAVE_SETEUID
6526n/a/*[clinic input]
6527n/aos.seteuid
6528n/a
6529n/a euid: uid_t
6530n/a /
6531n/a
6532n/aSet the current process's effective user id.
6533n/a[clinic start generated code]*/
6534n/a
6535n/astatic PyObject *
6536n/aos_seteuid_impl(PyObject *module, uid_t euid)
6537n/a/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
6538n/a{
6539n/a if (seteuid(euid) < 0)
6540n/a return posix_error();
6541n/a Py_RETURN_NONE;
6542n/a}
6543n/a#endif /* HAVE_SETEUID */
6544n/a
6545n/a
6546n/a#ifdef HAVE_SETEGID
6547n/a/*[clinic input]
6548n/aos.setegid
6549n/a
6550n/a egid: gid_t
6551n/a /
6552n/a
6553n/aSet the current process's effective group id.
6554n/a[clinic start generated code]*/
6555n/a
6556n/astatic PyObject *
6557n/aos_setegid_impl(PyObject *module, gid_t egid)
6558n/a/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
6559n/a{
6560n/a if (setegid(egid) < 0)
6561n/a return posix_error();
6562n/a Py_RETURN_NONE;
6563n/a}
6564n/a#endif /* HAVE_SETEGID */
6565n/a
6566n/a
6567n/a#ifdef HAVE_SETREUID
6568n/a/*[clinic input]
6569n/aos.setreuid
6570n/a
6571n/a ruid: uid_t
6572n/a euid: uid_t
6573n/a /
6574n/a
6575n/aSet the current process's real and effective user ids.
6576n/a[clinic start generated code]*/
6577n/a
6578n/astatic PyObject *
6579n/aos_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
6580n/a/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
6581n/a{
6582n/a if (setreuid(ruid, euid) < 0) {
6583n/a return posix_error();
6584n/a } else {
6585n/a Py_RETURN_NONE;
6586n/a }
6587n/a}
6588n/a#endif /* HAVE_SETREUID */
6589n/a
6590n/a
6591n/a#ifdef HAVE_SETREGID
6592n/a/*[clinic input]
6593n/aos.setregid
6594n/a
6595n/a rgid: gid_t
6596n/a egid: gid_t
6597n/a /
6598n/a
6599n/aSet the current process's real and effective group ids.
6600n/a[clinic start generated code]*/
6601n/a
6602n/astatic PyObject *
6603n/aos_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
6604n/a/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
6605n/a{
6606n/a if (setregid(rgid, egid) < 0)
6607n/a return posix_error();
6608n/a Py_RETURN_NONE;
6609n/a}
6610n/a#endif /* HAVE_SETREGID */
6611n/a
6612n/a
6613n/a#ifdef HAVE_SETGID
6614n/a/*[clinic input]
6615n/aos.setgid
6616n/a gid: gid_t
6617n/a /
6618n/a
6619n/aSet the current process's group id.
6620n/a[clinic start generated code]*/
6621n/a
6622n/astatic PyObject *
6623n/aos_setgid_impl(PyObject *module, gid_t gid)
6624n/a/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
6625n/a{
6626n/a if (setgid(gid) < 0)
6627n/a return posix_error();
6628n/a Py_RETURN_NONE;
6629n/a}
6630n/a#endif /* HAVE_SETGID */
6631n/a
6632n/a
6633n/a#ifdef HAVE_SETGROUPS
6634n/a/*[clinic input]
6635n/aos.setgroups
6636n/a
6637n/a groups: object
6638n/a /
6639n/a
6640n/aSet the groups of the current process to list.
6641n/a[clinic start generated code]*/
6642n/a
6643n/astatic PyObject *
6644n/aos_setgroups(PyObject *module, PyObject *groups)
6645n/a/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
6646n/a{
6647n/a int i, len;
6648n/a gid_t grouplist[MAX_GROUPS];
6649n/a
6650n/a if (!PySequence_Check(groups)) {
6651n/a PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
6652n/a return NULL;
6653n/a }
6654n/a len = PySequence_Size(groups);
6655n/a if (len > MAX_GROUPS) {
6656n/a PyErr_SetString(PyExc_ValueError, "too many groups");
6657n/a return NULL;
6658n/a }
6659n/a for(i = 0; i < len; i++) {
6660n/a PyObject *elem;
6661n/a elem = PySequence_GetItem(groups, i);
6662n/a if (!elem)
6663n/a return NULL;
6664n/a if (!PyLong_Check(elem)) {
6665n/a PyErr_SetString(PyExc_TypeError,
6666n/a "groups must be integers");
6667n/a Py_DECREF(elem);
6668n/a return NULL;
6669n/a } else {
6670n/a if (!_Py_Gid_Converter(elem, &grouplist[i])) {
6671n/a Py_DECREF(elem);
6672n/a return NULL;
6673n/a }
6674n/a }
6675n/a Py_DECREF(elem);
6676n/a }
6677n/a
6678n/a if (setgroups(len, grouplist) < 0)
6679n/a return posix_error();
6680n/a Py_RETURN_NONE;
6681n/a}
6682n/a#endif /* HAVE_SETGROUPS */
6683n/a
6684n/a#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
6685n/astatic PyObject *
6686n/await_helper(pid_t pid, int status, struct rusage *ru)
6687n/a{
6688n/a PyObject *result;
6689n/a static PyObject *struct_rusage;
6690n/a _Py_IDENTIFIER(struct_rusage);
6691n/a
6692n/a if (pid == -1)
6693n/a return posix_error();
6694n/a
6695n/a if (struct_rusage == NULL) {
6696n/a PyObject *m = PyImport_ImportModuleNoBlock("resource");
6697n/a if (m == NULL)
6698n/a return NULL;
6699n/a struct_rusage = _PyObject_GetAttrId(m, &PyId_struct_rusage);
6700n/a Py_DECREF(m);
6701n/a if (struct_rusage == NULL)
6702n/a return NULL;
6703n/a }
6704n/a
6705n/a /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
6706n/a result = PyStructSequence_New((PyTypeObject*) struct_rusage);
6707n/a if (!result)
6708n/a return NULL;
6709n/a
6710n/a#ifndef doubletime
6711n/a#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
6712n/a#endif
6713n/a
6714n/a PyStructSequence_SET_ITEM(result, 0,
6715n/a PyFloat_FromDouble(doubletime(ru->ru_utime)));
6716n/a PyStructSequence_SET_ITEM(result, 1,
6717n/a PyFloat_FromDouble(doubletime(ru->ru_stime)));
6718n/a#define SET_INT(result, index, value)\
6719n/a PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
6720n/a SET_INT(result, 2, ru->ru_maxrss);
6721n/a SET_INT(result, 3, ru->ru_ixrss);
6722n/a SET_INT(result, 4, ru->ru_idrss);
6723n/a SET_INT(result, 5, ru->ru_isrss);
6724n/a SET_INT(result, 6, ru->ru_minflt);
6725n/a SET_INT(result, 7, ru->ru_majflt);
6726n/a SET_INT(result, 8, ru->ru_nswap);
6727n/a SET_INT(result, 9, ru->ru_inblock);
6728n/a SET_INT(result, 10, ru->ru_oublock);
6729n/a SET_INT(result, 11, ru->ru_msgsnd);
6730n/a SET_INT(result, 12, ru->ru_msgrcv);
6731n/a SET_INT(result, 13, ru->ru_nsignals);
6732n/a SET_INT(result, 14, ru->ru_nvcsw);
6733n/a SET_INT(result, 15, ru->ru_nivcsw);
6734n/a#undef SET_INT
6735n/a
6736n/a if (PyErr_Occurred()) {
6737n/a Py_DECREF(result);
6738n/a return NULL;
6739n/a }
6740n/a
6741n/a return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
6742n/a}
6743n/a#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
6744n/a
6745n/a
6746n/a#ifdef HAVE_WAIT3
6747n/a/*[clinic input]
6748n/aos.wait3
6749n/a
6750n/a options: int
6751n/aWait for completion of a child process.
6752n/a
6753n/aReturns a tuple of information about the child process:
6754n/a (pid, status, rusage)
6755n/a[clinic start generated code]*/
6756n/a
6757n/astatic PyObject *
6758n/aos_wait3_impl(PyObject *module, int options)
6759n/a/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
6760n/a{
6761n/a pid_t pid;
6762n/a struct rusage ru;
6763n/a int async_err = 0;
6764n/a WAIT_TYPE status;
6765n/a WAIT_STATUS_INT(status) = 0;
6766n/a
6767n/a do {
6768n/a Py_BEGIN_ALLOW_THREADS
6769n/a pid = wait3(&status, options, &ru);
6770n/a Py_END_ALLOW_THREADS
6771n/a } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
6772n/a if (pid < 0)
6773n/a return (!async_err) ? posix_error() : NULL;
6774n/a
6775n/a return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
6776n/a}
6777n/a#endif /* HAVE_WAIT3 */
6778n/a
6779n/a
6780n/a#ifdef HAVE_WAIT4
6781n/a/*[clinic input]
6782n/a
6783n/aos.wait4
6784n/a
6785n/a pid: pid_t
6786n/a options: int
6787n/a
6788n/aWait for completion of a specific child process.
6789n/a
6790n/aReturns a tuple of information about the child process:
6791n/a (pid, status, rusage)
6792n/a[clinic start generated code]*/
6793n/a
6794n/astatic PyObject *
6795n/aos_wait4_impl(PyObject *module, pid_t pid, int options)
6796n/a/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
6797n/a{
6798n/a pid_t res;
6799n/a struct rusage ru;
6800n/a int async_err = 0;
6801n/a WAIT_TYPE status;
6802n/a WAIT_STATUS_INT(status) = 0;
6803n/a
6804n/a do {
6805n/a Py_BEGIN_ALLOW_THREADS
6806n/a res = wait4(pid, &status, options, &ru);
6807n/a Py_END_ALLOW_THREADS
6808n/a } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
6809n/a if (res < 0)
6810n/a return (!async_err) ? posix_error() : NULL;
6811n/a
6812n/a return wait_helper(res, WAIT_STATUS_INT(status), &ru);
6813n/a}
6814n/a#endif /* HAVE_WAIT4 */
6815n/a
6816n/a
6817n/a#if defined(HAVE_WAITID) && !defined(__APPLE__)
6818n/a/*[clinic input]
6819n/aos.waitid
6820n/a
6821n/a idtype: idtype_t
6822n/a Must be one of be P_PID, P_PGID or P_ALL.
6823n/a id: id_t
6824n/a The id to wait on.
6825n/a options: int
6826n/a Constructed from the ORing of one or more of WEXITED, WSTOPPED
6827n/a or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
6828n/a /
6829n/a
6830n/aReturns the result of waiting for a process or processes.
6831n/a
6832n/aReturns either waitid_result or None if WNOHANG is specified and there are
6833n/ano children in a waitable state.
6834n/a[clinic start generated code]*/
6835n/a
6836n/astatic PyObject *
6837n/aos_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
6838n/a/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
6839n/a{
6840n/a PyObject *result;
6841n/a int res;
6842n/a int async_err = 0;
6843n/a siginfo_t si;
6844n/a si.si_pid = 0;
6845n/a
6846n/a do {
6847n/a Py_BEGIN_ALLOW_THREADS
6848n/a res = waitid(idtype, id, &si, options);
6849n/a Py_END_ALLOW_THREADS
6850n/a } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
6851n/a if (res < 0)
6852n/a return (!async_err) ? posix_error() : NULL;
6853n/a
6854n/a if (si.si_pid == 0)
6855n/a Py_RETURN_NONE;
6856n/a
6857n/a result = PyStructSequence_New(&WaitidResultType);
6858n/a if (!result)
6859n/a return NULL;
6860n/a
6861n/a PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
6862n/a PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
6863n/a PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
6864n/a PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
6865n/a PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
6866n/a if (PyErr_Occurred()) {
6867n/a Py_DECREF(result);
6868n/a return NULL;
6869n/a }
6870n/a
6871n/a return result;
6872n/a}
6873n/a#endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
6874n/a
6875n/a
6876n/a#if defined(HAVE_WAITPID)
6877n/a/*[clinic input]
6878n/aos.waitpid
6879n/a pid: pid_t
6880n/a options: int
6881n/a /
6882n/a
6883n/aWait for completion of a given child process.
6884n/a
6885n/aReturns a tuple of information regarding the child process:
6886n/a (pid, status)
6887n/a
6888n/aThe options argument is ignored on Windows.
6889n/a[clinic start generated code]*/
6890n/a
6891n/astatic PyObject *
6892n/aos_waitpid_impl(PyObject *module, pid_t pid, int options)
6893n/a/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
6894n/a{
6895n/a pid_t res;
6896n/a int async_err = 0;
6897n/a WAIT_TYPE status;
6898n/a WAIT_STATUS_INT(status) = 0;
6899n/a
6900n/a do {
6901n/a Py_BEGIN_ALLOW_THREADS
6902n/a res = waitpid(pid, &status, options);
6903n/a Py_END_ALLOW_THREADS
6904n/a } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
6905n/a if (res < 0)
6906n/a return (!async_err) ? posix_error() : NULL;
6907n/a
6908n/a return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
6909n/a}
6910n/a#elif defined(HAVE_CWAIT)
6911n/a/* MS C has a variant of waitpid() that's usable for most purposes. */
6912n/a/*[clinic input]
6913n/aos.waitpid
6914n/a pid: intptr_t
6915n/a options: int
6916n/a /
6917n/a
6918n/aWait for completion of a given process.
6919n/a
6920n/aReturns a tuple of information regarding the process:
6921n/a (pid, status << 8)
6922n/a
6923n/aThe options argument is ignored on Windows.
6924n/a[clinic start generated code]*/
6925n/a
6926n/astatic PyObject *
6927n/aos_waitpid_impl(PyObject *module, intptr_t pid, int options)
6928n/a/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
6929n/a{
6930n/a int status;
6931n/a intptr_t res;
6932n/a int async_err = 0;
6933n/a
6934n/a do {
6935n/a Py_BEGIN_ALLOW_THREADS
6936n/a _Py_BEGIN_SUPPRESS_IPH
6937n/a res = _cwait(&status, pid, options);
6938n/a _Py_END_SUPPRESS_IPH
6939n/a Py_END_ALLOW_THREADS
6940n/a } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
6941n/a if (res < 0)
6942n/a return (!async_err) ? posix_error() : NULL;
6943n/a
6944n/a /* shift the status left a byte so this is more like the POSIX waitpid */
6945n/a return Py_BuildValue(_Py_PARSE_INTPTR "i", res, status << 8);
6946n/a}
6947n/a#endif
6948n/a
6949n/a
6950n/a#ifdef HAVE_WAIT
6951n/a/*[clinic input]
6952n/aos.wait
6953n/a
6954n/aWait for completion of a child process.
6955n/a
6956n/aReturns a tuple of information about the child process:
6957n/a (pid, status)
6958n/a[clinic start generated code]*/
6959n/a
6960n/astatic PyObject *
6961n/aos_wait_impl(PyObject *module)
6962n/a/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
6963n/a{
6964n/a pid_t pid;
6965n/a int async_err = 0;
6966n/a WAIT_TYPE status;
6967n/a WAIT_STATUS_INT(status) = 0;
6968n/a
6969n/a do {
6970n/a Py_BEGIN_ALLOW_THREADS
6971n/a pid = wait(&status);
6972n/a Py_END_ALLOW_THREADS
6973n/a } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
6974n/a if (pid < 0)
6975n/a return (!async_err) ? posix_error() : NULL;
6976n/a
6977n/a return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
6978n/a}
6979n/a#endif /* HAVE_WAIT */
6980n/a
6981n/a
6982n/a#if defined(HAVE_READLINK) || defined(MS_WINDOWS)
6983n/aPyDoc_STRVAR(readlink__doc__,
6984n/a"readlink(path, *, dir_fd=None) -> path\n\n\
6985n/aReturn a string representing the path to which the symbolic link points.\n\
6986n/a\n\
6987n/aIf dir_fd is not None, it should be a file descriptor open to a directory,\n\
6988n/a and path should be relative; path will then be relative to that directory.\n\
6989n/adir_fd may not be implemented on your platform.\n\
6990n/a If it is unavailable, using it will raise a NotImplementedError.");
6991n/a#endif
6992n/a
6993n/a#ifdef HAVE_READLINK
6994n/a
6995n/a/* AC 3.5: merge win32 and not together */
6996n/astatic PyObject *
6997n/aposix_readlink(PyObject *self, PyObject *args, PyObject *kwargs)
6998n/a{
6999n/a path_t path;
7000n/a int dir_fd = DEFAULT_DIR_FD;
7001n/a char buffer[MAXPATHLEN+1];
7002n/a ssize_t length;
7003n/a PyObject *return_value = NULL;
7004n/a static char *keywords[] = {"path", "dir_fd", NULL};
7005n/a
7006n/a memset(&path, 0, sizeof(path));
7007n/a path.function_name = "readlink";
7008n/a if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:readlink", keywords,
7009n/a path_converter, &path,
7010n/a READLINKAT_DIR_FD_CONVERTER, &dir_fd))
7011n/a return NULL;
7012n/a
7013n/a Py_BEGIN_ALLOW_THREADS
7014n/a#ifdef HAVE_READLINKAT
7015n/a if (dir_fd != DEFAULT_DIR_FD)
7016n/a length = readlinkat(dir_fd, path.narrow, buffer, MAXPATHLEN);
7017n/a else
7018n/a#endif
7019n/a length = readlink(path.narrow, buffer, MAXPATHLEN);
7020n/a Py_END_ALLOW_THREADS
7021n/a
7022n/a if (length < 0) {
7023n/a return_value = path_error(&path);
7024n/a goto exit;
7025n/a }
7026n/a buffer[length] = '\0';
7027n/a
7028n/a if (PyUnicode_Check(path.object))
7029n/a return_value = PyUnicode_DecodeFSDefaultAndSize(buffer, length);
7030n/a else
7031n/a return_value = PyBytes_FromStringAndSize(buffer, length);
7032n/aexit:
7033n/a path_cleanup(&path);
7034n/a return return_value;
7035n/a}
7036n/a
7037n/a#endif /* HAVE_READLINK */
7038n/a
7039n/a#if !defined(HAVE_READLINK) && defined(MS_WINDOWS)
7040n/a
7041n/astatic PyObject *
7042n/awin_readlink(PyObject *self, PyObject *args, PyObject *kwargs)
7043n/a{
7044n/a const wchar_t *path;
7045n/a DWORD n_bytes_returned;
7046n/a DWORD io_result;
7047n/a PyObject *po, *result;
7048n/a int dir_fd;
7049n/a HANDLE reparse_point_handle;
7050n/a
7051n/a char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
7052n/a _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
7053n/a const wchar_t *print_name;
7054n/a
7055n/a static char *keywords[] = {"path", "dir_fd", NULL};
7056n/a
7057n/a if (!PyArg_ParseTupleAndKeywords(args, kwargs, "U|$O&:readlink", keywords,
7058n/a &po,
7059n/a dir_fd_unavailable, &dir_fd
7060n/a ))
7061n/a return NULL;
7062n/a
7063n/a path = PyUnicode_AsUnicode(po);
7064n/a if (path == NULL)
7065n/a return NULL;
7066n/a
7067n/a /* First get a handle to the reparse point */
7068n/a Py_BEGIN_ALLOW_THREADS
7069n/a reparse_point_handle = CreateFileW(
7070n/a path,
7071n/a 0,
7072n/a 0,
7073n/a 0,
7074n/a OPEN_EXISTING,
7075n/a FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
7076n/a 0);
7077n/a Py_END_ALLOW_THREADS
7078n/a
7079n/a if (reparse_point_handle==INVALID_HANDLE_VALUE)
7080n/a return win32_error_object("readlink", po);
7081n/a
7082n/a Py_BEGIN_ALLOW_THREADS
7083n/a /* New call DeviceIoControl to read the reparse point */
7084n/a io_result = DeviceIoControl(
7085n/a reparse_point_handle,
7086n/a FSCTL_GET_REPARSE_POINT,
7087n/a 0, 0, /* in buffer */
7088n/a target_buffer, sizeof(target_buffer),
7089n/a &n_bytes_returned,
7090n/a 0 /* we're not using OVERLAPPED_IO */
7091n/a );
7092n/a CloseHandle(reparse_point_handle);
7093n/a Py_END_ALLOW_THREADS
7094n/a
7095n/a if (io_result==0)
7096n/a return win32_error_object("readlink", po);
7097n/a
7098n/a if (rdb->ReparseTag != IO_REPARSE_TAG_SYMLINK)
7099n/a {
7100n/a PyErr_SetString(PyExc_ValueError,
7101n/a "not a symbolic link");
7102n/a return NULL;
7103n/a }
7104n/a print_name = rdb->SymbolicLinkReparseBuffer.PathBuffer +
7105n/a rdb->SymbolicLinkReparseBuffer.PrintNameOffset;
7106n/a
7107n/a result = PyUnicode_FromWideChar(print_name,
7108n/a rdb->SymbolicLinkReparseBuffer.PrintNameLength/2);
7109n/a return result;
7110n/a}
7111n/a
7112n/a#endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */
7113n/a
7114n/a
7115n/a
7116n/a#ifdef HAVE_SYMLINK
7117n/a
7118n/a#if defined(MS_WINDOWS)
7119n/a
7120n/a/* Grab CreateSymbolicLinkW dynamically from kernel32 */
7121n/astatic DWORD (CALLBACK *Py_CreateSymbolicLinkW)(LPCWSTR, LPCWSTR, DWORD) = NULL;
7122n/a
7123n/astatic int
7124n/acheck_CreateSymbolicLink(void)
7125n/a{
7126n/a HINSTANCE hKernel32;
7127n/a /* only recheck */
7128n/a if (Py_CreateSymbolicLinkW)
7129n/a return 1;
7130n/a hKernel32 = GetModuleHandleW(L"KERNEL32");
7131n/a *(FARPROC*)&Py_CreateSymbolicLinkW = GetProcAddress(hKernel32,
7132n/a "CreateSymbolicLinkW");
7133n/a return Py_CreateSymbolicLinkW != NULL;
7134n/a}
7135n/a
7136n/a/* Remove the last portion of the path */
7137n/astatic void
7138n/a_dirnameW(WCHAR *path)
7139n/a{
7140n/a WCHAR *ptr;
7141n/a
7142n/a /* walk the path from the end until a backslash is encountered */
7143n/a for(ptr = path + wcslen(path); ptr != path; ptr--) {
7144n/a if (*ptr == L'\\' || *ptr == L'/')
7145n/a break;
7146n/a }
7147n/a *ptr = 0;
7148n/a}
7149n/a
7150n/a/* Is this path absolute? */
7151n/astatic int
7152n/a_is_absW(const WCHAR *path)
7153n/a{
7154n/a return path[0] == L'\\' || path[0] == L'/' || path[1] == L':';
7155n/a
7156n/a}
7157n/a
7158n/a/* join root and rest with a backslash */
7159n/astatic void
7160n/a_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
7161n/a{
7162n/a size_t root_len;
7163n/a
7164n/a if (_is_absW(rest)) {
7165n/a wcscpy(dest_path, rest);
7166n/a return;
7167n/a }
7168n/a
7169n/a root_len = wcslen(root);
7170n/a
7171n/a wcscpy(dest_path, root);
7172n/a if(root_len) {
7173n/a dest_path[root_len] = L'\\';
7174n/a root_len++;
7175n/a }
7176n/a wcscpy(dest_path+root_len, rest);
7177n/a}
7178n/a
7179n/a/* Return True if the path at src relative to dest is a directory */
7180n/astatic int
7181n/a_check_dirW(LPCWSTR src, LPCWSTR dest)
7182n/a{
7183n/a WIN32_FILE_ATTRIBUTE_DATA src_info;
7184n/a WCHAR dest_parent[MAX_PATH];
7185n/a WCHAR src_resolved[MAX_PATH] = L"";
7186n/a
7187n/a /* dest_parent = os.path.dirname(dest) */
7188n/a wcscpy(dest_parent, dest);
7189n/a _dirnameW(dest_parent);
7190n/a /* src_resolved = os.path.join(dest_parent, src) */
7191n/a _joinW(src_resolved, dest_parent, src);
7192n/a return (
7193n/a GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
7194n/a && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
7195n/a );
7196n/a}
7197n/a#endif
7198n/a
7199n/a
7200n/a/*[clinic input]
7201n/aos.symlink
7202n/a src: path_t
7203n/a dst: path_t
7204n/a target_is_directory: bool = False
7205n/a *
7206n/a dir_fd: dir_fd(requires='symlinkat')=None
7207n/a
7208n/a# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
7209n/a
7210n/aCreate a symbolic link pointing to src named dst.
7211n/a
7212n/atarget_is_directory is required on Windows if the target is to be
7213n/a interpreted as a directory. (On Windows, symlink requires
7214n/a Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
7215n/a target_is_directory is ignored on non-Windows platforms.
7216n/a
7217n/aIf dir_fd is not None, it should be a file descriptor open to a directory,
7218n/a and path should be relative; path will then be relative to that directory.
7219n/adir_fd may not be implemented on your platform.
7220n/a If it is unavailable, using it will raise a NotImplementedError.
7221n/a
7222n/a[clinic start generated code]*/
7223n/a
7224n/astatic PyObject *
7225n/aos_symlink_impl(PyObject *module, path_t *src, path_t *dst,
7226n/a int target_is_directory, int dir_fd)
7227n/a/*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
7228n/a{
7229n/a#ifdef MS_WINDOWS
7230n/a DWORD result;
7231n/a#else
7232n/a int result;
7233n/a#endif
7234n/a
7235n/a#ifdef MS_WINDOWS
7236n/a if (!check_CreateSymbolicLink()) {
7237n/a PyErr_SetString(PyExc_NotImplementedError,
7238n/a "CreateSymbolicLink functions not found");
7239n/a return NULL;
7240n/a }
7241n/a if (!win32_can_symlink) {
7242n/a PyErr_SetString(PyExc_OSError, "symbolic link privilege not held");
7243n/a return NULL;
7244n/a }
7245n/a#endif
7246n/a
7247n/a if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
7248n/a PyErr_SetString(PyExc_ValueError,
7249n/a "symlink: src and dst must be the same type");
7250n/a return NULL;
7251n/a }
7252n/a
7253n/a#ifdef MS_WINDOWS
7254n/a
7255n/a Py_BEGIN_ALLOW_THREADS
7256n/a /* if src is a directory, ensure target_is_directory==1 */
7257n/a target_is_directory |= _check_dirW(src->wide, dst->wide);
7258n/a result = Py_CreateSymbolicLinkW(dst->wide, src->wide,
7259n/a target_is_directory);
7260n/a Py_END_ALLOW_THREADS
7261n/a
7262n/a if (!result)
7263n/a return path_error2(src, dst);
7264n/a
7265n/a#else
7266n/a
7267n/a Py_BEGIN_ALLOW_THREADS
7268n/a#if HAVE_SYMLINKAT
7269n/a if (dir_fd != DEFAULT_DIR_FD)
7270n/a result = symlinkat(src->narrow, dir_fd, dst->narrow);
7271n/a else
7272n/a#endif
7273n/a result = symlink(src->narrow, dst->narrow);
7274n/a Py_END_ALLOW_THREADS
7275n/a
7276n/a if (result)
7277n/a return path_error2(src, dst);
7278n/a#endif
7279n/a
7280n/a Py_RETURN_NONE;
7281n/a}
7282n/a#endif /* HAVE_SYMLINK */
7283n/a
7284n/a
7285n/a
7286n/a
7287n/astatic PyStructSequence_Field times_result_fields[] = {
7288n/a {"user", "user time"},
7289n/a {"system", "system time"},
7290n/a {"children_user", "user time of children"},
7291n/a {"children_system", "system time of children"},
7292n/a {"elapsed", "elapsed time since an arbitrary point in the past"},
7293n/a {NULL}
7294n/a};
7295n/a
7296n/aPyDoc_STRVAR(times_result__doc__,
7297n/a"times_result: Result from os.times().\n\n\
7298n/aThis object may be accessed either as a tuple of\n\
7299n/a (user, system, children_user, children_system, elapsed),\n\
7300n/aor via the attributes user, system, children_user, children_system,\n\
7301n/aand elapsed.\n\
7302n/a\n\
7303n/aSee os.times for more information.");
7304n/a
7305n/astatic PyStructSequence_Desc times_result_desc = {
7306n/a "times_result", /* name */
7307n/a times_result__doc__, /* doc */
7308n/a times_result_fields,
7309n/a 5
7310n/a};
7311n/a
7312n/astatic PyTypeObject TimesResultType;
7313n/a
7314n/a#ifdef MS_WINDOWS
7315n/a#define HAVE_TIMES /* mandatory, for the method table */
7316n/a#endif
7317n/a
7318n/a#ifdef HAVE_TIMES
7319n/a
7320n/astatic PyObject *
7321n/abuild_times_result(double user, double system,
7322n/a double children_user, double children_system,
7323n/a double elapsed)
7324n/a{
7325n/a PyObject *value = PyStructSequence_New(&TimesResultType);
7326n/a if (value == NULL)
7327n/a return NULL;
7328n/a
7329n/a#define SET(i, field) \
7330n/a { \
7331n/a PyObject *o = PyFloat_FromDouble(field); \
7332n/a if (!o) { \
7333n/a Py_DECREF(value); \
7334n/a return NULL; \
7335n/a } \
7336n/a PyStructSequence_SET_ITEM(value, i, o); \
7337n/a } \
7338n/a
7339n/a SET(0, user);
7340n/a SET(1, system);
7341n/a SET(2, children_user);
7342n/a SET(3, children_system);
7343n/a SET(4, elapsed);
7344n/a
7345n/a#undef SET
7346n/a
7347n/a return value;
7348n/a}
7349n/a
7350n/a
7351n/a#ifndef MS_WINDOWS
7352n/a#define NEED_TICKS_PER_SECOND
7353n/astatic long ticks_per_second = -1;
7354n/a#endif /* MS_WINDOWS */
7355n/a
7356n/a/*[clinic input]
7357n/aos.times
7358n/a
7359n/aReturn a collection containing process timing information.
7360n/a
7361n/aThe object returned behaves like a named tuple with these fields:
7362n/a (utime, stime, cutime, cstime, elapsed_time)
7363n/aAll fields are floating point numbers.
7364n/a[clinic start generated code]*/
7365n/a
7366n/astatic PyObject *
7367n/aos_times_impl(PyObject *module)
7368n/a/*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
7369n/a#ifdef MS_WINDOWS
7370n/a{
7371n/a FILETIME create, exit, kernel, user;
7372n/a HANDLE hProc;
7373n/a hProc = GetCurrentProcess();
7374n/a GetProcessTimes(hProc, &create, &exit, &kernel, &user);
7375n/a /* The fields of a FILETIME structure are the hi and lo part
7376n/a of a 64-bit value expressed in 100 nanosecond units.
7377n/a 1e7 is one second in such units; 1e-7 the inverse.
7378n/a 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
7379n/a */
7380n/a return build_times_result(
7381n/a (double)(user.dwHighDateTime*429.4967296 +
7382n/a user.dwLowDateTime*1e-7),
7383n/a (double)(kernel.dwHighDateTime*429.4967296 +
7384n/a kernel.dwLowDateTime*1e-7),
7385n/a (double)0,
7386n/a (double)0,
7387n/a (double)0);
7388n/a}
7389n/a#else /* MS_WINDOWS */
7390n/a{
7391n/a
7392n/a
7393n/a struct tms t;
7394n/a clock_t c;
7395n/a errno = 0;
7396n/a c = times(&t);
7397n/a if (c == (clock_t) -1)
7398n/a return posix_error();
7399n/a return build_times_result(
7400n/a (double)t.tms_utime / ticks_per_second,
7401n/a (double)t.tms_stime / ticks_per_second,
7402n/a (double)t.tms_cutime / ticks_per_second,
7403n/a (double)t.tms_cstime / ticks_per_second,
7404n/a (double)c / ticks_per_second);
7405n/a}
7406n/a#endif /* MS_WINDOWS */
7407n/a#endif /* HAVE_TIMES */
7408n/a
7409n/a
7410n/a#ifdef HAVE_GETSID
7411n/a/*[clinic input]
7412n/aos.getsid
7413n/a
7414n/a pid: pid_t
7415n/a /
7416n/a
7417n/aCall the system call getsid(pid) and return the result.
7418n/a[clinic start generated code]*/
7419n/a
7420n/astatic PyObject *
7421n/aos_getsid_impl(PyObject *module, pid_t pid)
7422n/a/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
7423n/a{
7424n/a int sid;
7425n/a sid = getsid(pid);
7426n/a if (sid < 0)
7427n/a return posix_error();
7428n/a return PyLong_FromLong((long)sid);
7429n/a}
7430n/a#endif /* HAVE_GETSID */
7431n/a
7432n/a
7433n/a#ifdef HAVE_SETSID
7434n/a/*[clinic input]
7435n/aos.setsid
7436n/a
7437n/aCall the system call setsid().
7438n/a[clinic start generated code]*/
7439n/a
7440n/astatic PyObject *
7441n/aos_setsid_impl(PyObject *module)
7442n/a/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
7443n/a{
7444n/a if (setsid() < 0)
7445n/a return posix_error();
7446n/a Py_RETURN_NONE;
7447n/a}
7448n/a#endif /* HAVE_SETSID */
7449n/a
7450n/a
7451n/a#ifdef HAVE_SETPGID
7452n/a/*[clinic input]
7453n/aos.setpgid
7454n/a
7455n/a pid: pid_t
7456n/a pgrp: pid_t
7457n/a /
7458n/a
7459n/aCall the system call setpgid(pid, pgrp).
7460n/a[clinic start generated code]*/
7461n/a
7462n/astatic PyObject *
7463n/aos_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
7464n/a/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
7465n/a{
7466n/a if (setpgid(pid, pgrp) < 0)
7467n/a return posix_error();
7468n/a Py_RETURN_NONE;
7469n/a}
7470n/a#endif /* HAVE_SETPGID */
7471n/a
7472n/a
7473n/a#ifdef HAVE_TCGETPGRP
7474n/a/*[clinic input]
7475n/aos.tcgetpgrp
7476n/a
7477n/a fd: int
7478n/a /
7479n/a
7480n/aReturn the process group associated with the terminal specified by fd.
7481n/a[clinic start generated code]*/
7482n/a
7483n/astatic PyObject *
7484n/aos_tcgetpgrp_impl(PyObject *module, int fd)
7485n/a/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
7486n/a{
7487n/a pid_t pgid = tcgetpgrp(fd);
7488n/a if (pgid < 0)
7489n/a return posix_error();
7490n/a return PyLong_FromPid(pgid);
7491n/a}
7492n/a#endif /* HAVE_TCGETPGRP */
7493n/a
7494n/a
7495n/a#ifdef HAVE_TCSETPGRP
7496n/a/*[clinic input]
7497n/aos.tcsetpgrp
7498n/a
7499n/a fd: int
7500n/a pgid: pid_t
7501n/a /
7502n/a
7503n/aSet the process group associated with the terminal specified by fd.
7504n/a[clinic start generated code]*/
7505n/a
7506n/astatic PyObject *
7507n/aos_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
7508n/a/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
7509n/a{
7510n/a if (tcsetpgrp(fd, pgid) < 0)
7511n/a return posix_error();
7512n/a Py_RETURN_NONE;
7513n/a}
7514n/a#endif /* HAVE_TCSETPGRP */
7515n/a
7516n/a/* Functions acting on file descriptors */
7517n/a
7518n/a#ifdef O_CLOEXEC
7519n/aextern int _Py_open_cloexec_works;
7520n/a#endif
7521n/a
7522n/a
7523n/a/*[clinic input]
7524n/aos.open -> int
7525n/a path: path_t
7526n/a flags: int
7527n/a mode: int = 0o777
7528n/a *
7529n/a dir_fd: dir_fd(requires='openat') = None
7530n/a
7531n/a# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
7532n/a
7533n/aOpen a file for low level IO. Returns a file descriptor (integer).
7534n/a
7535n/aIf dir_fd is not None, it should be a file descriptor open to a directory,
7536n/a and path should be relative; path will then be relative to that directory.
7537n/adir_fd may not be implemented on your platform.
7538n/a If it is unavailable, using it will raise a NotImplementedError.
7539n/a[clinic start generated code]*/
7540n/a
7541n/astatic int
7542n/aos_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
7543n/a/*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
7544n/a{
7545n/a int fd;
7546n/a int async_err = 0;
7547n/a
7548n/a#ifdef O_CLOEXEC
7549n/a int *atomic_flag_works = &_Py_open_cloexec_works;
7550n/a#elif !defined(MS_WINDOWS)
7551n/a int *atomic_flag_works = NULL;
7552n/a#endif
7553n/a
7554n/a#ifdef MS_WINDOWS
7555n/a flags |= O_NOINHERIT;
7556n/a#elif defined(O_CLOEXEC)
7557n/a flags |= O_CLOEXEC;
7558n/a#endif
7559n/a
7560n/a _Py_BEGIN_SUPPRESS_IPH
7561n/a do {
7562n/a Py_BEGIN_ALLOW_THREADS
7563n/a#ifdef MS_WINDOWS
7564n/a fd = _wopen(path->wide, flags, mode);
7565n/a#else
7566n/a#ifdef HAVE_OPENAT
7567n/a if (dir_fd != DEFAULT_DIR_FD)
7568n/a fd = openat(dir_fd, path->narrow, flags, mode);
7569n/a else
7570n/a#endif /* HAVE_OPENAT */
7571n/a fd = open(path->narrow, flags, mode);
7572n/a#endif /* !MS_WINDOWS */
7573n/a Py_END_ALLOW_THREADS
7574n/a } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7575n/a _Py_END_SUPPRESS_IPH
7576n/a
7577n/a if (fd < 0) {
7578n/a if (!async_err)
7579n/a PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
7580n/a return -1;
7581n/a }
7582n/a
7583n/a#ifndef MS_WINDOWS
7584n/a if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
7585n/a close(fd);
7586n/a return -1;
7587n/a }
7588n/a#endif
7589n/a
7590n/a return fd;
7591n/a}
7592n/a
7593n/a
7594n/a/*[clinic input]
7595n/aos.close
7596n/a
7597n/a fd: int
7598n/a
7599n/aClose a file descriptor.
7600n/a[clinic start generated code]*/
7601n/a
7602n/astatic PyObject *
7603n/aos_close_impl(PyObject *module, int fd)
7604n/a/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
7605n/a{
7606n/a int res;
7607n/a /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
7608n/a * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
7609n/a * for more details.
7610n/a */
7611n/a Py_BEGIN_ALLOW_THREADS
7612n/a _Py_BEGIN_SUPPRESS_IPH
7613n/a res = close(fd);
7614n/a _Py_END_SUPPRESS_IPH
7615n/a Py_END_ALLOW_THREADS
7616n/a if (res < 0)
7617n/a return posix_error();
7618n/a Py_RETURN_NONE;
7619n/a}
7620n/a
7621n/a
7622n/a/*[clinic input]
7623n/aos.closerange
7624n/a
7625n/a fd_low: int
7626n/a fd_high: int
7627n/a /
7628n/a
7629n/aCloses all file descriptors in [fd_low, fd_high), ignoring errors.
7630n/a[clinic start generated code]*/
7631n/a
7632n/astatic PyObject *
7633n/aos_closerange_impl(PyObject *module, int fd_low, int fd_high)
7634n/a/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
7635n/a{
7636n/a int i;
7637n/a Py_BEGIN_ALLOW_THREADS
7638n/a _Py_BEGIN_SUPPRESS_IPH
7639n/a for (i = Py_MAX(fd_low, 0); i < fd_high; i++)
7640n/a close(i);
7641n/a _Py_END_SUPPRESS_IPH
7642n/a Py_END_ALLOW_THREADS
7643n/a Py_RETURN_NONE;
7644n/a}
7645n/a
7646n/a
7647n/a/*[clinic input]
7648n/aos.dup -> int
7649n/a
7650n/a fd: int
7651n/a /
7652n/a
7653n/aReturn a duplicate of a file descriptor.
7654n/a[clinic start generated code]*/
7655n/a
7656n/astatic int
7657n/aos_dup_impl(PyObject *module, int fd)
7658n/a/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
7659n/a{
7660n/a return _Py_dup(fd);
7661n/a}
7662n/a
7663n/a
7664n/a/*[clinic input]
7665n/aos.dup2
7666n/a fd: int
7667n/a fd2: int
7668n/a inheritable: bool=True
7669n/a
7670n/aDuplicate file descriptor.
7671n/a[clinic start generated code]*/
7672n/a
7673n/astatic PyObject *
7674n/aos_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
7675n/a/*[clinic end generated code: output=db832a2d872ccc5f input=76e96f511be0352f]*/
7676n/a{
7677n/a int res;
7678n/a#if defined(HAVE_DUP3) && \
7679n/a !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
7680n/a /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
7681n/a int dup3_works = -1;
7682n/a#endif
7683n/a
7684n/a if (fd < 0 || fd2 < 0)
7685n/a return posix_error();
7686n/a
7687n/a /* dup2() can fail with EINTR if the target FD is already open, because it
7688n/a * then has to be closed. See os_close_impl() for why we don't handle EINTR
7689n/a * upon close(), and therefore below.
7690n/a */
7691n/a#ifdef MS_WINDOWS
7692n/a Py_BEGIN_ALLOW_THREADS
7693n/a _Py_BEGIN_SUPPRESS_IPH
7694n/a res = dup2(fd, fd2);
7695n/a _Py_END_SUPPRESS_IPH
7696n/a Py_END_ALLOW_THREADS
7697n/a if (res < 0)
7698n/a return posix_error();
7699n/a
7700n/a /* Character files like console cannot be make non-inheritable */
7701n/a if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
7702n/a close(fd2);
7703n/a return NULL;
7704n/a }
7705n/a
7706n/a#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
7707n/a Py_BEGIN_ALLOW_THREADS
7708n/a if (!inheritable)
7709n/a res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
7710n/a else
7711n/a res = dup2(fd, fd2);
7712n/a Py_END_ALLOW_THREADS
7713n/a if (res < 0)
7714n/a return posix_error();
7715n/a
7716n/a#else
7717n/a
7718n/a#ifdef HAVE_DUP3
7719n/a if (!inheritable && dup3_works != 0) {
7720n/a Py_BEGIN_ALLOW_THREADS
7721n/a res = dup3(fd, fd2, O_CLOEXEC);
7722n/a Py_END_ALLOW_THREADS
7723n/a if (res < 0) {
7724n/a if (dup3_works == -1)
7725n/a dup3_works = (errno != ENOSYS);
7726n/a if (dup3_works)
7727n/a return posix_error();
7728n/a }
7729n/a }
7730n/a
7731n/a if (inheritable || dup3_works == 0)
7732n/a {
7733n/a#endif
7734n/a Py_BEGIN_ALLOW_THREADS
7735n/a res = dup2(fd, fd2);
7736n/a Py_END_ALLOW_THREADS
7737n/a if (res < 0)
7738n/a return posix_error();
7739n/a
7740n/a if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
7741n/a close(fd2);
7742n/a return NULL;
7743n/a }
7744n/a#ifdef HAVE_DUP3
7745n/a }
7746n/a#endif
7747n/a
7748n/a#endif
7749n/a
7750n/a Py_RETURN_NONE;
7751n/a}
7752n/a
7753n/a
7754n/a#ifdef HAVE_LOCKF
7755n/a/*[clinic input]
7756n/aos.lockf
7757n/a
7758n/a fd: int
7759n/a An open file descriptor.
7760n/a command: int
7761n/a One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
7762n/a length: Py_off_t
7763n/a The number of bytes to lock, starting at the current position.
7764n/a /
7765n/a
7766n/aApply, test or remove a POSIX lock on an open file descriptor.
7767n/a
7768n/a[clinic start generated code]*/
7769n/a
7770n/astatic PyObject *
7771n/aos_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
7772n/a/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
7773n/a{
7774n/a int res;
7775n/a
7776n/a Py_BEGIN_ALLOW_THREADS
7777n/a res = lockf(fd, command, length);
7778n/a Py_END_ALLOW_THREADS
7779n/a
7780n/a if (res < 0)
7781n/a return posix_error();
7782n/a
7783n/a Py_RETURN_NONE;
7784n/a}
7785n/a#endif /* HAVE_LOCKF */
7786n/a
7787n/a
7788n/a/*[clinic input]
7789n/aos.lseek -> Py_off_t
7790n/a
7791n/a fd: int
7792n/a position: Py_off_t
7793n/a how: int
7794n/a /
7795n/a
7796n/aSet the position of a file descriptor. Return the new position.
7797n/a
7798n/aReturn the new cursor position in number of bytes
7799n/arelative to the beginning of the file.
7800n/a[clinic start generated code]*/
7801n/a
7802n/astatic Py_off_t
7803n/aos_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
7804n/a/*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
7805n/a{
7806n/a Py_off_t result;
7807n/a
7808n/a#ifdef SEEK_SET
7809n/a /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
7810n/a switch (how) {
7811n/a case 0: how = SEEK_SET; break;
7812n/a case 1: how = SEEK_CUR; break;
7813n/a case 2: how = SEEK_END; break;
7814n/a }
7815n/a#endif /* SEEK_END */
7816n/a
7817n/a if (PyErr_Occurred())
7818n/a return -1;
7819n/a
7820n/a Py_BEGIN_ALLOW_THREADS
7821n/a _Py_BEGIN_SUPPRESS_IPH
7822n/a#ifdef MS_WINDOWS
7823n/a result = _lseeki64(fd, position, how);
7824n/a#else
7825n/a result = lseek(fd, position, how);
7826n/a#endif
7827n/a _Py_END_SUPPRESS_IPH
7828n/a Py_END_ALLOW_THREADS
7829n/a if (result < 0)
7830n/a posix_error();
7831n/a
7832n/a return result;
7833n/a}
7834n/a
7835n/a
7836n/a/*[clinic input]
7837n/aos.read
7838n/a fd: int
7839n/a length: Py_ssize_t
7840n/a /
7841n/a
7842n/aRead from a file descriptor. Returns a bytes object.
7843n/a[clinic start generated code]*/
7844n/a
7845n/astatic PyObject *
7846n/aos_read_impl(PyObject *module, int fd, Py_ssize_t length)
7847n/a/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
7848n/a{
7849n/a Py_ssize_t n;
7850n/a PyObject *buffer;
7851n/a
7852n/a if (length < 0) {
7853n/a errno = EINVAL;
7854n/a return posix_error();
7855n/a }
7856n/a
7857n/a#ifdef MS_WINDOWS
7858n/a /* On Windows, the count parameter of read() is an int */
7859n/a if (length > INT_MAX)
7860n/a length = INT_MAX;
7861n/a#endif
7862n/a
7863n/a buffer = PyBytes_FromStringAndSize((char *)NULL, length);
7864n/a if (buffer == NULL)
7865n/a return NULL;
7866n/a
7867n/a n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
7868n/a if (n == -1) {
7869n/a Py_DECREF(buffer);
7870n/a return NULL;
7871n/a }
7872n/a
7873n/a if (n != length)
7874n/a _PyBytes_Resize(&buffer, n);
7875n/a
7876n/a return buffer;
7877n/a}
7878n/a
7879n/a#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
7880n/a || defined(__APPLE__))) || defined(HAVE_READV) || defined(HAVE_WRITEV)
7881n/astatic Py_ssize_t
7882n/aiov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type)
7883n/a{
7884n/a int i, j;
7885n/a Py_ssize_t blen, total = 0;
7886n/a
7887n/a *iov = PyMem_New(struct iovec, cnt);
7888n/a if (*iov == NULL) {
7889n/a PyErr_NoMemory();
7890n/a return -1;
7891n/a }
7892n/a
7893n/a *buf = PyMem_New(Py_buffer, cnt);
7894n/a if (*buf == NULL) {
7895n/a PyMem_Del(*iov);
7896n/a PyErr_NoMemory();
7897n/a return -1;
7898n/a }
7899n/a
7900n/a for (i = 0; i < cnt; i++) {
7901n/a PyObject *item = PySequence_GetItem(seq, i);
7902n/a if (item == NULL)
7903n/a goto fail;
7904n/a if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
7905n/a Py_DECREF(item);
7906n/a goto fail;
7907n/a }
7908n/a Py_DECREF(item);
7909n/a (*iov)[i].iov_base = (*buf)[i].buf;
7910n/a blen = (*buf)[i].len;
7911n/a (*iov)[i].iov_len = blen;
7912n/a total += blen;
7913n/a }
7914n/a return total;
7915n/a
7916n/afail:
7917n/a PyMem_Del(*iov);
7918n/a for (j = 0; j < i; j++) {
7919n/a PyBuffer_Release(&(*buf)[j]);
7920n/a }
7921n/a PyMem_Del(*buf);
7922n/a return -1;
7923n/a}
7924n/a
7925n/astatic void
7926n/aiov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
7927n/a{
7928n/a int i;
7929n/a PyMem_Del(iov);
7930n/a for (i = 0; i < cnt; i++) {
7931n/a PyBuffer_Release(&buf[i]);
7932n/a }
7933n/a PyMem_Del(buf);
7934n/a}
7935n/a#endif
7936n/a
7937n/a
7938n/a#ifdef HAVE_READV
7939n/a/*[clinic input]
7940n/aos.readv -> Py_ssize_t
7941n/a
7942n/a fd: int
7943n/a buffers: object
7944n/a /
7945n/a
7946n/aRead from a file descriptor fd into an iterable of buffers.
7947n/a
7948n/aThe buffers should be mutable buffers accepting bytes.
7949n/areadv will transfer data into each buffer until it is full
7950n/aand then move on to the next buffer in the sequence to hold
7951n/athe rest of the data.
7952n/a
7953n/areadv returns the total number of bytes read,
7954n/awhich may be less than the total capacity of all the buffers.
7955n/a[clinic start generated code]*/
7956n/a
7957n/astatic Py_ssize_t
7958n/aos_readv_impl(PyObject *module, int fd, PyObject *buffers)
7959n/a/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
7960n/a{
7961n/a int cnt;
7962n/a Py_ssize_t n;
7963n/a int async_err = 0;
7964n/a struct iovec *iov;
7965n/a Py_buffer *buf;
7966n/a
7967n/a if (!PySequence_Check(buffers)) {
7968n/a PyErr_SetString(PyExc_TypeError,
7969n/a "readv() arg 2 must be a sequence");
7970n/a return -1;
7971n/a }
7972n/a
7973n/a cnt = PySequence_Size(buffers);
7974n/a
7975n/a if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
7976n/a return -1;
7977n/a
7978n/a do {
7979n/a Py_BEGIN_ALLOW_THREADS
7980n/a n = readv(fd, iov, cnt);
7981n/a Py_END_ALLOW_THREADS
7982n/a } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7983n/a
7984n/a iov_cleanup(iov, buf, cnt);
7985n/a if (n < 0) {
7986n/a if (!async_err)
7987n/a posix_error();
7988n/a return -1;
7989n/a }
7990n/a
7991n/a return n;
7992n/a}
7993n/a#endif /* HAVE_READV */
7994n/a
7995n/a
7996n/a#ifdef HAVE_PREAD
7997n/a/*[clinic input]
7998n/a# TODO length should be size_t! but Python doesn't support parsing size_t yet.
7999n/aos.pread
8000n/a
8001n/a fd: int
8002n/a length: int
8003n/a offset: Py_off_t
8004n/a /
8005n/a
8006n/aRead a number of bytes from a file descriptor starting at a particular offset.
8007n/a
8008n/aRead length bytes from file descriptor fd, starting at offset bytes from
8009n/athe beginning of the file. The file offset remains unchanged.
8010n/a[clinic start generated code]*/
8011n/a
8012n/astatic PyObject *
8013n/aos_pread_impl(PyObject *module, int fd, int length, Py_off_t offset)
8014n/a/*[clinic end generated code: output=435b29ee32b54a78 input=084948dcbaa35d4c]*/
8015n/a{
8016n/a Py_ssize_t n;
8017n/a int async_err = 0;
8018n/a PyObject *buffer;
8019n/a
8020n/a if (length < 0) {
8021n/a errno = EINVAL;
8022n/a return posix_error();
8023n/a }
8024n/a buffer = PyBytes_FromStringAndSize((char *)NULL, length);
8025n/a if (buffer == NULL)
8026n/a return NULL;
8027n/a
8028n/a do {
8029n/a Py_BEGIN_ALLOW_THREADS
8030n/a _Py_BEGIN_SUPPRESS_IPH
8031n/a n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
8032n/a _Py_END_SUPPRESS_IPH
8033n/a Py_END_ALLOW_THREADS
8034n/a } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8035n/a
8036n/a if (n < 0) {
8037n/a Py_DECREF(buffer);
8038n/a return (!async_err) ? posix_error() : NULL;
8039n/a }
8040n/a if (n != length)
8041n/a _PyBytes_Resize(&buffer, n);
8042n/a return buffer;
8043n/a}
8044n/a#endif /* HAVE_PREAD */
8045n/a
8046n/a
8047n/a/*[clinic input]
8048n/aos.write -> Py_ssize_t
8049n/a
8050n/a fd: int
8051n/a data: Py_buffer
8052n/a /
8053n/a
8054n/aWrite a bytes object to a file descriptor.
8055n/a[clinic start generated code]*/
8056n/a
8057n/astatic Py_ssize_t
8058n/aos_write_impl(PyObject *module, int fd, Py_buffer *data)
8059n/a/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
8060n/a{
8061n/a return _Py_write(fd, data->buf, data->len);
8062n/a}
8063n/a
8064n/a#ifdef HAVE_SENDFILE
8065n/aPyDoc_STRVAR(posix_sendfile__doc__,
8066n/a"sendfile(out, in, offset, count) -> byteswritten\n\
8067n/asendfile(out, in, offset, count[, headers][, trailers], flags=0)\n\
8068n/a -> byteswritten\n\
8069n/aCopy count bytes from file descriptor in to file descriptor out.");
8070n/a
8071n/a/* AC 3.5: don't bother converting, has optional group*/
8072n/astatic PyObject *
8073n/aposix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
8074n/a{
8075n/a int in, out;
8076n/a Py_ssize_t ret;
8077n/a int async_err = 0;
8078n/a off_t offset;
8079n/a
8080n/a#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
8081n/a#ifndef __APPLE__
8082n/a Py_ssize_t len;
8083n/a#endif
8084n/a PyObject *headers = NULL, *trailers = NULL;
8085n/a Py_buffer *hbuf, *tbuf;
8086n/a off_t sbytes;
8087n/a struct sf_hdtr sf;
8088n/a int flags = 0;
8089n/a /* Beware that "in" clashes with Python's own "in" operator keyword */
8090n/a static char *keywords[] = {"out", "in",
8091n/a "offset", "count",
8092n/a "headers", "trailers", "flags", NULL};
8093n/a
8094n/a sf.headers = NULL;
8095n/a sf.trailers = NULL;
8096n/a
8097n/a#ifdef __APPLE__
8098n/a if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile",
8099n/a keywords, &out, &in, Py_off_t_converter, &offset, Py_off_t_converter, &sbytes,
8100n/a#else
8101n/a if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&n|OOi:sendfile",
8102n/a keywords, &out, &in, Py_off_t_converter, &offset, &len,
8103n/a#endif
8104n/a &headers, &trailers, &flags))
8105n/a return NULL;
8106n/a if (headers != NULL) {
8107n/a if (!PySequence_Check(headers)) {
8108n/a PyErr_SetString(PyExc_TypeError,
8109n/a "sendfile() headers must be a sequence");
8110n/a return NULL;
8111n/a } else {
8112n/a Py_ssize_t i = 0; /* Avoid uninitialized warning */
8113n/a sf.hdr_cnt = PySequence_Size(headers);
8114n/a if (sf.hdr_cnt > 0 &&
8115n/a (i = iov_setup(&(sf.headers), &hbuf,
8116n/a headers, sf.hdr_cnt, PyBUF_SIMPLE)) < 0)
8117n/a return NULL;
8118n/a#ifdef __APPLE__
8119n/a sbytes += i;
8120n/a#endif
8121n/a }
8122n/a }
8123n/a if (trailers != NULL) {
8124n/a if (!PySequence_Check(trailers)) {
8125n/a PyErr_SetString(PyExc_TypeError,
8126n/a "sendfile() trailers must be a sequence");
8127n/a return NULL;
8128n/a } else {
8129n/a Py_ssize_t i = 0; /* Avoid uninitialized warning */
8130n/a sf.trl_cnt = PySequence_Size(trailers);
8131n/a if (sf.trl_cnt > 0 &&
8132n/a (i = iov_setup(&(sf.trailers), &tbuf,
8133n/a trailers, sf.trl_cnt, PyBUF_SIMPLE)) < 0)
8134n/a return NULL;
8135n/a#ifdef __APPLE__
8136n/a sbytes += i;
8137n/a#endif
8138n/a }
8139n/a }
8140n/a
8141n/a _Py_BEGIN_SUPPRESS_IPH
8142n/a do {
8143n/a Py_BEGIN_ALLOW_THREADS
8144n/a#ifdef __APPLE__
8145n/a ret = sendfile(in, out, offset, &sbytes, &sf, flags);
8146n/a#else
8147n/a ret = sendfile(in, out, offset, len, &sf, &sbytes, flags);
8148n/a#endif
8149n/a Py_END_ALLOW_THREADS
8150n/a } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8151n/a _Py_END_SUPPRESS_IPH
8152n/a
8153n/a if (sf.headers != NULL)
8154n/a iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
8155n/a if (sf.trailers != NULL)
8156n/a iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
8157n/a
8158n/a if (ret < 0) {
8159n/a if ((errno == EAGAIN) || (errno == EBUSY)) {
8160n/a if (sbytes != 0) {
8161n/a // some data has been sent
8162n/a goto done;
8163n/a }
8164n/a else {
8165n/a // no data has been sent; upper application is supposed
8166n/a // to retry on EAGAIN or EBUSY
8167n/a return posix_error();
8168n/a }
8169n/a }
8170n/a return (!async_err) ? posix_error() : NULL;
8171n/a }
8172n/a goto done;
8173n/a
8174n/adone:
8175n/a #if !defined(HAVE_LARGEFILE_SUPPORT)
8176n/a return Py_BuildValue("l", sbytes);
8177n/a #else
8178n/a return Py_BuildValue("L", sbytes);
8179n/a #endif
8180n/a
8181n/a#else
8182n/a Py_ssize_t count;
8183n/a PyObject *offobj;
8184n/a static char *keywords[] = {"out", "in",
8185n/a "offset", "count", NULL};
8186n/a if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile",
8187n/a keywords, &out, &in, &offobj, &count))
8188n/a return NULL;
8189n/a#ifdef __linux__
8190n/a if (offobj == Py_None) {
8191n/a do {
8192n/a Py_BEGIN_ALLOW_THREADS
8193n/a ret = sendfile(out, in, NULL, count);
8194n/a Py_END_ALLOW_THREADS
8195n/a } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8196n/a if (ret < 0)
8197n/a return (!async_err) ? posix_error() : NULL;
8198n/a return Py_BuildValue("n", ret);
8199n/a }
8200n/a#endif
8201n/a if (!Py_off_t_converter(offobj, &offset))
8202n/a return NULL;
8203n/a
8204n/a do {
8205n/a Py_BEGIN_ALLOW_THREADS
8206n/a ret = sendfile(out, in, &offset, count);
8207n/a Py_END_ALLOW_THREADS
8208n/a } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8209n/a if (ret < 0)
8210n/a return (!async_err) ? posix_error() : NULL;
8211n/a return Py_BuildValue("n", ret);
8212n/a#endif
8213n/a}
8214n/a#endif /* HAVE_SENDFILE */
8215n/a
8216n/a
8217n/a/*[clinic input]
8218n/aos.fstat
8219n/a
8220n/a fd : int
8221n/a
8222n/aPerform a stat system call on the given file descriptor.
8223n/a
8224n/aLike stat(), but for an open file descriptor.
8225n/aEquivalent to os.stat(fd).
8226n/a[clinic start generated code]*/
8227n/a
8228n/astatic PyObject *
8229n/aos_fstat_impl(PyObject *module, int fd)
8230n/a/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
8231n/a{
8232n/a STRUCT_STAT st;
8233n/a int res;
8234n/a int async_err = 0;
8235n/a
8236n/a do {
8237n/a Py_BEGIN_ALLOW_THREADS
8238n/a res = FSTAT(fd, &st);
8239n/a Py_END_ALLOW_THREADS
8240n/a } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8241n/a if (res != 0) {
8242n/a#ifdef MS_WINDOWS
8243n/a return PyErr_SetFromWindowsErr(0);
8244n/a#else
8245n/a return (!async_err) ? posix_error() : NULL;
8246n/a#endif
8247n/a }
8248n/a
8249n/a return _pystat_fromstructstat(&st);
8250n/a}
8251n/a
8252n/a
8253n/a/*[clinic input]
8254n/aos.isatty -> bool
8255n/a fd: int
8256n/a /
8257n/a
8258n/aReturn True if the fd is connected to a terminal.
8259n/a
8260n/aReturn True if the file descriptor is an open file descriptor
8261n/aconnected to the slave end of a terminal.
8262n/a[clinic start generated code]*/
8263n/a
8264n/astatic int
8265n/aos_isatty_impl(PyObject *module, int fd)
8266n/a/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
8267n/a{
8268n/a int return_value;
8269n/a _Py_BEGIN_SUPPRESS_IPH
8270n/a return_value = isatty(fd);
8271n/a _Py_END_SUPPRESS_IPH
8272n/a return return_value;
8273n/a}
8274n/a
8275n/a
8276n/a#ifdef HAVE_PIPE
8277n/a/*[clinic input]
8278n/aos.pipe
8279n/a
8280n/aCreate a pipe.
8281n/a
8282n/aReturns a tuple of two file descriptors:
8283n/a (read_fd, write_fd)
8284n/a[clinic start generated code]*/
8285n/a
8286n/astatic PyObject *
8287n/aos_pipe_impl(PyObject *module)
8288n/a/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
8289n/a{
8290n/a int fds[2];
8291n/a#ifdef MS_WINDOWS
8292n/a HANDLE read, write;
8293n/a SECURITY_ATTRIBUTES attr;
8294n/a BOOL ok;
8295n/a#else
8296n/a int res;
8297n/a#endif
8298n/a
8299n/a#ifdef MS_WINDOWS
8300n/a attr.nLength = sizeof(attr);
8301n/a attr.lpSecurityDescriptor = NULL;
8302n/a attr.bInheritHandle = FALSE;
8303n/a
8304n/a Py_BEGIN_ALLOW_THREADS
8305n/a _Py_BEGIN_SUPPRESS_IPH
8306n/a ok = CreatePipe(&read, &write, &attr, 0);
8307n/a if (ok) {
8308n/a fds[0] = _open_osfhandle((intptr_t)read, _O_RDONLY);
8309n/a fds[1] = _open_osfhandle((intptr_t)write, _O_WRONLY);
8310n/a if (fds[0] == -1 || fds[1] == -1) {
8311n/a CloseHandle(read);
8312n/a CloseHandle(write);
8313n/a ok = 0;
8314n/a }
8315n/a }
8316n/a _Py_END_SUPPRESS_IPH
8317n/a Py_END_ALLOW_THREADS
8318n/a
8319n/a if (!ok)
8320n/a return PyErr_SetFromWindowsErr(0);
8321n/a#else
8322n/a
8323n/a#ifdef HAVE_PIPE2
8324n/a Py_BEGIN_ALLOW_THREADS
8325n/a res = pipe2(fds, O_CLOEXEC);
8326n/a Py_END_ALLOW_THREADS
8327n/a
8328n/a if (res != 0 && errno == ENOSYS)
8329n/a {
8330n/a#endif
8331n/a Py_BEGIN_ALLOW_THREADS
8332n/a res = pipe(fds);
8333n/a Py_END_ALLOW_THREADS
8334n/a
8335n/a if (res == 0) {
8336n/a if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
8337n/a close(fds[0]);
8338n/a close(fds[1]);
8339n/a return NULL;
8340n/a }
8341n/a if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
8342n/a close(fds[0]);
8343n/a close(fds[1]);
8344n/a return NULL;
8345n/a }
8346n/a }
8347n/a#ifdef HAVE_PIPE2
8348n/a }
8349n/a#endif
8350n/a
8351n/a if (res != 0)
8352n/a return PyErr_SetFromErrno(PyExc_OSError);
8353n/a#endif /* !MS_WINDOWS */
8354n/a return Py_BuildValue("(ii)", fds[0], fds[1]);
8355n/a}
8356n/a#endif /* HAVE_PIPE */
8357n/a
8358n/a
8359n/a#ifdef HAVE_PIPE2
8360n/a/*[clinic input]
8361n/aos.pipe2
8362n/a
8363n/a flags: int
8364n/a /
8365n/a
8366n/aCreate a pipe with flags set atomically.
8367n/a
8368n/aReturns a tuple of two file descriptors:
8369n/a (read_fd, write_fd)
8370n/a
8371n/aflags can be constructed by ORing together one or more of these values:
8372n/aO_NONBLOCK, O_CLOEXEC.
8373n/a[clinic start generated code]*/
8374n/a
8375n/astatic PyObject *
8376n/aos_pipe2_impl(PyObject *module, int flags)
8377n/a/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
8378n/a{
8379n/a int fds[2];
8380n/a int res;
8381n/a
8382n/a res = pipe2(fds, flags);
8383n/a if (res != 0)
8384n/a return posix_error();
8385n/a return Py_BuildValue("(ii)", fds[0], fds[1]);
8386n/a}
8387n/a#endif /* HAVE_PIPE2 */
8388n/a
8389n/a
8390n/a#ifdef HAVE_WRITEV
8391n/a/*[clinic input]
8392n/aos.writev -> Py_ssize_t
8393n/a fd: int
8394n/a buffers: object
8395n/a /
8396n/a
8397n/aIterate over buffers, and write the contents of each to a file descriptor.
8398n/a
8399n/aReturns the total number of bytes written.
8400n/abuffers must be a sequence of bytes-like objects.
8401n/a[clinic start generated code]*/
8402n/a
8403n/astatic Py_ssize_t
8404n/aos_writev_impl(PyObject *module, int fd, PyObject *buffers)
8405n/a/*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
8406n/a{
8407n/a int cnt;
8408n/a Py_ssize_t result;
8409n/a int async_err = 0;
8410n/a struct iovec *iov;
8411n/a Py_buffer *buf;
8412n/a
8413n/a if (!PySequence_Check(buffers)) {
8414n/a PyErr_SetString(PyExc_TypeError,
8415n/a "writev() arg 2 must be a sequence");
8416n/a return -1;
8417n/a }
8418n/a cnt = PySequence_Size(buffers);
8419n/a
8420n/a if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
8421n/a return -1;
8422n/a }
8423n/a
8424n/a do {
8425n/a Py_BEGIN_ALLOW_THREADS
8426n/a result = writev(fd, iov, cnt);
8427n/a Py_END_ALLOW_THREADS
8428n/a } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8429n/a
8430n/a iov_cleanup(iov, buf, cnt);
8431n/a if (result < 0 && !async_err)
8432n/a posix_error();
8433n/a
8434n/a return result;
8435n/a}
8436n/a#endif /* HAVE_WRITEV */
8437n/a
8438n/a
8439n/a#ifdef HAVE_PWRITE
8440n/a/*[clinic input]
8441n/aos.pwrite -> Py_ssize_t
8442n/a
8443n/a fd: int
8444n/a buffer: Py_buffer
8445n/a offset: Py_off_t
8446n/a /
8447n/a
8448n/aWrite bytes to a file descriptor starting at a particular offset.
8449n/a
8450n/aWrite buffer to fd, starting at offset bytes from the beginning of
8451n/athe file. Returns the number of bytes writte. Does not change the
8452n/acurrent file offset.
8453n/a[clinic start generated code]*/
8454n/a
8455n/astatic Py_ssize_t
8456n/aos_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
8457n/a/*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
8458n/a{
8459n/a Py_ssize_t size;
8460n/a int async_err = 0;
8461n/a
8462n/a do {
8463n/a Py_BEGIN_ALLOW_THREADS
8464n/a _Py_BEGIN_SUPPRESS_IPH
8465n/a size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
8466n/a _Py_END_SUPPRESS_IPH
8467n/a Py_END_ALLOW_THREADS
8468n/a } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8469n/a
8470n/a if (size < 0 && !async_err)
8471n/a posix_error();
8472n/a return size;
8473n/a}
8474n/a#endif /* HAVE_PWRITE */
8475n/a
8476n/a
8477n/a#ifdef HAVE_MKFIFO
8478n/a/*[clinic input]
8479n/aos.mkfifo
8480n/a
8481n/a path: path_t
8482n/a mode: int=0o666
8483n/a *
8484n/a dir_fd: dir_fd(requires='mkfifoat')=None
8485n/a
8486n/aCreate a "fifo" (a POSIX named pipe).
8487n/a
8488n/aIf dir_fd is not None, it should be a file descriptor open to a directory,
8489n/a and path should be relative; path will then be relative to that directory.
8490n/adir_fd may not be implemented on your platform.
8491n/a If it is unavailable, using it will raise a NotImplementedError.
8492n/a[clinic start generated code]*/
8493n/a
8494n/astatic PyObject *
8495n/aos_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
8496n/a/*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
8497n/a{
8498n/a int result;
8499n/a int async_err = 0;
8500n/a
8501n/a do {
8502n/a Py_BEGIN_ALLOW_THREADS
8503n/a#ifdef HAVE_MKFIFOAT
8504n/a if (dir_fd != DEFAULT_DIR_FD)
8505n/a result = mkfifoat(dir_fd, path->narrow, mode);
8506n/a else
8507n/a#endif
8508n/a result = mkfifo(path->narrow, mode);
8509n/a Py_END_ALLOW_THREADS
8510n/a } while (result != 0 && errno == EINTR &&
8511n/a !(async_err = PyErr_CheckSignals()));
8512n/a if (result != 0)
8513n/a return (!async_err) ? posix_error() : NULL;
8514n/a
8515n/a Py_RETURN_NONE;
8516n/a}
8517n/a#endif /* HAVE_MKFIFO */
8518n/a
8519n/a
8520n/a#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
8521n/a/*[clinic input]
8522n/aos.mknod
8523n/a
8524n/a path: path_t
8525n/a mode: int=0o600
8526n/a device: dev_t=0
8527n/a *
8528n/a dir_fd: dir_fd(requires='mknodat')=None
8529n/a
8530n/aCreate a node in the file system.
8531n/a
8532n/aCreate a node in the file system (file, device special file or named pipe)
8533n/aat path. mode specifies both the permissions to use and the
8534n/atype of node to be created, being combined (bitwise OR) with one of
8535n/aS_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode,
8536n/adevice defines the newly created device special file (probably using
8537n/aos.makedev()). Otherwise device is ignored.
8538n/a
8539n/aIf dir_fd is not None, it should be a file descriptor open to a directory,
8540n/a and path should be relative; path will then be relative to that directory.
8541n/adir_fd may not be implemented on your platform.
8542n/a If it is unavailable, using it will raise a NotImplementedError.
8543n/a[clinic start generated code]*/
8544n/a
8545n/astatic PyObject *
8546n/aos_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
8547n/a int dir_fd)
8548n/a/*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
8549n/a{
8550n/a int result;
8551n/a int async_err = 0;
8552n/a
8553n/a do {
8554n/a Py_BEGIN_ALLOW_THREADS
8555n/a#ifdef HAVE_MKNODAT
8556n/a if (dir_fd != DEFAULT_DIR_FD)
8557n/a result = mknodat(dir_fd, path->narrow, mode, device);
8558n/a else
8559n/a#endif
8560n/a result = mknod(path->narrow, mode, device);
8561n/a Py_END_ALLOW_THREADS
8562n/a } while (result != 0 && errno == EINTR &&
8563n/a !(async_err = PyErr_CheckSignals()));
8564n/a if (result != 0)
8565n/a return (!async_err) ? posix_error() : NULL;
8566n/a
8567n/a Py_RETURN_NONE;
8568n/a}
8569n/a#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
8570n/a
8571n/a
8572n/a#ifdef HAVE_DEVICE_MACROS
8573n/a/*[clinic input]
8574n/aos.major -> unsigned_int
8575n/a
8576n/a device: dev_t
8577n/a /
8578n/a
8579n/aExtracts a device major number from a raw device number.
8580n/a[clinic start generated code]*/
8581n/a
8582n/astatic unsigned int
8583n/aos_major_impl(PyObject *module, dev_t device)
8584n/a/*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
8585n/a{
8586n/a return major(device);
8587n/a}
8588n/a
8589n/a
8590n/a/*[clinic input]
8591n/aos.minor -> unsigned_int
8592n/a
8593n/a device: dev_t
8594n/a /
8595n/a
8596n/aExtracts a device minor number from a raw device number.
8597n/a[clinic start generated code]*/
8598n/a
8599n/astatic unsigned int
8600n/aos_minor_impl(PyObject *module, dev_t device)
8601n/a/*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
8602n/a{
8603n/a return minor(device);
8604n/a}
8605n/a
8606n/a
8607n/a/*[clinic input]
8608n/aos.makedev -> dev_t
8609n/a
8610n/a major: int
8611n/a minor: int
8612n/a /
8613n/a
8614n/aComposes a raw device number from the major and minor device numbers.
8615n/a[clinic start generated code]*/
8616n/a
8617n/astatic dev_t
8618n/aos_makedev_impl(PyObject *module, int major, int minor)
8619n/a/*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
8620n/a{
8621n/a return makedev(major, minor);
8622n/a}
8623n/a#endif /* HAVE_DEVICE_MACROS */
8624n/a
8625n/a
8626n/a#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
8627n/a/*[clinic input]
8628n/aos.ftruncate
8629n/a
8630n/a fd: int
8631n/a length: Py_off_t
8632n/a /
8633n/a
8634n/aTruncate a file, specified by file descriptor, to a specific length.
8635n/a[clinic start generated code]*/
8636n/a
8637n/astatic PyObject *
8638n/aos_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
8639n/a/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
8640n/a{
8641n/a int result;
8642n/a int async_err = 0;
8643n/a
8644n/a do {
8645n/a Py_BEGIN_ALLOW_THREADS
8646n/a _Py_BEGIN_SUPPRESS_IPH
8647n/a#ifdef MS_WINDOWS
8648n/a result = _chsize_s(fd, length);
8649n/a#else
8650n/a result = ftruncate(fd, length);
8651n/a#endif
8652n/a _Py_END_SUPPRESS_IPH
8653n/a Py_END_ALLOW_THREADS
8654n/a } while (result != 0 && errno == EINTR &&
8655n/a !(async_err = PyErr_CheckSignals()));
8656n/a if (result != 0)
8657n/a return (!async_err) ? posix_error() : NULL;
8658n/a Py_RETURN_NONE;
8659n/a}
8660n/a#endif /* HAVE_FTRUNCATE || MS_WINDOWS */
8661n/a
8662n/a
8663n/a#if defined HAVE_TRUNCATE || defined MS_WINDOWS
8664n/a/*[clinic input]
8665n/aos.truncate
8666n/a path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
8667n/a length: Py_off_t
8668n/a
8669n/aTruncate a file, specified by path, to a specific length.
8670n/a
8671n/aOn some platforms, path may also be specified as an open file descriptor.
8672n/a If this functionality is unavailable, using it raises an exception.
8673n/a[clinic start generated code]*/
8674n/a
8675n/astatic PyObject *
8676n/aos_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
8677n/a/*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
8678n/a{
8679n/a int result;
8680n/a#ifdef MS_WINDOWS
8681n/a int fd;
8682n/a#endif
8683n/a
8684n/a if (path->fd != -1)
8685n/a return os_ftruncate_impl(module, path->fd, length);
8686n/a
8687n/a Py_BEGIN_ALLOW_THREADS
8688n/a _Py_BEGIN_SUPPRESS_IPH
8689n/a#ifdef MS_WINDOWS
8690n/a fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
8691n/a if (fd < 0)
8692n/a result = -1;
8693n/a else {
8694n/a result = _chsize_s(fd, length);
8695n/a close(fd);
8696n/a if (result < 0)
8697n/a errno = result;
8698n/a }
8699n/a#else
8700n/a result = truncate(path->narrow, length);
8701n/a#endif
8702n/a _Py_END_SUPPRESS_IPH
8703n/a Py_END_ALLOW_THREADS
8704n/a if (result < 0)
8705n/a return path_error(path);
8706n/a
8707n/a Py_RETURN_NONE;
8708n/a}
8709n/a#endif /* HAVE_TRUNCATE || MS_WINDOWS */
8710n/a
8711n/a
8712n/a/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
8713n/a and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
8714n/a defined, which is the case in Python on AIX. AIX bug report:
8715n/a http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
8716n/a#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
8717n/a# define POSIX_FADVISE_AIX_BUG
8718n/a#endif
8719n/a
8720n/a
8721n/a#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
8722n/a/*[clinic input]
8723n/aos.posix_fallocate
8724n/a
8725n/a fd: int
8726n/a offset: Py_off_t
8727n/a length: Py_off_t
8728n/a /
8729n/a
8730n/aEnsure a file has allocated at least a particular number of bytes on disk.
8731n/a
8732n/aEnsure that the file specified by fd encompasses a range of bytes
8733n/astarting at offset bytes from the beginning and continuing for length bytes.
8734n/a[clinic start generated code]*/
8735n/a
8736n/astatic PyObject *
8737n/aos_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
8738n/a Py_off_t length)
8739n/a/*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
8740n/a{
8741n/a int result;
8742n/a int async_err = 0;
8743n/a
8744n/a do {
8745n/a Py_BEGIN_ALLOW_THREADS
8746n/a result = posix_fallocate(fd, offset, length);
8747n/a Py_END_ALLOW_THREADS
8748n/a } while (result != 0 && errno == EINTR &&
8749n/a !(async_err = PyErr_CheckSignals()));
8750n/a if (result != 0)
8751n/a return (!async_err) ? posix_error() : NULL;
8752n/a Py_RETURN_NONE;
8753n/a}
8754n/a#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
8755n/a
8756n/a
8757n/a#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
8758n/a/*[clinic input]
8759n/aos.posix_fadvise
8760n/a
8761n/a fd: int
8762n/a offset: Py_off_t
8763n/a length: Py_off_t
8764n/a advice: int
8765n/a /
8766n/a
8767n/aAnnounce an intention to access data in a specific pattern.
8768n/a
8769n/aAnnounce an intention to access data in a specific pattern, thus allowing
8770n/athe kernel to make optimizations.
8771n/aThe advice applies to the region of the file specified by fd starting at
8772n/aoffset and continuing for length bytes.
8773n/aadvice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
8774n/aPOSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
8775n/aPOSIX_FADV_DONTNEED.
8776n/a[clinic start generated code]*/
8777n/a
8778n/astatic PyObject *
8779n/aos_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
8780n/a Py_off_t length, int advice)
8781n/a/*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
8782n/a{
8783n/a int result;
8784n/a int async_err = 0;
8785n/a
8786n/a do {
8787n/a Py_BEGIN_ALLOW_THREADS
8788n/a result = posix_fadvise(fd, offset, length, advice);
8789n/a Py_END_ALLOW_THREADS
8790n/a } while (result != 0 && errno == EINTR &&
8791n/a !(async_err = PyErr_CheckSignals()));
8792n/a if (result != 0)
8793n/a return (!async_err) ? posix_error() : NULL;
8794n/a Py_RETURN_NONE;
8795n/a}
8796n/a#endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
8797n/a
8798n/a#ifdef HAVE_PUTENV
8799n/a
8800n/a/* Save putenv() parameters as values here, so we can collect them when they
8801n/a * get re-set with another call for the same key. */
8802n/astatic PyObject *posix_putenv_garbage;
8803n/a
8804n/astatic void
8805n/aposix_putenv_garbage_setitem(PyObject *name, PyObject *value)
8806n/a{
8807n/a /* Install the first arg and newstr in posix_putenv_garbage;
8808n/a * this will cause previous value to be collected. This has to
8809n/a * happen after the real putenv() call because the old value
8810n/a * was still accessible until then. */
8811n/a if (PyDict_SetItem(posix_putenv_garbage, name, value))
8812n/a /* really not much we can do; just leak */
8813n/a PyErr_Clear();
8814n/a else
8815n/a Py_DECREF(value);
8816n/a}
8817n/a
8818n/a
8819n/a#ifdef MS_WINDOWS
8820n/a/*[clinic input]
8821n/aos.putenv
8822n/a
8823n/a name: unicode
8824n/a value: unicode
8825n/a /
8826n/a
8827n/aChange or add an environment variable.
8828n/a[clinic start generated code]*/
8829n/a
8830n/astatic PyObject *
8831n/aos_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
8832n/a/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
8833n/a{
8834n/a const wchar_t *env;
8835n/a
8836n/a PyObject *unicode = PyUnicode_FromFormat("%U=%U", name, value);
8837n/a if (unicode == NULL) {
8838n/a PyErr_NoMemory();
8839n/a return NULL;
8840n/a }
8841n/a if (_MAX_ENV < PyUnicode_GET_LENGTH(unicode)) {
8842n/a PyErr_Format(PyExc_ValueError,
8843n/a "the environment variable is longer than %u characters",
8844n/a _MAX_ENV);
8845n/a goto error;
8846n/a }
8847n/a
8848n/a env = PyUnicode_AsUnicode(unicode);
8849n/a if (env == NULL)
8850n/a goto error;
8851n/a if (_wputenv(env)) {
8852n/a posix_error();
8853n/a goto error;
8854n/a }
8855n/a
8856n/a posix_putenv_garbage_setitem(name, unicode);
8857n/a Py_RETURN_NONE;
8858n/a
8859n/aerror:
8860n/a Py_DECREF(unicode);
8861n/a return NULL;
8862n/a}
8863n/a#else /* MS_WINDOWS */
8864n/a/*[clinic input]
8865n/aos.putenv
8866n/a
8867n/a name: FSConverter
8868n/a value: FSConverter
8869n/a /
8870n/a
8871n/aChange or add an environment variable.
8872n/a[clinic start generated code]*/
8873n/a
8874n/astatic PyObject *
8875n/aos_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
8876n/a/*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
8877n/a{
8878n/a PyObject *bytes = NULL;
8879n/a char *env;
8880n/a const char *name_string = PyBytes_AsString(name);
8881n/a const char *value_string = PyBytes_AsString(value);
8882n/a
8883n/a bytes = PyBytes_FromFormat("%s=%s", name_string, value_string);
8884n/a if (bytes == NULL) {
8885n/a PyErr_NoMemory();
8886n/a return NULL;
8887n/a }
8888n/a
8889n/a env = PyBytes_AS_STRING(bytes);
8890n/a if (putenv(env)) {
8891n/a Py_DECREF(bytes);
8892n/a return posix_error();
8893n/a }
8894n/a
8895n/a posix_putenv_garbage_setitem(name, bytes);
8896n/a Py_RETURN_NONE;
8897n/a}
8898n/a#endif /* MS_WINDOWS */
8899n/a#endif /* HAVE_PUTENV */
8900n/a
8901n/a
8902n/a#ifdef HAVE_UNSETENV
8903n/a/*[clinic input]
8904n/aos.unsetenv
8905n/a name: FSConverter
8906n/a /
8907n/a
8908n/aDelete an environment variable.
8909n/a[clinic start generated code]*/
8910n/a
8911n/astatic PyObject *
8912n/aos_unsetenv_impl(PyObject *module, PyObject *name)
8913n/a/*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
8914n/a{
8915n/a#ifndef HAVE_BROKEN_UNSETENV
8916n/a int err;
8917n/a#endif
8918n/a
8919n/a#ifdef HAVE_BROKEN_UNSETENV
8920n/a unsetenv(PyBytes_AS_STRING(name));
8921n/a#else
8922n/a err = unsetenv(PyBytes_AS_STRING(name));
8923n/a if (err)
8924n/a return posix_error();
8925n/a#endif
8926n/a
8927n/a /* Remove the key from posix_putenv_garbage;
8928n/a * this will cause it to be collected. This has to
8929n/a * happen after the real unsetenv() call because the
8930n/a * old value was still accessible until then.
8931n/a */
8932n/a if (PyDict_DelItem(posix_putenv_garbage, name)) {
8933n/a /* really not much we can do; just leak */
8934n/a PyErr_Clear();
8935n/a }
8936n/a Py_RETURN_NONE;
8937n/a}
8938n/a#endif /* HAVE_UNSETENV */
8939n/a
8940n/a
8941n/a/*[clinic input]
8942n/aos.strerror
8943n/a
8944n/a code: int
8945n/a /
8946n/a
8947n/aTranslate an error code to a message string.
8948n/a[clinic start generated code]*/
8949n/a
8950n/astatic PyObject *
8951n/aos_strerror_impl(PyObject *module, int code)
8952n/a/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
8953n/a{
8954n/a char *message = strerror(code);
8955n/a if (message == NULL) {
8956n/a PyErr_SetString(PyExc_ValueError,
8957n/a "strerror() argument out of range");
8958n/a return NULL;
8959n/a }
8960n/a return PyUnicode_DecodeLocale(message, "surrogateescape");
8961n/a}
8962n/a
8963n/a
8964n/a#ifdef HAVE_SYS_WAIT_H
8965n/a#ifdef WCOREDUMP
8966n/a/*[clinic input]
8967n/aos.WCOREDUMP -> bool
8968n/a
8969n/a status: int
8970n/a /
8971n/a
8972n/aReturn True if the process returning status was dumped to a core file.
8973n/a[clinic start generated code]*/
8974n/a
8975n/astatic int
8976n/aos_WCOREDUMP_impl(PyObject *module, int status)
8977n/a/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
8978n/a{
8979n/a WAIT_TYPE wait_status;
8980n/a WAIT_STATUS_INT(wait_status) = status;
8981n/a return WCOREDUMP(wait_status);
8982n/a}
8983n/a#endif /* WCOREDUMP */
8984n/a
8985n/a
8986n/a#ifdef WIFCONTINUED
8987n/a/*[clinic input]
8988n/aos.WIFCONTINUED -> bool
8989n/a
8990n/a status: int
8991n/a
8992n/aReturn True if a particular process was continued from a job control stop.
8993n/a
8994n/aReturn True if the process returning status was continued from a
8995n/ajob control stop.
8996n/a[clinic start generated code]*/
8997n/a
8998n/astatic int
8999n/aos_WIFCONTINUED_impl(PyObject *module, int status)
9000n/a/*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
9001n/a{
9002n/a WAIT_TYPE wait_status;
9003n/a WAIT_STATUS_INT(wait_status) = status;
9004n/a return WIFCONTINUED(wait_status);
9005n/a}
9006n/a#endif /* WIFCONTINUED */
9007n/a
9008n/a
9009n/a#ifdef WIFSTOPPED
9010n/a/*[clinic input]
9011n/aos.WIFSTOPPED -> bool
9012n/a
9013n/a status: int
9014n/a
9015n/aReturn True if the process returning status was stopped.
9016n/a[clinic start generated code]*/
9017n/a
9018n/astatic int
9019n/aos_WIFSTOPPED_impl(PyObject *module, int status)
9020n/a/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
9021n/a{
9022n/a WAIT_TYPE wait_status;
9023n/a WAIT_STATUS_INT(wait_status) = status;
9024n/a return WIFSTOPPED(wait_status);
9025n/a}
9026n/a#endif /* WIFSTOPPED */
9027n/a
9028n/a
9029n/a#ifdef WIFSIGNALED
9030n/a/*[clinic input]
9031n/aos.WIFSIGNALED -> bool
9032n/a
9033n/a status: int
9034n/a
9035n/aReturn True if the process returning status was terminated by a signal.
9036n/a[clinic start generated code]*/
9037n/a
9038n/astatic int
9039n/aos_WIFSIGNALED_impl(PyObject *module, int status)
9040n/a/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
9041n/a{
9042n/a WAIT_TYPE wait_status;
9043n/a WAIT_STATUS_INT(wait_status) = status;
9044n/a return WIFSIGNALED(wait_status);
9045n/a}
9046n/a#endif /* WIFSIGNALED */
9047n/a
9048n/a
9049n/a#ifdef WIFEXITED
9050n/a/*[clinic input]
9051n/aos.WIFEXITED -> bool
9052n/a
9053n/a status: int
9054n/a
9055n/aReturn True if the process returning status exited via the exit() system call.
9056n/a[clinic start generated code]*/
9057n/a
9058n/astatic int
9059n/aos_WIFEXITED_impl(PyObject *module, int status)
9060n/a/*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
9061n/a{
9062n/a WAIT_TYPE wait_status;
9063n/a WAIT_STATUS_INT(wait_status) = status;
9064n/a return WIFEXITED(wait_status);
9065n/a}
9066n/a#endif /* WIFEXITED */
9067n/a
9068n/a
9069n/a#ifdef WEXITSTATUS
9070n/a/*[clinic input]
9071n/aos.WEXITSTATUS -> int
9072n/a
9073n/a status: int
9074n/a
9075n/aReturn the process return code from status.
9076n/a[clinic start generated code]*/
9077n/a
9078n/astatic int
9079n/aos_WEXITSTATUS_impl(PyObject *module, int status)
9080n/a/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
9081n/a{
9082n/a WAIT_TYPE wait_status;
9083n/a WAIT_STATUS_INT(wait_status) = status;
9084n/a return WEXITSTATUS(wait_status);
9085n/a}
9086n/a#endif /* WEXITSTATUS */
9087n/a
9088n/a
9089n/a#ifdef WTERMSIG
9090n/a/*[clinic input]
9091n/aos.WTERMSIG -> int
9092n/a
9093n/a status: int
9094n/a
9095n/aReturn the signal that terminated the process that provided the status value.
9096n/a[clinic start generated code]*/
9097n/a
9098n/astatic int
9099n/aos_WTERMSIG_impl(PyObject *module, int status)
9100n/a/*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
9101n/a{
9102n/a WAIT_TYPE wait_status;
9103n/a WAIT_STATUS_INT(wait_status) = status;
9104n/a return WTERMSIG(wait_status);
9105n/a}
9106n/a#endif /* WTERMSIG */
9107n/a
9108n/a
9109n/a#ifdef WSTOPSIG
9110n/a/*[clinic input]
9111n/aos.WSTOPSIG -> int
9112n/a
9113n/a status: int
9114n/a
9115n/aReturn the signal that stopped the process that provided the status value.
9116n/a[clinic start generated code]*/
9117n/a
9118n/astatic int
9119n/aos_WSTOPSIG_impl(PyObject *module, int status)
9120n/a/*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
9121n/a{
9122n/a WAIT_TYPE wait_status;
9123n/a WAIT_STATUS_INT(wait_status) = status;
9124n/a return WSTOPSIG(wait_status);
9125n/a}
9126n/a#endif /* WSTOPSIG */
9127n/a#endif /* HAVE_SYS_WAIT_H */
9128n/a
9129n/a
9130n/a#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
9131n/a#ifdef _SCO_DS
9132n/a/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
9133n/a needed definitions in sys/statvfs.h */
9134n/a#define _SVID3
9135n/a#endif
9136n/a#include <sys/statvfs.h>
9137n/a
9138n/astatic PyObject*
9139n/a_pystatvfs_fromstructstatvfs(struct statvfs st) {
9140n/a PyObject *v = PyStructSequence_New(&StatVFSResultType);
9141n/a if (v == NULL)
9142n/a return NULL;
9143n/a
9144n/a#if !defined(HAVE_LARGEFILE_SUPPORT)
9145n/a PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
9146n/a PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
9147n/a PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
9148n/a PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
9149n/a PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
9150n/a PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
9151n/a PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
9152n/a PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
9153n/a PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
9154n/a PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
9155n/a#else
9156n/a PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
9157n/a PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
9158n/a PyStructSequence_SET_ITEM(v, 2,
9159n/a PyLong_FromLongLong((long long) st.f_blocks));
9160n/a PyStructSequence_SET_ITEM(v, 3,
9161n/a PyLong_FromLongLong((long long) st.f_bfree));
9162n/a PyStructSequence_SET_ITEM(v, 4,
9163n/a PyLong_FromLongLong((long long) st.f_bavail));
9164n/a PyStructSequence_SET_ITEM(v, 5,
9165n/a PyLong_FromLongLong((long long) st.f_files));
9166n/a PyStructSequence_SET_ITEM(v, 6,
9167n/a PyLong_FromLongLong((long long) st.f_ffree));
9168n/a PyStructSequence_SET_ITEM(v, 7,
9169n/a PyLong_FromLongLong((long long) st.f_favail));
9170n/a PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
9171n/a PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
9172n/a#endif
9173n/a if (PyErr_Occurred()) {
9174n/a Py_DECREF(v);
9175n/a return NULL;
9176n/a }
9177n/a
9178n/a return v;
9179n/a}
9180n/a
9181n/a
9182n/a/*[clinic input]
9183n/aos.fstatvfs
9184n/a fd: int
9185n/a /
9186n/a
9187n/aPerform an fstatvfs system call on the given fd.
9188n/a
9189n/aEquivalent to statvfs(fd).
9190n/a[clinic start generated code]*/
9191n/a
9192n/astatic PyObject *
9193n/aos_fstatvfs_impl(PyObject *module, int fd)
9194n/a/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
9195n/a{
9196n/a int result;
9197n/a int async_err = 0;
9198n/a struct statvfs st;
9199n/a
9200n/a do {
9201n/a Py_BEGIN_ALLOW_THREADS
9202n/a result = fstatvfs(fd, &st);
9203n/a Py_END_ALLOW_THREADS
9204n/a } while (result != 0 && errno == EINTR &&
9205n/a !(async_err = PyErr_CheckSignals()));
9206n/a if (result != 0)
9207n/a return (!async_err) ? posix_error() : NULL;
9208n/a
9209n/a return _pystatvfs_fromstructstatvfs(st);
9210n/a}
9211n/a#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
9212n/a
9213n/a
9214n/a#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
9215n/a#include <sys/statvfs.h>
9216n/a/*[clinic input]
9217n/aos.statvfs
9218n/a
9219n/a path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
9220n/a
9221n/aPerform a statvfs system call on the given path.
9222n/a
9223n/apath may always be specified as a string.
9224n/aOn some platforms, path may also be specified as an open file descriptor.
9225n/a If this functionality is unavailable, using it raises an exception.
9226n/a[clinic start generated code]*/
9227n/a
9228n/astatic PyObject *
9229n/aos_statvfs_impl(PyObject *module, path_t *path)
9230n/a/*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
9231n/a{
9232n/a int result;
9233n/a struct statvfs st;
9234n/a
9235n/a Py_BEGIN_ALLOW_THREADS
9236n/a#ifdef HAVE_FSTATVFS
9237n/a if (path->fd != -1) {
9238n/a#ifdef __APPLE__
9239n/a /* handle weak-linking on Mac OS X 10.3 */
9240n/a if (fstatvfs == NULL) {
9241n/a fd_specified("statvfs", path->fd);
9242n/a return NULL;
9243n/a }
9244n/a#endif
9245n/a result = fstatvfs(path->fd, &st);
9246n/a }
9247n/a else
9248n/a#endif
9249n/a result = statvfs(path->narrow, &st);
9250n/a Py_END_ALLOW_THREADS
9251n/a
9252n/a if (result) {
9253n/a return path_error(path);
9254n/a }
9255n/a
9256n/a return _pystatvfs_fromstructstatvfs(st);
9257n/a}
9258n/a#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
9259n/a
9260n/a
9261n/a#ifdef MS_WINDOWS
9262n/a/*[clinic input]
9263n/aos._getdiskusage
9264n/a
9265n/a path: Py_UNICODE
9266n/a
9267n/aReturn disk usage statistics about the given path as a (total, free) tuple.
9268n/a[clinic start generated code]*/
9269n/a
9270n/astatic PyObject *
9271n/aos__getdiskusage_impl(PyObject *module, Py_UNICODE *path)
9272n/a/*[clinic end generated code: output=76d6adcd86b1db0b input=6458133aed893c78]*/
9273n/a{
9274n/a BOOL retval;
9275n/a ULARGE_INTEGER _, total, free;
9276n/a
9277n/a Py_BEGIN_ALLOW_THREADS
9278n/a retval = GetDiskFreeSpaceExW(path, &_, &total, &free);
9279n/a Py_END_ALLOW_THREADS
9280n/a if (retval == 0)
9281n/a return PyErr_SetFromWindowsErr(0);
9282n/a
9283n/a return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
9284n/a}
9285n/a#endif /* MS_WINDOWS */
9286n/a
9287n/a
9288n/a/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
9289n/a * It maps strings representing configuration variable names to
9290n/a * integer values, allowing those functions to be called with the
9291n/a * magic names instead of polluting the module's namespace with tons of
9292n/a * rarely-used constants. There are three separate tables that use
9293n/a * these definitions.
9294n/a *
9295n/a * This code is always included, even if none of the interfaces that
9296n/a * need it are included. The #if hackery needed to avoid it would be
9297n/a * sufficiently pervasive that it's not worth the loss of readability.
9298n/a */
9299n/astruct constdef {
9300n/a const char *name;
9301n/a int value;
9302n/a};
9303n/a
9304n/astatic int
9305n/aconv_confname(PyObject *arg, int *valuep, struct constdef *table,
9306n/a size_t tablesize)
9307n/a{
9308n/a if (PyLong_Check(arg)) {
9309n/a int value = _PyLong_AsInt(arg);
9310n/a if (value == -1 && PyErr_Occurred())
9311n/a return 0;
9312n/a *valuep = value;
9313n/a return 1;
9314n/a }
9315n/a else {
9316n/a /* look up the value in the table using a binary search */
9317n/a size_t lo = 0;
9318n/a size_t mid;
9319n/a size_t hi = tablesize;
9320n/a int cmp;
9321n/a const char *confname;
9322n/a if (!PyUnicode_Check(arg)) {
9323n/a PyErr_SetString(PyExc_TypeError,
9324n/a "configuration names must be strings or integers");
9325n/a return 0;
9326n/a }
9327n/a confname = PyUnicode_AsUTF8(arg);
9328n/a if (confname == NULL)
9329n/a return 0;
9330n/a while (lo < hi) {
9331n/a mid = (lo + hi) / 2;
9332n/a cmp = strcmp(confname, table[mid].name);
9333n/a if (cmp < 0)
9334n/a hi = mid;
9335n/a else if (cmp > 0)
9336n/a lo = mid + 1;
9337n/a else {
9338n/a *valuep = table[mid].value;
9339n/a return 1;
9340n/a }
9341n/a }
9342n/a PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
9343n/a return 0;
9344n/a }
9345n/a}
9346n/a
9347n/a
9348n/a#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
9349n/astatic struct constdef posix_constants_pathconf[] = {
9350n/a#ifdef _PC_ABI_AIO_XFER_MAX
9351n/a {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX},
9352n/a#endif
9353n/a#ifdef _PC_ABI_ASYNC_IO
9354n/a {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
9355n/a#endif
9356n/a#ifdef _PC_ASYNC_IO
9357n/a {"PC_ASYNC_IO", _PC_ASYNC_IO},
9358n/a#endif
9359n/a#ifdef _PC_CHOWN_RESTRICTED
9360n/a {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED},
9361n/a#endif
9362n/a#ifdef _PC_FILESIZEBITS
9363n/a {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
9364n/a#endif
9365n/a#ifdef _PC_LAST
9366n/a {"PC_LAST", _PC_LAST},
9367n/a#endif
9368n/a#ifdef _PC_LINK_MAX
9369n/a {"PC_LINK_MAX", _PC_LINK_MAX},
9370n/a#endif
9371n/a#ifdef _PC_MAX_CANON
9372n/a {"PC_MAX_CANON", _PC_MAX_CANON},
9373n/a#endif
9374n/a#ifdef _PC_MAX_INPUT
9375n/a {"PC_MAX_INPUT", _PC_MAX_INPUT},
9376n/a#endif
9377n/a#ifdef _PC_NAME_MAX
9378n/a {"PC_NAME_MAX", _PC_NAME_MAX},
9379n/a#endif
9380n/a#ifdef _PC_NO_TRUNC
9381n/a {"PC_NO_TRUNC", _PC_NO_TRUNC},
9382n/a#endif
9383n/a#ifdef _PC_PATH_MAX
9384n/a {"PC_PATH_MAX", _PC_PATH_MAX},
9385n/a#endif
9386n/a#ifdef _PC_PIPE_BUF
9387n/a {"PC_PIPE_BUF", _PC_PIPE_BUF},
9388n/a#endif
9389n/a#ifdef _PC_PRIO_IO
9390n/a {"PC_PRIO_IO", _PC_PRIO_IO},
9391n/a#endif
9392n/a#ifdef _PC_SOCK_MAXBUF
9393n/a {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF},
9394n/a#endif
9395n/a#ifdef _PC_SYNC_IO
9396n/a {"PC_SYNC_IO", _PC_SYNC_IO},
9397n/a#endif
9398n/a#ifdef _PC_VDISABLE
9399n/a {"PC_VDISABLE", _PC_VDISABLE},
9400n/a#endif
9401n/a#ifdef _PC_ACL_ENABLED
9402n/a {"PC_ACL_ENABLED", _PC_ACL_ENABLED},
9403n/a#endif
9404n/a#ifdef _PC_MIN_HOLE_SIZE
9405n/a {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE},
9406n/a#endif
9407n/a#ifdef _PC_ALLOC_SIZE_MIN
9408n/a {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN},
9409n/a#endif
9410n/a#ifdef _PC_REC_INCR_XFER_SIZE
9411n/a {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE},
9412n/a#endif
9413n/a#ifdef _PC_REC_MAX_XFER_SIZE
9414n/a {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE},
9415n/a#endif
9416n/a#ifdef _PC_REC_MIN_XFER_SIZE
9417n/a {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE},
9418n/a#endif
9419n/a#ifdef _PC_REC_XFER_ALIGN
9420n/a {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN},
9421n/a#endif
9422n/a#ifdef _PC_SYMLINK_MAX
9423n/a {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX},
9424n/a#endif
9425n/a#ifdef _PC_XATTR_ENABLED
9426n/a {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED},
9427n/a#endif
9428n/a#ifdef _PC_XATTR_EXISTS
9429n/a {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
9430n/a#endif
9431n/a#ifdef _PC_TIMESTAMP_RESOLUTION
9432n/a {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
9433n/a#endif
9434n/a};
9435n/a
9436n/astatic int
9437n/aconv_path_confname(PyObject *arg, int *valuep)
9438n/a{
9439n/a return conv_confname(arg, valuep, posix_constants_pathconf,
9440n/a sizeof(posix_constants_pathconf)
9441n/a / sizeof(struct constdef));
9442n/a}
9443n/a#endif
9444n/a
9445n/a
9446n/a#ifdef HAVE_FPATHCONF
9447n/a/*[clinic input]
9448n/aos.fpathconf -> long
9449n/a
9450n/a fd: int
9451n/a name: path_confname
9452n/a /
9453n/a
9454n/aReturn the configuration limit name for the file descriptor fd.
9455n/a
9456n/aIf there is no limit, return -1.
9457n/a[clinic start generated code]*/
9458n/a
9459n/astatic long
9460n/aos_fpathconf_impl(PyObject *module, int fd, int name)
9461n/a/*[clinic end generated code: output=d5b7042425fc3e21 input=5942a024d3777810]*/
9462n/a{
9463n/a long limit;
9464n/a
9465n/a errno = 0;
9466n/a limit = fpathconf(fd, name);
9467n/a if (limit == -1 && errno != 0)
9468n/a posix_error();
9469n/a
9470n/a return limit;
9471n/a}
9472n/a#endif /* HAVE_FPATHCONF */
9473n/a
9474n/a
9475n/a#ifdef HAVE_PATHCONF
9476n/a/*[clinic input]
9477n/aos.pathconf -> long
9478n/a path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
9479n/a name: path_confname
9480n/a
9481n/aReturn the configuration limit name for the file or directory path.
9482n/a
9483n/aIf there is no limit, return -1.
9484n/aOn some platforms, path may also be specified as an open file descriptor.
9485n/a If this functionality is unavailable, using it raises an exception.
9486n/a[clinic start generated code]*/
9487n/a
9488n/astatic long
9489n/aos_pathconf_impl(PyObject *module, path_t *path, int name)
9490n/a/*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
9491n/a{
9492n/a long limit;
9493n/a
9494n/a errno = 0;
9495n/a#ifdef HAVE_FPATHCONF
9496n/a if (path->fd != -1)
9497n/a limit = fpathconf(path->fd, name);
9498n/a else
9499n/a#endif
9500n/a limit = pathconf(path->narrow, name);
9501n/a if (limit == -1 && errno != 0) {
9502n/a if (errno == EINVAL)
9503n/a /* could be a path or name problem */
9504n/a posix_error();
9505n/a else
9506n/a path_error(path);
9507n/a }
9508n/a
9509n/a return limit;
9510n/a}
9511n/a#endif /* HAVE_PATHCONF */
9512n/a
9513n/a#ifdef HAVE_CONFSTR
9514n/astatic struct constdef posix_constants_confstr[] = {
9515n/a#ifdef _CS_ARCHITECTURE
9516n/a {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
9517n/a#endif
9518n/a#ifdef _CS_GNU_LIBC_VERSION
9519n/a {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION},
9520n/a#endif
9521n/a#ifdef _CS_GNU_LIBPTHREAD_VERSION
9522n/a {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION},
9523n/a#endif
9524n/a#ifdef _CS_HOSTNAME
9525n/a {"CS_HOSTNAME", _CS_HOSTNAME},
9526n/a#endif
9527n/a#ifdef _CS_HW_PROVIDER
9528n/a {"CS_HW_PROVIDER", _CS_HW_PROVIDER},
9529n/a#endif
9530n/a#ifdef _CS_HW_SERIAL
9531n/a {"CS_HW_SERIAL", _CS_HW_SERIAL},
9532n/a#endif
9533n/a#ifdef _CS_INITTAB_NAME
9534n/a {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
9535n/a#endif
9536n/a#ifdef _CS_LFS64_CFLAGS
9537n/a {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
9538n/a#endif
9539n/a#ifdef _CS_LFS64_LDFLAGS
9540n/a {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS},
9541n/a#endif
9542n/a#ifdef _CS_LFS64_LIBS
9543n/a {"CS_LFS64_LIBS", _CS_LFS64_LIBS},
9544n/a#endif
9545n/a#ifdef _CS_LFS64_LINTFLAGS
9546n/a {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS},
9547n/a#endif
9548n/a#ifdef _CS_LFS_CFLAGS
9549n/a {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS},
9550n/a#endif
9551n/a#ifdef _CS_LFS_LDFLAGS
9552n/a {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS},
9553n/a#endif
9554n/a#ifdef _CS_LFS_LIBS
9555n/a {"CS_LFS_LIBS", _CS_LFS_LIBS},
9556n/a#endif
9557n/a#ifdef _CS_LFS_LINTFLAGS
9558n/a {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS},
9559n/a#endif
9560n/a#ifdef _CS_MACHINE
9561n/a {"CS_MACHINE", _CS_MACHINE},
9562n/a#endif
9563n/a#ifdef _CS_PATH
9564n/a {"CS_PATH", _CS_PATH},
9565n/a#endif
9566n/a#ifdef _CS_RELEASE
9567n/a {"CS_RELEASE", _CS_RELEASE},
9568n/a#endif
9569n/a#ifdef _CS_SRPC_DOMAIN
9570n/a {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN},
9571n/a#endif
9572n/a#ifdef _CS_SYSNAME
9573n/a {"CS_SYSNAME", _CS_SYSNAME},
9574n/a#endif
9575n/a#ifdef _CS_VERSION
9576n/a {"CS_VERSION", _CS_VERSION},
9577n/a#endif
9578n/a#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
9579n/a {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS},
9580n/a#endif
9581n/a#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
9582n/a {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS},
9583n/a#endif
9584n/a#ifdef _CS_XBS5_ILP32_OFF32_LIBS
9585n/a {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS},
9586n/a#endif
9587n/a#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
9588n/a {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS},
9589n/a#endif
9590n/a#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
9591n/a {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS},
9592n/a#endif
9593n/a#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
9594n/a {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
9595n/a#endif
9596n/a#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
9597n/a {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS},
9598n/a#endif
9599n/a#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
9600n/a {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
9601n/a#endif
9602n/a#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
9603n/a {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS},
9604n/a#endif
9605n/a#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
9606n/a {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS},
9607n/a#endif
9608n/a#ifdef _CS_XBS5_LP64_OFF64_LIBS
9609n/a {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
9610n/a#endif
9611n/a#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
9612n/a {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS},
9613n/a#endif
9614n/a#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
9615n/a {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
9616n/a#endif
9617n/a#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
9618n/a {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
9619n/a#endif
9620n/a#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
9621n/a {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS},
9622n/a#endif
9623n/a#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
9624n/a {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
9625n/a#endif
9626n/a#ifdef _MIPS_CS_AVAIL_PROCESSORS
9627n/a {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS},
9628n/a#endif
9629n/a#ifdef _MIPS_CS_BASE
9630n/a {"MIPS_CS_BASE", _MIPS_CS_BASE},
9631n/a#endif
9632n/a#ifdef _MIPS_CS_HOSTID
9633n/a {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID},
9634n/a#endif
9635n/a#ifdef _MIPS_CS_HW_NAME
9636n/a {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
9637n/a#endif
9638n/a#ifdef _MIPS_CS_NUM_PROCESSORS
9639n/a {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS},
9640n/a#endif
9641n/a#ifdef _MIPS_CS_OSREL_MAJ
9642n/a {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ},
9643n/a#endif
9644n/a#ifdef _MIPS_CS_OSREL_MIN
9645n/a {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN},
9646n/a#endif
9647n/a#ifdef _MIPS_CS_OSREL_PATCH
9648n/a {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH},
9649n/a#endif
9650n/a#ifdef _MIPS_CS_OS_NAME
9651n/a {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
9652n/a#endif
9653n/a#ifdef _MIPS_CS_OS_PROVIDER
9654n/a {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER},
9655n/a#endif
9656n/a#ifdef _MIPS_CS_PROCESSORS
9657n/a {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS},
9658n/a#endif
9659n/a#ifdef _MIPS_CS_SERIAL
9660n/a {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL},
9661n/a#endif
9662n/a#ifdef _MIPS_CS_VENDOR
9663n/a {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR},
9664n/a#endif
9665n/a};
9666n/a
9667n/astatic int
9668n/aconv_confstr_confname(PyObject *arg, int *valuep)
9669n/a{
9670n/a return conv_confname(arg, valuep, posix_constants_confstr,
9671n/a sizeof(posix_constants_confstr)
9672n/a / sizeof(struct constdef));
9673n/a}
9674n/a
9675n/a
9676n/a/*[clinic input]
9677n/aos.confstr
9678n/a
9679n/a name: confstr_confname
9680n/a /
9681n/a
9682n/aReturn a string-valued system configuration variable.
9683n/a[clinic start generated code]*/
9684n/a
9685n/astatic PyObject *
9686n/aos_confstr_impl(PyObject *module, int name)
9687n/a/*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
9688n/a{
9689n/a PyObject *result = NULL;
9690n/a char buffer[255];
9691n/a size_t len;
9692n/a
9693n/a errno = 0;
9694n/a len = confstr(name, buffer, sizeof(buffer));
9695n/a if (len == 0) {
9696n/a if (errno) {
9697n/a posix_error();
9698n/a return NULL;
9699n/a }
9700n/a else {
9701n/a Py_RETURN_NONE;
9702n/a }
9703n/a }
9704n/a
9705n/a if (len >= sizeof(buffer)) {
9706n/a size_t len2;
9707n/a char *buf = PyMem_Malloc(len);
9708n/a if (buf == NULL)
9709n/a return PyErr_NoMemory();
9710n/a len2 = confstr(name, buf, len);
9711n/a assert(len == len2);
9712n/a result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
9713n/a PyMem_Free(buf);
9714n/a }
9715n/a else
9716n/a result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
9717n/a return result;
9718n/a}
9719n/a#endif /* HAVE_CONFSTR */
9720n/a
9721n/a
9722n/a#ifdef HAVE_SYSCONF
9723n/astatic struct constdef posix_constants_sysconf[] = {
9724n/a#ifdef _SC_2_CHAR_TERM
9725n/a {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM},
9726n/a#endif
9727n/a#ifdef _SC_2_C_BIND
9728n/a {"SC_2_C_BIND", _SC_2_C_BIND},
9729n/a#endif
9730n/a#ifdef _SC_2_C_DEV
9731n/a {"SC_2_C_DEV", _SC_2_C_DEV},
9732n/a#endif
9733n/a#ifdef _SC_2_C_VERSION
9734n/a {"SC_2_C_VERSION", _SC_2_C_VERSION},
9735n/a#endif
9736n/a#ifdef _SC_2_FORT_DEV
9737n/a {"SC_2_FORT_DEV", _SC_2_FORT_DEV},
9738n/a#endif
9739n/a#ifdef _SC_2_FORT_RUN
9740n/a {"SC_2_FORT_RUN", _SC_2_FORT_RUN},
9741n/a#endif
9742n/a#ifdef _SC_2_LOCALEDEF
9743n/a {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF},
9744n/a#endif
9745n/a#ifdef _SC_2_SW_DEV
9746n/a {"SC_2_SW_DEV", _SC_2_SW_DEV},
9747n/a#endif
9748n/a#ifdef _SC_2_UPE
9749n/a {"SC_2_UPE", _SC_2_UPE},
9750n/a#endif
9751n/a#ifdef _SC_2_VERSION
9752n/a {"SC_2_VERSION", _SC_2_VERSION},
9753n/a#endif
9754n/a#ifdef _SC_ABI_ASYNCHRONOUS_IO
9755n/a {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO},
9756n/a#endif
9757n/a#ifdef _SC_ACL
9758n/a {"SC_ACL", _SC_ACL},
9759n/a#endif
9760n/a#ifdef _SC_AIO_LISTIO_MAX
9761n/a {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX},
9762n/a#endif
9763n/a#ifdef _SC_AIO_MAX
9764n/a {"SC_AIO_MAX", _SC_AIO_MAX},
9765n/a#endif
9766n/a#ifdef _SC_AIO_PRIO_DELTA_MAX
9767n/a {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX},
9768n/a#endif
9769n/a#ifdef _SC_ARG_MAX
9770n/a {"SC_ARG_MAX", _SC_ARG_MAX},
9771n/a#endif
9772n/a#ifdef _SC_ASYNCHRONOUS_IO
9773n/a {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO},
9774n/a#endif
9775n/a#ifdef _SC_ATEXIT_MAX
9776n/a {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX},
9777n/a#endif
9778n/a#ifdef _SC_AUDIT
9779n/a {"SC_AUDIT", _SC_AUDIT},
9780n/a#endif
9781n/a#ifdef _SC_AVPHYS_PAGES
9782n/a {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
9783n/a#endif
9784n/a#ifdef _SC_BC_BASE_MAX
9785n/a {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX},
9786n/a#endif
9787n/a#ifdef _SC_BC_DIM_MAX
9788n/a {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX},
9789n/a#endif
9790n/a#ifdef _SC_BC_SCALE_MAX
9791n/a {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
9792n/a#endif
9793n/a#ifdef _SC_BC_STRING_MAX
9794n/a {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX},
9795n/a#endif
9796n/a#ifdef _SC_CAP
9797n/a {"SC_CAP", _SC_CAP},
9798n/a#endif
9799n/a#ifdef _SC_CHARCLASS_NAME_MAX
9800n/a {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX},
9801n/a#endif
9802n/a#ifdef _SC_CHAR_BIT
9803n/a {"SC_CHAR_BIT", _SC_CHAR_BIT},
9804n/a#endif
9805n/a#ifdef _SC_CHAR_MAX
9806n/a {"SC_CHAR_MAX", _SC_CHAR_MAX},
9807n/a#endif
9808n/a#ifdef _SC_CHAR_MIN
9809n/a {"SC_CHAR_MIN", _SC_CHAR_MIN},
9810n/a#endif
9811n/a#ifdef _SC_CHILD_MAX
9812n/a {"SC_CHILD_MAX", _SC_CHILD_MAX},
9813n/a#endif
9814n/a#ifdef _SC_CLK_TCK
9815n/a {"SC_CLK_TCK", _SC_CLK_TCK},
9816n/a#endif
9817n/a#ifdef _SC_COHER_BLKSZ
9818n/a {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ},
9819n/a#endif
9820n/a#ifdef _SC_COLL_WEIGHTS_MAX
9821n/a {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX},
9822n/a#endif
9823n/a#ifdef _SC_DCACHE_ASSOC
9824n/a {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
9825n/a#endif
9826n/a#ifdef _SC_DCACHE_BLKSZ
9827n/a {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
9828n/a#endif
9829n/a#ifdef _SC_DCACHE_LINESZ
9830n/a {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ},
9831n/a#endif
9832n/a#ifdef _SC_DCACHE_SZ
9833n/a {"SC_DCACHE_SZ", _SC_DCACHE_SZ},
9834n/a#endif
9835n/a#ifdef _SC_DCACHE_TBLKSZ
9836n/a {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ},
9837n/a#endif
9838n/a#ifdef _SC_DELAYTIMER_MAX
9839n/a {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX},
9840n/a#endif
9841n/a#ifdef _SC_EQUIV_CLASS_MAX
9842n/a {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX},
9843n/a#endif
9844n/a#ifdef _SC_EXPR_NEST_MAX
9845n/a {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX},
9846n/a#endif
9847n/a#ifdef _SC_FSYNC
9848n/a {"SC_FSYNC", _SC_FSYNC},
9849n/a#endif
9850n/a#ifdef _SC_GETGR_R_SIZE_MAX
9851n/a {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX},
9852n/a#endif
9853n/a#ifdef _SC_GETPW_R_SIZE_MAX
9854n/a {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX},
9855n/a#endif
9856n/a#ifdef _SC_ICACHE_ASSOC
9857n/a {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
9858n/a#endif
9859n/a#ifdef _SC_ICACHE_BLKSZ
9860n/a {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
9861n/a#endif
9862n/a#ifdef _SC_ICACHE_LINESZ
9863n/a {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ},
9864n/a#endif
9865n/a#ifdef _SC_ICACHE_SZ
9866n/a {"SC_ICACHE_SZ", _SC_ICACHE_SZ},
9867n/a#endif
9868n/a#ifdef _SC_INF
9869n/a {"SC_INF", _SC_INF},
9870n/a#endif
9871n/a#ifdef _SC_INT_MAX
9872n/a {"SC_INT_MAX", _SC_INT_MAX},
9873n/a#endif
9874n/a#ifdef _SC_INT_MIN
9875n/a {"SC_INT_MIN", _SC_INT_MIN},
9876n/a#endif
9877n/a#ifdef _SC_IOV_MAX
9878n/a {"SC_IOV_MAX", _SC_IOV_MAX},
9879n/a#endif
9880n/a#ifdef _SC_IP_SECOPTS
9881n/a {"SC_IP_SECOPTS", _SC_IP_SECOPTS},
9882n/a#endif
9883n/a#ifdef _SC_JOB_CONTROL
9884n/a {"SC_JOB_CONTROL", _SC_JOB_CONTROL},
9885n/a#endif
9886n/a#ifdef _SC_KERN_POINTERS
9887n/a {"SC_KERN_POINTERS", _SC_KERN_POINTERS},
9888n/a#endif
9889n/a#ifdef _SC_KERN_SIM
9890n/a {"SC_KERN_SIM", _SC_KERN_SIM},
9891n/a#endif
9892n/a#ifdef _SC_LINE_MAX
9893n/a {"SC_LINE_MAX", _SC_LINE_MAX},
9894n/a#endif
9895n/a#ifdef _SC_LOGIN_NAME_MAX
9896n/a {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX},
9897n/a#endif
9898n/a#ifdef _SC_LOGNAME_MAX
9899n/a {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX},
9900n/a#endif
9901n/a#ifdef _SC_LONG_BIT
9902n/a {"SC_LONG_BIT", _SC_LONG_BIT},
9903n/a#endif
9904n/a#ifdef _SC_MAC
9905n/a {"SC_MAC", _SC_MAC},
9906n/a#endif
9907n/a#ifdef _SC_MAPPED_FILES
9908n/a {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
9909n/a#endif
9910n/a#ifdef _SC_MAXPID
9911n/a {"SC_MAXPID", _SC_MAXPID},
9912n/a#endif
9913n/a#ifdef _SC_MB_LEN_MAX
9914n/a {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX},
9915n/a#endif
9916n/a#ifdef _SC_MEMLOCK
9917n/a {"SC_MEMLOCK", _SC_MEMLOCK},
9918n/a#endif
9919n/a#ifdef _SC_MEMLOCK_RANGE
9920n/a {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE},
9921n/a#endif
9922n/a#ifdef _SC_MEMORY_PROTECTION
9923n/a {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION},
9924n/a#endif
9925n/a#ifdef _SC_MESSAGE_PASSING
9926n/a {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING},
9927n/a#endif
9928n/a#ifdef _SC_MMAP_FIXED_ALIGNMENT
9929n/a {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
9930n/a#endif
9931n/a#ifdef _SC_MQ_OPEN_MAX
9932n/a {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX},
9933n/a#endif
9934n/a#ifdef _SC_MQ_PRIO_MAX
9935n/a {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX},
9936n/a#endif
9937n/a#ifdef _SC_NACLS_MAX
9938n/a {"SC_NACLS_MAX", _SC_NACLS_MAX},
9939n/a#endif
9940n/a#ifdef _SC_NGROUPS_MAX
9941n/a {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX},
9942n/a#endif
9943n/a#ifdef _SC_NL_ARGMAX
9944n/a {"SC_NL_ARGMAX", _SC_NL_ARGMAX},
9945n/a#endif
9946n/a#ifdef _SC_NL_LANGMAX
9947n/a {"SC_NL_LANGMAX", _SC_NL_LANGMAX},
9948n/a#endif
9949n/a#ifdef _SC_NL_MSGMAX
9950n/a {"SC_NL_MSGMAX", _SC_NL_MSGMAX},
9951n/a#endif
9952n/a#ifdef _SC_NL_NMAX
9953n/a {"SC_NL_NMAX", _SC_NL_NMAX},
9954n/a#endif
9955n/a#ifdef _SC_NL_SETMAX
9956n/a {"SC_NL_SETMAX", _SC_NL_SETMAX},
9957n/a#endif
9958n/a#ifdef _SC_NL_TEXTMAX
9959n/a {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX},
9960n/a#endif
9961n/a#ifdef _SC_NPROCESSORS_CONF
9962n/a {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF},
9963n/a#endif
9964n/a#ifdef _SC_NPROCESSORS_ONLN
9965n/a {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN},
9966n/a#endif
9967n/a#ifdef _SC_NPROC_CONF
9968n/a {"SC_NPROC_CONF", _SC_NPROC_CONF},
9969n/a#endif
9970n/a#ifdef _SC_NPROC_ONLN
9971n/a {"SC_NPROC_ONLN", _SC_NPROC_ONLN},
9972n/a#endif
9973n/a#ifdef _SC_NZERO
9974n/a {"SC_NZERO", _SC_NZERO},
9975n/a#endif
9976n/a#ifdef _SC_OPEN_MAX
9977n/a {"SC_OPEN_MAX", _SC_OPEN_MAX},
9978n/a#endif
9979n/a#ifdef _SC_PAGESIZE
9980n/a {"SC_PAGESIZE", _SC_PAGESIZE},
9981n/a#endif
9982n/a#ifdef _SC_PAGE_SIZE
9983n/a {"SC_PAGE_SIZE", _SC_PAGE_SIZE},
9984n/a#endif
9985n/a#ifdef _SC_PASS_MAX
9986n/a {"SC_PASS_MAX", _SC_PASS_MAX},
9987n/a#endif
9988n/a#ifdef _SC_PHYS_PAGES
9989n/a {"SC_PHYS_PAGES", _SC_PHYS_PAGES},
9990n/a#endif
9991n/a#ifdef _SC_PII
9992n/a {"SC_PII", _SC_PII},
9993n/a#endif
9994n/a#ifdef _SC_PII_INTERNET
9995n/a {"SC_PII_INTERNET", _SC_PII_INTERNET},
9996n/a#endif
9997n/a#ifdef _SC_PII_INTERNET_DGRAM
9998n/a {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM},
9999n/a#endif
10000n/a#ifdef _SC_PII_INTERNET_STREAM
10001n/a {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM},
10002n/a#endif
10003n/a#ifdef _SC_PII_OSI
10004n/a {"SC_PII_OSI", _SC_PII_OSI},
10005n/a#endif
10006n/a#ifdef _SC_PII_OSI_CLTS
10007n/a {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
10008n/a#endif
10009n/a#ifdef _SC_PII_OSI_COTS
10010n/a {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
10011n/a#endif
10012n/a#ifdef _SC_PII_OSI_M
10013n/a {"SC_PII_OSI_M", _SC_PII_OSI_M},
10014n/a#endif
10015n/a#ifdef _SC_PII_SOCKET
10016n/a {"SC_PII_SOCKET", _SC_PII_SOCKET},
10017n/a#endif
10018n/a#ifdef _SC_PII_XTI
10019n/a {"SC_PII_XTI", _SC_PII_XTI},
10020n/a#endif
10021n/a#ifdef _SC_POLL
10022n/a {"SC_POLL", _SC_POLL},
10023n/a#endif
10024n/a#ifdef _SC_PRIORITIZED_IO
10025n/a {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO},
10026n/a#endif
10027n/a#ifdef _SC_PRIORITY_SCHEDULING
10028n/a {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING},
10029n/a#endif
10030n/a#ifdef _SC_REALTIME_SIGNALS
10031n/a {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS},
10032n/a#endif
10033n/a#ifdef _SC_RE_DUP_MAX
10034n/a {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX},
10035n/a#endif
10036n/a#ifdef _SC_RTSIG_MAX
10037n/a {"SC_RTSIG_MAX", _SC_RTSIG_MAX},
10038n/a#endif
10039n/a#ifdef _SC_SAVED_IDS
10040n/a {"SC_SAVED_IDS", _SC_SAVED_IDS},
10041n/a#endif
10042n/a#ifdef _SC_SCHAR_MAX
10043n/a {"SC_SCHAR_MAX", _SC_SCHAR_MAX},
10044n/a#endif
10045n/a#ifdef _SC_SCHAR_MIN
10046n/a {"SC_SCHAR_MIN", _SC_SCHAR_MIN},
10047n/a#endif
10048n/a#ifdef _SC_SELECT
10049n/a {"SC_SELECT", _SC_SELECT},
10050n/a#endif
10051n/a#ifdef _SC_SEMAPHORES
10052n/a {"SC_SEMAPHORES", _SC_SEMAPHORES},
10053n/a#endif
10054n/a#ifdef _SC_SEM_NSEMS_MAX
10055n/a {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX},
10056n/a#endif
10057n/a#ifdef _SC_SEM_VALUE_MAX
10058n/a {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX},
10059n/a#endif
10060n/a#ifdef _SC_SHARED_MEMORY_OBJECTS
10061n/a {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS},
10062n/a#endif
10063n/a#ifdef _SC_SHRT_MAX
10064n/a {"SC_SHRT_MAX", _SC_SHRT_MAX},
10065n/a#endif
10066n/a#ifdef _SC_SHRT_MIN
10067n/a {"SC_SHRT_MIN", _SC_SHRT_MIN},
10068n/a#endif
10069n/a#ifdef _SC_SIGQUEUE_MAX
10070n/a {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
10071n/a#endif
10072n/a#ifdef _SC_SIGRT_MAX
10073n/a {"SC_SIGRT_MAX", _SC_SIGRT_MAX},
10074n/a#endif
10075n/a#ifdef _SC_SIGRT_MIN
10076n/a {"SC_SIGRT_MIN", _SC_SIGRT_MIN},
10077n/a#endif
10078n/a#ifdef _SC_SOFTPOWER
10079n/a {"SC_SOFTPOWER", _SC_SOFTPOWER},
10080n/a#endif
10081n/a#ifdef _SC_SPLIT_CACHE
10082n/a {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE},
10083n/a#endif
10084n/a#ifdef _SC_SSIZE_MAX
10085n/a {"SC_SSIZE_MAX", _SC_SSIZE_MAX},
10086n/a#endif
10087n/a#ifdef _SC_STACK_PROT
10088n/a {"SC_STACK_PROT", _SC_STACK_PROT},
10089n/a#endif
10090n/a#ifdef _SC_STREAM_MAX
10091n/a {"SC_STREAM_MAX", _SC_STREAM_MAX},
10092n/a#endif
10093n/a#ifdef _SC_SYNCHRONIZED_IO
10094n/a {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO},
10095n/a#endif
10096n/a#ifdef _SC_THREADS
10097n/a {"SC_THREADS", _SC_THREADS},
10098n/a#endif
10099n/a#ifdef _SC_THREAD_ATTR_STACKADDR
10100n/a {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR},
10101n/a#endif
10102n/a#ifdef _SC_THREAD_ATTR_STACKSIZE
10103n/a {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE},
10104n/a#endif
10105n/a#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
10106n/a {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
10107n/a#endif
10108n/a#ifdef _SC_THREAD_KEYS_MAX
10109n/a {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX},
10110n/a#endif
10111n/a#ifdef _SC_THREAD_PRIORITY_SCHEDULING
10112n/a {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING},
10113n/a#endif
10114n/a#ifdef _SC_THREAD_PRIO_INHERIT
10115n/a {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT},
10116n/a#endif
10117n/a#ifdef _SC_THREAD_PRIO_PROTECT
10118n/a {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT},
10119n/a#endif
10120n/a#ifdef _SC_THREAD_PROCESS_SHARED
10121n/a {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED},
10122n/a#endif
10123n/a#ifdef _SC_THREAD_SAFE_FUNCTIONS
10124n/a {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS},
10125n/a#endif
10126n/a#ifdef _SC_THREAD_STACK_MIN
10127n/a {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN},
10128n/a#endif
10129n/a#ifdef _SC_THREAD_THREADS_MAX
10130n/a {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX},
10131n/a#endif
10132n/a#ifdef _SC_TIMERS
10133n/a {"SC_TIMERS", _SC_TIMERS},
10134n/a#endif
10135n/a#ifdef _SC_TIMER_MAX
10136n/a {"SC_TIMER_MAX", _SC_TIMER_MAX},
10137n/a#endif
10138n/a#ifdef _SC_TTY_NAME_MAX
10139n/a {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
10140n/a#endif
10141n/a#ifdef _SC_TZNAME_MAX
10142n/a {"SC_TZNAME_MAX", _SC_TZNAME_MAX},
10143n/a#endif
10144n/a#ifdef _SC_T_IOV_MAX
10145n/a {"SC_T_IOV_MAX", _SC_T_IOV_MAX},
10146n/a#endif
10147n/a#ifdef _SC_UCHAR_MAX
10148n/a {"SC_UCHAR_MAX", _SC_UCHAR_MAX},
10149n/a#endif
10150n/a#ifdef _SC_UINT_MAX
10151n/a {"SC_UINT_MAX", _SC_UINT_MAX},
10152n/a#endif
10153n/a#ifdef _SC_UIO_MAXIOV
10154n/a {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV},
10155n/a#endif
10156n/a#ifdef _SC_ULONG_MAX
10157n/a {"SC_ULONG_MAX", _SC_ULONG_MAX},
10158n/a#endif
10159n/a#ifdef _SC_USHRT_MAX
10160n/a {"SC_USHRT_MAX", _SC_USHRT_MAX},
10161n/a#endif
10162n/a#ifdef _SC_VERSION
10163n/a {"SC_VERSION", _SC_VERSION},
10164n/a#endif
10165n/a#ifdef _SC_WORD_BIT
10166n/a {"SC_WORD_BIT", _SC_WORD_BIT},
10167n/a#endif
10168n/a#ifdef _SC_XBS5_ILP32_OFF32
10169n/a {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32},
10170n/a#endif
10171n/a#ifdef _SC_XBS5_ILP32_OFFBIG
10172n/a {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG},
10173n/a#endif
10174n/a#ifdef _SC_XBS5_LP64_OFF64
10175n/a {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64},
10176n/a#endif
10177n/a#ifdef _SC_XBS5_LPBIG_OFFBIG
10178n/a {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG},
10179n/a#endif
10180n/a#ifdef _SC_XOPEN_CRYPT
10181n/a {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT},
10182n/a#endif
10183n/a#ifdef _SC_XOPEN_ENH_I18N
10184n/a {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N},
10185n/a#endif
10186n/a#ifdef _SC_XOPEN_LEGACY
10187n/a {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
10188n/a#endif
10189n/a#ifdef _SC_XOPEN_REALTIME
10190n/a {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME},
10191n/a#endif
10192n/a#ifdef _SC_XOPEN_REALTIME_THREADS
10193n/a {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS},
10194n/a#endif
10195n/a#ifdef _SC_XOPEN_SHM
10196n/a {"SC_XOPEN_SHM", _SC_XOPEN_SHM},
10197n/a#endif
10198n/a#ifdef _SC_XOPEN_UNIX
10199n/a {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX},
10200n/a#endif
10201n/a#ifdef _SC_XOPEN_VERSION
10202n/a {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION},
10203n/a#endif
10204n/a#ifdef _SC_XOPEN_XCU_VERSION
10205n/a {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION},
10206n/a#endif
10207n/a#ifdef _SC_XOPEN_XPG2
10208n/a {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2},
10209n/a#endif
10210n/a#ifdef _SC_XOPEN_XPG3
10211n/a {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3},
10212n/a#endif
10213n/a#ifdef _SC_XOPEN_XPG4
10214n/a {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4},
10215n/a#endif
10216n/a};
10217n/a
10218n/astatic int
10219n/aconv_sysconf_confname(PyObject *arg, int *valuep)
10220n/a{
10221n/a return conv_confname(arg, valuep, posix_constants_sysconf,
10222n/a sizeof(posix_constants_sysconf)
10223n/a / sizeof(struct constdef));
10224n/a}
10225n/a
10226n/a
10227n/a/*[clinic input]
10228n/aos.sysconf -> long
10229n/a name: sysconf_confname
10230n/a /
10231n/a
10232n/aReturn an integer-valued system configuration variable.
10233n/a[clinic start generated code]*/
10234n/a
10235n/astatic long
10236n/aos_sysconf_impl(PyObject *module, int name)
10237n/a/*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
10238n/a{
10239n/a long value;
10240n/a
10241n/a errno = 0;
10242n/a value = sysconf(name);
10243n/a if (value == -1 && errno != 0)
10244n/a posix_error();
10245n/a return value;
10246n/a}
10247n/a#endif /* HAVE_SYSCONF */
10248n/a
10249n/a
10250n/a/* This code is used to ensure that the tables of configuration value names
10251n/a * are in sorted order as required by conv_confname(), and also to build
10252n/a * the exported dictionaries that are used to publish information about the
10253n/a * names available on the host platform.
10254n/a *
10255n/a * Sorting the table at runtime ensures that the table is properly ordered
10256n/a * when used, even for platforms we're not able to test on. It also makes
10257n/a * it easier to add additional entries to the tables.
10258n/a */
10259n/a
10260n/astatic int
10261n/acmp_constdefs(const void *v1, const void *v2)
10262n/a{
10263n/a const struct constdef *c1 =
10264n/a (const struct constdef *) v1;
10265n/a const struct constdef *c2 =
10266n/a (const struct constdef *) v2;
10267n/a
10268n/a return strcmp(c1->name, c2->name);
10269n/a}
10270n/a
10271n/astatic int
10272n/asetup_confname_table(struct constdef *table, size_t tablesize,
10273n/a const char *tablename, PyObject *module)
10274n/a{
10275n/a PyObject *d = NULL;
10276n/a size_t i;
10277n/a
10278n/a qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
10279n/a d = PyDict_New();
10280n/a if (d == NULL)
10281n/a return -1;
10282n/a
10283n/a for (i=0; i < tablesize; ++i) {
10284n/a PyObject *o = PyLong_FromLong(table[i].value);
10285n/a if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
10286n/a Py_XDECREF(o);
10287n/a Py_DECREF(d);
10288n/a return -1;
10289n/a }
10290n/a Py_DECREF(o);
10291n/a }
10292n/a return PyModule_AddObject(module, tablename, d);
10293n/a}
10294n/a
10295n/a/* Return -1 on failure, 0 on success. */
10296n/astatic int
10297n/asetup_confname_tables(PyObject *module)
10298n/a{
10299n/a#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
10300n/a if (setup_confname_table(posix_constants_pathconf,
10301n/a sizeof(posix_constants_pathconf)
10302n/a / sizeof(struct constdef),
10303n/a "pathconf_names", module))
10304n/a return -1;
10305n/a#endif
10306n/a#ifdef HAVE_CONFSTR
10307n/a if (setup_confname_table(posix_constants_confstr,
10308n/a sizeof(posix_constants_confstr)
10309n/a / sizeof(struct constdef),
10310n/a "confstr_names", module))
10311n/a return -1;
10312n/a#endif
10313n/a#ifdef HAVE_SYSCONF
10314n/a if (setup_confname_table(posix_constants_sysconf,
10315n/a sizeof(posix_constants_sysconf)
10316n/a / sizeof(struct constdef),
10317n/a "sysconf_names", module))
10318n/a return -1;
10319n/a#endif
10320n/a return 0;
10321n/a}
10322n/a
10323n/a
10324n/a/*[clinic input]
10325n/aos.abort
10326n/a
10327n/aAbort the interpreter immediately.
10328n/a
10329n/aThis function 'dumps core' or otherwise fails in the hardest way possible
10330n/aon the hosting operating system. This function never returns.
10331n/a[clinic start generated code]*/
10332n/a
10333n/astatic PyObject *
10334n/aos_abort_impl(PyObject *module)
10335n/a/*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
10336n/a{
10337n/a abort();
10338n/a /*NOTREACHED*/
10339n/a#ifndef __clang__
10340n/a /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
10341n/a GCC emits a warning without "return NULL;" (compiler bug?), but Clang
10342n/a is smarter and emits a warning on the return. */
10343n/a Py_FatalError("abort() called from Python code didn't abort!");
10344n/a return NULL;
10345n/a#endif
10346n/a}
10347n/a
10348n/a#ifdef MS_WINDOWS
10349n/a/* Grab ShellExecute dynamically from shell32 */
10350n/astatic int has_ShellExecute = -1;
10351n/astatic HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
10352n/a LPCWSTR, INT);
10353n/astatic int
10354n/acheck_ShellExecute()
10355n/a{
10356n/a HINSTANCE hShell32;
10357n/a
10358n/a /* only recheck */
10359n/a if (-1 == has_ShellExecute) {
10360n/a Py_BEGIN_ALLOW_THREADS
10361n/a hShell32 = LoadLibraryW(L"SHELL32");
10362n/a Py_END_ALLOW_THREADS
10363n/a if (hShell32) {
10364n/a *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
10365n/a "ShellExecuteW");
10366n/a has_ShellExecute = Py_ShellExecuteW != NULL;
10367n/a } else {
10368n/a has_ShellExecute = 0;
10369n/a }
10370n/a }
10371n/a return has_ShellExecute;
10372n/a}
10373n/a
10374n/a
10375n/a/*[clinic input]
10376n/aos.startfile
10377n/a filepath: path_t
10378n/a operation: Py_UNICODE = NULL
10379n/a
10380n/astartfile(filepath [, operation])
10381n/a
10382n/aStart a file with its associated application.
10383n/a
10384n/aWhen "operation" is not specified or "open", this acts like
10385n/adouble-clicking the file in Explorer, or giving the file name as an
10386n/aargument to the DOS "start" command: the file is opened with whatever
10387n/aapplication (if any) its extension is associated.
10388n/aWhen another "operation" is given, it specifies what should be done with
10389n/athe file. A typical operation is "print".
10390n/a
10391n/astartfile returns as soon as the associated application is launched.
10392n/aThere is no option to wait for the application to close, and no way
10393n/ato retrieve the application's exit status.
10394n/a
10395n/aThe filepath is relative to the current directory. If you want to use
10396n/aan absolute path, make sure the first character is not a slash ("/");
10397n/athe underlying Win32 ShellExecute function doesn't work if it is.
10398n/a[clinic start generated code]*/
10399n/a
10400n/astatic PyObject *
10401n/aos_startfile_impl(PyObject *module, path_t *filepath, Py_UNICODE *operation)
10402n/a/*[clinic end generated code: output=912ceba79acfa1c9 input=63950bf2986380d0]*/
10403n/a{
10404n/a HINSTANCE rc;
10405n/a
10406n/a if(!check_ShellExecute()) {
10407n/a /* If the OS doesn't have ShellExecute, return a
10408n/a NotImplementedError. */
10409n/a return PyErr_Format(PyExc_NotImplementedError,
10410n/a "startfile not available on this platform");
10411n/a }
10412n/a
10413n/a Py_BEGIN_ALLOW_THREADS
10414n/a rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
10415n/a NULL, NULL, SW_SHOWNORMAL);
10416n/a Py_END_ALLOW_THREADS
10417n/a
10418n/a if (rc <= (HINSTANCE)32) {
10419n/a win32_error_object("startfile", filepath->object);
10420n/a return NULL;
10421n/a }
10422n/a Py_RETURN_NONE;
10423n/a}
10424n/a#endif /* MS_WINDOWS */
10425n/a
10426n/a
10427n/a#ifdef HAVE_GETLOADAVG
10428n/a/*[clinic input]
10429n/aos.getloadavg
10430n/a
10431n/aReturn average recent system load information.
10432n/a
10433n/aReturn the number of processes in the system run queue averaged over
10434n/athe last 1, 5, and 15 minutes as a tuple of three floats.
10435n/aRaises OSError if the load average was unobtainable.
10436n/a[clinic start generated code]*/
10437n/a
10438n/astatic PyObject *
10439n/aos_getloadavg_impl(PyObject *module)
10440n/a/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
10441n/a{
10442n/a double loadavg[3];
10443n/a if (getloadavg(loadavg, 3)!=3) {
10444n/a PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
10445n/a return NULL;
10446n/a } else
10447n/a return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
10448n/a}
10449n/a#endif /* HAVE_GETLOADAVG */
10450n/a
10451n/a
10452n/a/*[clinic input]
10453n/aos.device_encoding
10454n/a fd: int
10455n/a
10456n/aReturn a string describing the encoding of a terminal's file descriptor.
10457n/a
10458n/aThe file descriptor must be attached to a terminal.
10459n/aIf the device is not a terminal, return None.
10460n/a[clinic start generated code]*/
10461n/a
10462n/astatic PyObject *
10463n/aos_device_encoding_impl(PyObject *module, int fd)
10464n/a/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
10465n/a{
10466n/a return _Py_device_encoding(fd);
10467n/a}
10468n/a
10469n/a
10470n/a#ifdef HAVE_SETRESUID
10471n/a/*[clinic input]
10472n/aos.setresuid
10473n/a
10474n/a ruid: uid_t
10475n/a euid: uid_t
10476n/a suid: uid_t
10477n/a /
10478n/a
10479n/aSet the current process's real, effective, and saved user ids.
10480n/a[clinic start generated code]*/
10481n/a
10482n/astatic PyObject *
10483n/aos_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
10484n/a/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
10485n/a{
10486n/a if (setresuid(ruid, euid, suid) < 0)
10487n/a return posix_error();
10488n/a Py_RETURN_NONE;
10489n/a}
10490n/a#endif /* HAVE_SETRESUID */
10491n/a
10492n/a
10493n/a#ifdef HAVE_SETRESGID
10494n/a/*[clinic input]
10495n/aos.setresgid
10496n/a
10497n/a rgid: gid_t
10498n/a egid: gid_t
10499n/a sgid: gid_t
10500n/a /
10501n/a
10502n/aSet the current process's real, effective, and saved group ids.
10503n/a[clinic start generated code]*/
10504n/a
10505n/astatic PyObject *
10506n/aos_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
10507n/a/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
10508n/a{
10509n/a if (setresgid(rgid, egid, sgid) < 0)
10510n/a return posix_error();
10511n/a Py_RETURN_NONE;
10512n/a}
10513n/a#endif /* HAVE_SETRESGID */
10514n/a
10515n/a
10516n/a#ifdef HAVE_GETRESUID
10517n/a/*[clinic input]
10518n/aos.getresuid
10519n/a
10520n/aReturn a tuple of the current process's real, effective, and saved user ids.
10521n/a[clinic start generated code]*/
10522n/a
10523n/astatic PyObject *
10524n/aos_getresuid_impl(PyObject *module)
10525n/a/*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
10526n/a{
10527n/a uid_t ruid, euid, suid;
10528n/a if (getresuid(&ruid, &euid, &suid) < 0)
10529n/a return posix_error();
10530n/a return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
10531n/a _PyLong_FromUid(euid),
10532n/a _PyLong_FromUid(suid));
10533n/a}
10534n/a#endif /* HAVE_GETRESUID */
10535n/a
10536n/a
10537n/a#ifdef HAVE_GETRESGID
10538n/a/*[clinic input]
10539n/aos.getresgid
10540n/a
10541n/aReturn a tuple of the current process's real, effective, and saved group ids.
10542n/a[clinic start generated code]*/
10543n/a
10544n/astatic PyObject *
10545n/aos_getresgid_impl(PyObject *module)
10546n/a/*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
10547n/a{
10548n/a gid_t rgid, egid, sgid;
10549n/a if (getresgid(&rgid, &egid, &sgid) < 0)
10550n/a return posix_error();
10551n/a return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
10552n/a _PyLong_FromGid(egid),
10553n/a _PyLong_FromGid(sgid));
10554n/a}
10555n/a#endif /* HAVE_GETRESGID */
10556n/a
10557n/a
10558n/a#ifdef USE_XATTRS
10559n/a/*[clinic input]
10560n/aos.getxattr
10561n/a
10562n/a path: path_t(allow_fd=True)
10563n/a attribute: path_t
10564n/a *
10565n/a follow_symlinks: bool = True
10566n/a
10567n/aReturn the value of extended attribute attribute on path.
10568n/a
10569n/apath may be either a string or an open file descriptor.
10570n/aIf follow_symlinks is False, and the last element of the path is a symbolic
10571n/a link, getxattr will examine the symbolic link itself instead of the file
10572n/a the link points to.
10573n/a
10574n/a[clinic start generated code]*/
10575n/a
10576n/astatic PyObject *
10577n/aos_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
10578n/a int follow_symlinks)
10579n/a/*[clinic end generated code: output=5f2f44200a43cff2 input=8c8ea3bab78d89c2]*/
10580n/a{
10581n/a Py_ssize_t i;
10582n/a PyObject *buffer = NULL;
10583n/a
10584n/a if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
10585n/a return NULL;
10586n/a
10587n/a for (i = 0; ; i++) {
10588n/a void *ptr;
10589n/a ssize_t result;
10590n/a static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
10591n/a Py_ssize_t buffer_size = buffer_sizes[i];
10592n/a if (!buffer_size) {
10593n/a path_error(path);
10594n/a return NULL;
10595n/a }
10596n/a buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
10597n/a if (!buffer)
10598n/a return NULL;
10599n/a ptr = PyBytes_AS_STRING(buffer);
10600n/a
10601n/a Py_BEGIN_ALLOW_THREADS;
10602n/a if (path->fd >= 0)
10603n/a result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
10604n/a else if (follow_symlinks)
10605n/a result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
10606n/a else
10607n/a result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
10608n/a Py_END_ALLOW_THREADS;
10609n/a
10610n/a if (result < 0) {
10611n/a Py_DECREF(buffer);
10612n/a if (errno == ERANGE)
10613n/a continue;
10614n/a path_error(path);
10615n/a return NULL;
10616n/a }
10617n/a
10618n/a if (result != buffer_size) {
10619n/a /* Can only shrink. */
10620n/a _PyBytes_Resize(&buffer, result);
10621n/a }
10622n/a break;
10623n/a }
10624n/a
10625n/a return buffer;
10626n/a}
10627n/a
10628n/a
10629n/a/*[clinic input]
10630n/aos.setxattr
10631n/a
10632n/a path: path_t(allow_fd=True)
10633n/a attribute: path_t
10634n/a value: Py_buffer
10635n/a flags: int = 0
10636n/a *
10637n/a follow_symlinks: bool = True
10638n/a
10639n/aSet extended attribute attribute on path to value.
10640n/a
10641n/apath may be either a string or an open file descriptor.
10642n/aIf follow_symlinks is False, and the last element of the path is a symbolic
10643n/a link, setxattr will modify the symbolic link itself instead of the file
10644n/a the link points to.
10645n/a
10646n/a[clinic start generated code]*/
10647n/a
10648n/astatic PyObject *
10649n/aos_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
10650n/a Py_buffer *value, int flags, int follow_symlinks)
10651n/a/*[clinic end generated code: output=98b83f63fdde26bb input=f0d26833992015c2]*/
10652n/a{
10653n/a ssize_t result;
10654n/a
10655n/a if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
10656n/a return NULL;
10657n/a
10658n/a Py_BEGIN_ALLOW_THREADS;
10659n/a if (path->fd > -1)
10660n/a result = fsetxattr(path->fd, attribute->narrow,
10661n/a value->buf, value->len, flags);
10662n/a else if (follow_symlinks)
10663n/a result = setxattr(path->narrow, attribute->narrow,
10664n/a value->buf, value->len, flags);
10665n/a else
10666n/a result = lsetxattr(path->narrow, attribute->narrow,
10667n/a value->buf, value->len, flags);
10668n/a Py_END_ALLOW_THREADS;
10669n/a
10670n/a if (result) {
10671n/a path_error(path);
10672n/a return NULL;
10673n/a }
10674n/a
10675n/a Py_RETURN_NONE;
10676n/a}
10677n/a
10678n/a
10679n/a/*[clinic input]
10680n/aos.removexattr
10681n/a
10682n/a path: path_t(allow_fd=True)
10683n/a attribute: path_t
10684n/a *
10685n/a follow_symlinks: bool = True
10686n/a
10687n/aRemove extended attribute attribute on path.
10688n/a
10689n/apath may be either a string or an open file descriptor.
10690n/aIf follow_symlinks is False, and the last element of the path is a symbolic
10691n/a link, removexattr will modify the symbolic link itself instead of the file
10692n/a the link points to.
10693n/a
10694n/a[clinic start generated code]*/
10695n/a
10696n/astatic PyObject *
10697n/aos_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
10698n/a int follow_symlinks)
10699n/a/*[clinic end generated code: output=521a51817980cda6 input=cdb54834161e3329]*/
10700n/a{
10701n/a ssize_t result;
10702n/a
10703n/a if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
10704n/a return NULL;
10705n/a
10706n/a Py_BEGIN_ALLOW_THREADS;
10707n/a if (path->fd > -1)
10708n/a result = fremovexattr(path->fd, attribute->narrow);
10709n/a else if (follow_symlinks)
10710n/a result = removexattr(path->narrow, attribute->narrow);
10711n/a else
10712n/a result = lremovexattr(path->narrow, attribute->narrow);
10713n/a Py_END_ALLOW_THREADS;
10714n/a
10715n/a if (result) {
10716n/a return path_error(path);
10717n/a }
10718n/a
10719n/a Py_RETURN_NONE;
10720n/a}
10721n/a
10722n/a
10723n/a/*[clinic input]
10724n/aos.listxattr
10725n/a
10726n/a path: path_t(allow_fd=True, nullable=True) = None
10727n/a *
10728n/a follow_symlinks: bool = True
10729n/a
10730n/aReturn a list of extended attributes on path.
10731n/a
10732n/apath may be either None, a string, or an open file descriptor.
10733n/aif path is None, listxattr will examine the current directory.
10734n/aIf follow_symlinks is False, and the last element of the path is a symbolic
10735n/a link, listxattr will examine the symbolic link itself instead of the file
10736n/a the link points to.
10737n/a[clinic start generated code]*/
10738n/a
10739n/astatic PyObject *
10740n/aos_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
10741n/a/*[clinic end generated code: output=bebdb4e2ad0ce435 input=08cca53ac0b07c13]*/
10742n/a{
10743n/a Py_ssize_t i;
10744n/a PyObject *result = NULL;
10745n/a const char *name;
10746n/a char *buffer = NULL;
10747n/a
10748n/a if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
10749n/a goto exit;
10750n/a
10751n/a name = path->narrow ? path->narrow : ".";
10752n/a
10753n/a for (i = 0; ; i++) {
10754n/a const char *start, *trace, *end;
10755n/a ssize_t length;
10756n/a static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
10757n/a Py_ssize_t buffer_size = buffer_sizes[i];
10758n/a if (!buffer_size) {
10759n/a /* ERANGE */
10760n/a path_error(path);
10761n/a break;
10762n/a }
10763n/a buffer = PyMem_MALLOC(buffer_size);
10764n/a if (!buffer) {
10765n/a PyErr_NoMemory();
10766n/a break;
10767n/a }
10768n/a
10769n/a Py_BEGIN_ALLOW_THREADS;
10770n/a if (path->fd > -1)
10771n/a length = flistxattr(path->fd, buffer, buffer_size);
10772n/a else if (follow_symlinks)
10773n/a length = listxattr(name, buffer, buffer_size);
10774n/a else
10775n/a length = llistxattr(name, buffer, buffer_size);
10776n/a Py_END_ALLOW_THREADS;
10777n/a
10778n/a if (length < 0) {
10779n/a if (errno == ERANGE) {
10780n/a PyMem_FREE(buffer);
10781n/a buffer = NULL;
10782n/a continue;
10783n/a }
10784n/a path_error(path);
10785n/a break;
10786n/a }
10787n/a
10788n/a result = PyList_New(0);
10789n/a if (!result) {
10790n/a goto exit;
10791n/a }
10792n/a
10793n/a end = buffer + length;
10794n/a for (trace = start = buffer; trace != end; trace++) {
10795n/a if (!*trace) {
10796n/a int error;
10797n/a PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
10798n/a trace - start);
10799n/a if (!attribute) {
10800n/a Py_DECREF(result);
10801n/a result = NULL;
10802n/a goto exit;
10803n/a }
10804n/a error = PyList_Append(result, attribute);
10805n/a Py_DECREF(attribute);
10806n/a if (error) {
10807n/a Py_DECREF(result);
10808n/a result = NULL;
10809n/a goto exit;
10810n/a }
10811n/a start = trace + 1;
10812n/a }
10813n/a }
10814n/a break;
10815n/a }
10816n/aexit:
10817n/a if (buffer)
10818n/a PyMem_FREE(buffer);
10819n/a return result;
10820n/a}
10821n/a#endif /* USE_XATTRS */
10822n/a
10823n/a
10824n/a/*[clinic input]
10825n/aos.urandom
10826n/a
10827n/a size: Py_ssize_t
10828n/a /
10829n/a
10830n/aReturn a bytes object containing random bytes suitable for cryptographic use.
10831n/a[clinic start generated code]*/
10832n/a
10833n/astatic PyObject *
10834n/aos_urandom_impl(PyObject *module, Py_ssize_t size)
10835n/a/*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
10836n/a{
10837n/a PyObject *bytes;
10838n/a int result;
10839n/a
10840n/a if (size < 0)
10841n/a return PyErr_Format(PyExc_ValueError,
10842n/a "negative argument not allowed");
10843n/a bytes = PyBytes_FromStringAndSize(NULL, size);
10844n/a if (bytes == NULL)
10845n/a return NULL;
10846n/a
10847n/a result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
10848n/a if (result == -1) {
10849n/a Py_DECREF(bytes);
10850n/a return NULL;
10851n/a }
10852n/a return bytes;
10853n/a}
10854n/a
10855n/a/* Terminal size querying */
10856n/a
10857n/astatic PyTypeObject TerminalSizeType;
10858n/a
10859n/aPyDoc_STRVAR(TerminalSize_docstring,
10860n/a "A tuple of (columns, lines) for holding terminal window size");
10861n/a
10862n/astatic PyStructSequence_Field TerminalSize_fields[] = {
10863n/a {"columns", "width of the terminal window in characters"},
10864n/a {"lines", "height of the terminal window in characters"},
10865n/a {NULL, NULL}
10866n/a};
10867n/a
10868n/astatic PyStructSequence_Desc TerminalSize_desc = {
10869n/a "os.terminal_size",
10870n/a TerminalSize_docstring,
10871n/a TerminalSize_fields,
10872n/a 2,
10873n/a};
10874n/a
10875n/a#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
10876n/a/* AC 3.5: fd should accept None */
10877n/aPyDoc_STRVAR(termsize__doc__,
10878n/a "Return the size of the terminal window as (columns, lines).\n" \
10879n/a "\n" \
10880n/a "The optional argument fd (default standard output) specifies\n" \
10881n/a "which file descriptor should be queried.\n" \
10882n/a "\n" \
10883n/a "If the file descriptor is not connected to a terminal, an OSError\n" \
10884n/a "is thrown.\n" \
10885n/a "\n" \
10886n/a "This function will only be defined if an implementation is\n" \
10887n/a "available for this system.\n" \
10888n/a "\n" \
10889n/a "shutil.get_terminal_size is the high-level function which should \n" \
10890n/a "normally be used, os.get_terminal_size is the low-level implementation.");
10891n/a
10892n/astatic PyObject*
10893n/aget_terminal_size(PyObject *self, PyObject *args)
10894n/a{
10895n/a int columns, lines;
10896n/a PyObject *termsize;
10897n/a
10898n/a int fd = fileno(stdout);
10899n/a /* Under some conditions stdout may not be connected and
10900n/a * fileno(stdout) may point to an invalid file descriptor. For example
10901n/a * GUI apps don't have valid standard streams by default.
10902n/a *
10903n/a * If this happens, and the optional fd argument is not present,
10904n/a * the ioctl below will fail returning EBADF. This is what we want.
10905n/a */
10906n/a
10907n/a if (!PyArg_ParseTuple(args, "|i", &fd))
10908n/a return NULL;
10909n/a
10910n/a#ifdef TERMSIZE_USE_IOCTL
10911n/a {
10912n/a struct winsize w;
10913n/a if (ioctl(fd, TIOCGWINSZ, &w))
10914n/a return PyErr_SetFromErrno(PyExc_OSError);
10915n/a columns = w.ws_col;
10916n/a lines = w.ws_row;
10917n/a }
10918n/a#endif /* TERMSIZE_USE_IOCTL */
10919n/a
10920n/a#ifdef TERMSIZE_USE_CONIO
10921n/a {
10922n/a DWORD nhandle;
10923n/a HANDLE handle;
10924n/a CONSOLE_SCREEN_BUFFER_INFO csbi;
10925n/a switch (fd) {
10926n/a case 0: nhandle = STD_INPUT_HANDLE;
10927n/a break;
10928n/a case 1: nhandle = STD_OUTPUT_HANDLE;
10929n/a break;
10930n/a case 2: nhandle = STD_ERROR_HANDLE;
10931n/a break;
10932n/a default:
10933n/a return PyErr_Format(PyExc_ValueError, "bad file descriptor");
10934n/a }
10935n/a handle = GetStdHandle(nhandle);
10936n/a if (handle == NULL)
10937n/a return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
10938n/a if (handle == INVALID_HANDLE_VALUE)
10939n/a return PyErr_SetFromWindowsErr(0);
10940n/a
10941n/a if (!GetConsoleScreenBufferInfo(handle, &csbi))
10942n/a return PyErr_SetFromWindowsErr(0);
10943n/a
10944n/a columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
10945n/a lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
10946n/a }
10947n/a#endif /* TERMSIZE_USE_CONIO */
10948n/a
10949n/a termsize = PyStructSequence_New(&TerminalSizeType);
10950n/a if (termsize == NULL)
10951n/a return NULL;
10952n/a PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
10953n/a PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
10954n/a if (PyErr_Occurred()) {
10955n/a Py_DECREF(termsize);
10956n/a return NULL;
10957n/a }
10958n/a return termsize;
10959n/a}
10960n/a#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
10961n/a
10962n/a
10963n/a/*[clinic input]
10964n/aos.cpu_count
10965n/a
10966n/aReturn the number of CPUs in the system; return None if indeterminable.
10967n/a
10968n/aThis number is not equivalent to the number of CPUs the current process can
10969n/ause. The number of usable CPUs can be obtained with
10970n/a``len(os.sched_getaffinity(0))``
10971n/a[clinic start generated code]*/
10972n/a
10973n/astatic PyObject *
10974n/aos_cpu_count_impl(PyObject *module)
10975n/a/*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
10976n/a{
10977n/a int ncpu = 0;
10978n/a#ifdef MS_WINDOWS
10979n/a SYSTEM_INFO sysinfo;
10980n/a GetSystemInfo(&sysinfo);
10981n/a ncpu = sysinfo.dwNumberOfProcessors;
10982n/a#elif defined(__hpux)
10983n/a ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
10984n/a#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
10985n/a ncpu = sysconf(_SC_NPROCESSORS_ONLN);
10986n/a#elif defined(__DragonFly__) || \
10987n/a defined(__OpenBSD__) || \
10988n/a defined(__FreeBSD__) || \
10989n/a defined(__NetBSD__) || \
10990n/a defined(__APPLE__)
10991n/a int mib[2];
10992n/a size_t len = sizeof(ncpu);
10993n/a mib[0] = CTL_HW;
10994n/a mib[1] = HW_NCPU;
10995n/a if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
10996n/a ncpu = 0;
10997n/a#endif
10998n/a if (ncpu >= 1)
10999n/a return PyLong_FromLong(ncpu);
11000n/a else
11001n/a Py_RETURN_NONE;
11002n/a}
11003n/a
11004n/a
11005n/a/*[clinic input]
11006n/aos.get_inheritable -> bool
11007n/a
11008n/a fd: int
11009n/a /
11010n/a
11011n/aGet the close-on-exe flag of the specified file descriptor.
11012n/a[clinic start generated code]*/
11013n/a
11014n/astatic int
11015n/aos_get_inheritable_impl(PyObject *module, int fd)
11016n/a/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
11017n/a{
11018n/a int return_value;
11019n/a _Py_BEGIN_SUPPRESS_IPH
11020n/a return_value = _Py_get_inheritable(fd);
11021n/a _Py_END_SUPPRESS_IPH
11022n/a return return_value;
11023n/a}
11024n/a
11025n/a
11026n/a/*[clinic input]
11027n/aos.set_inheritable
11028n/a fd: int
11029n/a inheritable: int
11030n/a /
11031n/a
11032n/aSet the inheritable flag of the specified file descriptor.
11033n/a[clinic start generated code]*/
11034n/a
11035n/astatic PyObject *
11036n/aos_set_inheritable_impl(PyObject *module, int fd, int inheritable)
11037n/a/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
11038n/a{
11039n/a int result;
11040n/a
11041n/a _Py_BEGIN_SUPPRESS_IPH
11042n/a result = _Py_set_inheritable(fd, inheritable, NULL);
11043n/a _Py_END_SUPPRESS_IPH
11044n/a if (result < 0)
11045n/a return NULL;
11046n/a Py_RETURN_NONE;
11047n/a}
11048n/a
11049n/a
11050n/a#ifdef MS_WINDOWS
11051n/a/*[clinic input]
11052n/aos.get_handle_inheritable -> bool
11053n/a handle: intptr_t
11054n/a /
11055n/a
11056n/aGet the close-on-exe flag of the specified file descriptor.
11057n/a[clinic start generated code]*/
11058n/a
11059n/astatic int
11060n/aos_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
11061n/a/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
11062n/a{
11063n/a DWORD flags;
11064n/a
11065n/a if (!GetHandleInformation((HANDLE)handle, &flags)) {
11066n/a PyErr_SetFromWindowsErr(0);
11067n/a return -1;
11068n/a }
11069n/a
11070n/a return flags & HANDLE_FLAG_INHERIT;
11071n/a}
11072n/a
11073n/a
11074n/a/*[clinic input]
11075n/aos.set_handle_inheritable
11076n/a handle: intptr_t
11077n/a inheritable: bool
11078n/a /
11079n/a
11080n/aSet the inheritable flag of the specified handle.
11081n/a[clinic start generated code]*/
11082n/a
11083n/astatic PyObject *
11084n/aos_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
11085n/a int inheritable)
11086n/a/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
11087n/a{
11088n/a DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
11089n/a if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
11090n/a PyErr_SetFromWindowsErr(0);
11091n/a return NULL;
11092n/a }
11093n/a Py_RETURN_NONE;
11094n/a}
11095n/a#endif /* MS_WINDOWS */
11096n/a
11097n/a#ifndef MS_WINDOWS
11098n/aPyDoc_STRVAR(get_blocking__doc__,
11099n/a "get_blocking(fd) -> bool\n" \
11100n/a "\n" \
11101n/a "Get the blocking mode of the file descriptor:\n" \
11102n/a "False if the O_NONBLOCK flag is set, True if the flag is cleared.");
11103n/a
11104n/astatic PyObject*
11105n/aposix_get_blocking(PyObject *self, PyObject *args)
11106n/a{
11107n/a int fd;
11108n/a int blocking;
11109n/a
11110n/a if (!PyArg_ParseTuple(args, "i:get_blocking", &fd))
11111n/a return NULL;
11112n/a
11113n/a _Py_BEGIN_SUPPRESS_IPH
11114n/a blocking = _Py_get_blocking(fd);
11115n/a _Py_END_SUPPRESS_IPH
11116n/a if (blocking < 0)
11117n/a return NULL;
11118n/a return PyBool_FromLong(blocking);
11119n/a}
11120n/a
11121n/aPyDoc_STRVAR(set_blocking__doc__,
11122n/a "set_blocking(fd, blocking)\n" \
11123n/a "\n" \
11124n/a "Set the blocking mode of the specified file descriptor.\n" \
11125n/a "Set the O_NONBLOCK flag if blocking is False,\n" \
11126n/a "clear the O_NONBLOCK flag otherwise.");
11127n/a
11128n/astatic PyObject*
11129n/aposix_set_blocking(PyObject *self, PyObject *args)
11130n/a{
11131n/a int fd, blocking, result;
11132n/a
11133n/a if (!PyArg_ParseTuple(args, "ii:set_blocking", &fd, &blocking))
11134n/a return NULL;
11135n/a
11136n/a _Py_BEGIN_SUPPRESS_IPH
11137n/a result = _Py_set_blocking(fd, blocking);
11138n/a _Py_END_SUPPRESS_IPH
11139n/a if (result < 0)
11140n/a return NULL;
11141n/a Py_RETURN_NONE;
11142n/a}
11143n/a#endif /* !MS_WINDOWS */
11144n/a
11145n/a
11146n/a/*[clinic input]
11147n/aclass os.DirEntry "DirEntry *" "&DirEntryType"
11148n/a[clinic start generated code]*/
11149n/a/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3138f09f7c683f1d]*/
11150n/a
11151n/atypedef struct {
11152n/a PyObject_HEAD
11153n/a PyObject *name;
11154n/a PyObject *path;
11155n/a PyObject *stat;
11156n/a PyObject *lstat;
11157n/a#ifdef MS_WINDOWS
11158n/a struct _Py_stat_struct win32_lstat;
11159n/a __int64 win32_file_index;
11160n/a int got_file_index;
11161n/a#else /* POSIX */
11162n/a#ifdef HAVE_DIRENT_D_TYPE
11163n/a unsigned char d_type;
11164n/a#endif
11165n/a ino_t d_ino;
11166n/a#endif
11167n/a} DirEntry;
11168n/a
11169n/astatic void
11170n/aDirEntry_dealloc(DirEntry *entry)
11171n/a{
11172n/a Py_XDECREF(entry->name);
11173n/a Py_XDECREF(entry->path);
11174n/a Py_XDECREF(entry->stat);
11175n/a Py_XDECREF(entry->lstat);
11176n/a Py_TYPE(entry)->tp_free((PyObject *)entry);
11177n/a}
11178n/a
11179n/a/* Forward reference */
11180n/astatic int
11181n/aDirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits);
11182n/a
11183n/a/*[clinic input]
11184n/aos.DirEntry.is_symlink -> bool
11185n/a
11186n/aReturn True if the entry is a symbolic link; cached per entry.
11187n/a[clinic start generated code]*/
11188n/a
11189n/astatic int
11190n/aos_DirEntry_is_symlink_impl(DirEntry *self)
11191n/a/*[clinic end generated code: output=42244667d7bcfc25 input=1605a1b4b96976c3]*/
11192n/a{
11193n/a#ifdef MS_WINDOWS
11194n/a return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
11195n/a#elif defined(HAVE_DIRENT_D_TYPE)
11196n/a /* POSIX */
11197n/a if (self->d_type != DT_UNKNOWN)
11198n/a return self->d_type == DT_LNK;
11199n/a else
11200n/a return DirEntry_test_mode(self, 0, S_IFLNK);
11201n/a#else
11202n/a /* POSIX without d_type */
11203n/a return DirEntry_test_mode(self, 0, S_IFLNK);
11204n/a#endif
11205n/a}
11206n/a
11207n/astatic PyObject *
11208n/aDirEntry_fetch_stat(DirEntry *self, int follow_symlinks)
11209n/a{
11210n/a int result;
11211n/a STRUCT_STAT st;
11212n/a PyObject *ub;
11213n/a
11214n/a#ifdef MS_WINDOWS
11215n/a if (PyUnicode_FSDecoder(self->path, &ub)) {
11216n/a const wchar_t *path = PyUnicode_AsUnicode(ub);
11217n/a#else /* POSIX */
11218n/a if (PyUnicode_FSConverter(self->path, &ub)) {
11219n/a const char *path = PyBytes_AS_STRING(ub);
11220n/a#endif
11221n/a if (follow_symlinks)
11222n/a result = STAT(path, &st);
11223n/a else
11224n/a result = LSTAT(path, &st);
11225n/a Py_DECREF(ub);
11226n/a } else
11227n/a return NULL;
11228n/a
11229n/a if (result != 0)
11230n/a return path_object_error(self->path);
11231n/a
11232n/a return _pystat_fromstructstat(&st);
11233n/a}
11234n/a
11235n/astatic PyObject *
11236n/aDirEntry_get_lstat(DirEntry *self)
11237n/a{
11238n/a if (!self->lstat) {
11239n/a#ifdef MS_WINDOWS
11240n/a self->lstat = _pystat_fromstructstat(&self->win32_lstat);
11241n/a#else /* POSIX */
11242n/a self->lstat = DirEntry_fetch_stat(self, 0);
11243n/a#endif
11244n/a }
11245n/a Py_XINCREF(self->lstat);
11246n/a return self->lstat;
11247n/a}
11248n/a
11249n/a/*[clinic input]
11250n/aos.DirEntry.stat
11251n/a *
11252n/a follow_symlinks: bool = True
11253n/a
11254n/aReturn stat_result object for the entry; cached per entry.
11255n/a[clinic start generated code]*/
11256n/a
11257n/astatic PyObject *
11258n/aos_DirEntry_stat_impl(DirEntry *self, int follow_symlinks)
11259n/a/*[clinic end generated code: output=008593b3a6d01305 input=280d14c1d6f1d00d]*/
11260n/a{
11261n/a if (!follow_symlinks)
11262n/a return DirEntry_get_lstat(self);
11263n/a
11264n/a if (!self->stat) {
11265n/a int result = os_DirEntry_is_symlink_impl(self);
11266n/a if (result == -1)
11267n/a return NULL;
11268n/a else if (result)
11269n/a self->stat = DirEntry_fetch_stat(self, 1);
11270n/a else
11271n/a self->stat = DirEntry_get_lstat(self);
11272n/a }
11273n/a
11274n/a Py_XINCREF(self->stat);
11275n/a return self->stat;
11276n/a}
11277n/a
11278n/a/* Set exception and return -1 on error, 0 for False, 1 for True */
11279n/astatic int
11280n/aDirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits)
11281n/a{
11282n/a PyObject *stat = NULL;
11283n/a PyObject *st_mode = NULL;
11284n/a long mode;
11285n/a int result;
11286n/a#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
11287n/a int is_symlink;
11288n/a int need_stat;
11289n/a#endif
11290n/a#ifdef MS_WINDOWS
11291n/a unsigned long dir_bits;
11292n/a#endif
11293n/a _Py_IDENTIFIER(st_mode);
11294n/a
11295n/a#ifdef MS_WINDOWS
11296n/a is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
11297n/a need_stat = follow_symlinks && is_symlink;
11298n/a#elif defined(HAVE_DIRENT_D_TYPE)
11299n/a is_symlink = self->d_type == DT_LNK;
11300n/a need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
11301n/a#endif
11302n/a
11303n/a#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
11304n/a if (need_stat) {
11305n/a#endif
11306n/a stat = os_DirEntry_stat_impl(self, follow_symlinks);
11307n/a if (!stat) {
11308n/a if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
11309n/a /* If file doesn't exist (anymore), then return False
11310n/a (i.e., say it's not a file/directory) */
11311n/a PyErr_Clear();
11312n/a return 0;
11313n/a }
11314n/a goto error;
11315n/a }
11316n/a st_mode = _PyObject_GetAttrId(stat, &PyId_st_mode);
11317n/a if (!st_mode)
11318n/a goto error;
11319n/a
11320n/a mode = PyLong_AsLong(st_mode);
11321n/a if (mode == -1 && PyErr_Occurred())
11322n/a goto error;
11323n/a Py_CLEAR(st_mode);
11324n/a Py_CLEAR(stat);
11325n/a result = (mode & S_IFMT) == mode_bits;
11326n/a#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
11327n/a }
11328n/a else if (is_symlink) {
11329n/a assert(mode_bits != S_IFLNK);
11330n/a result = 0;
11331n/a }
11332n/a else {
11333n/a assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
11334n/a#ifdef MS_WINDOWS
11335n/a dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
11336n/a if (mode_bits == S_IFDIR)
11337n/a result = dir_bits != 0;
11338n/a else
11339n/a result = dir_bits == 0;
11340n/a#else /* POSIX */
11341n/a if (mode_bits == S_IFDIR)
11342n/a result = self->d_type == DT_DIR;
11343n/a else
11344n/a result = self->d_type == DT_REG;
11345n/a#endif
11346n/a }
11347n/a#endif
11348n/a
11349n/a return result;
11350n/a
11351n/aerror:
11352n/a Py_XDECREF(st_mode);
11353n/a Py_XDECREF(stat);
11354n/a return -1;
11355n/a}
11356n/a
11357n/a/*[clinic input]
11358n/aos.DirEntry.is_dir -> bool
11359n/a *
11360n/a follow_symlinks: bool = True
11361n/a
11362n/aReturn True if the entry is a directory; cached per entry.
11363n/a[clinic start generated code]*/
11364n/a
11365n/astatic int
11366n/aos_DirEntry_is_dir_impl(DirEntry *self, int follow_symlinks)
11367n/a/*[clinic end generated code: output=ad2e8d54365da287 input=0135232766f53f58]*/
11368n/a{
11369n/a return DirEntry_test_mode(self, follow_symlinks, S_IFDIR);
11370n/a}
11371n/a
11372n/a/*[clinic input]
11373n/aos.DirEntry.is_file -> bool
11374n/a *
11375n/a follow_symlinks: bool = True
11376n/a
11377n/aReturn True if the entry is a file; cached per entry.
11378n/a[clinic start generated code]*/
11379n/a
11380n/astatic int
11381n/aos_DirEntry_is_file_impl(DirEntry *self, int follow_symlinks)
11382n/a/*[clinic end generated code: output=8462ade481d8a476 input=0dc90be168b041ee]*/
11383n/a{
11384n/a return DirEntry_test_mode(self, follow_symlinks, S_IFREG);
11385n/a}
11386n/a
11387n/a/*[clinic input]
11388n/aos.DirEntry.inode
11389n/a
11390n/aReturn inode of the entry; cached per entry.
11391n/a[clinic start generated code]*/
11392n/a
11393n/astatic PyObject *
11394n/aos_DirEntry_inode_impl(DirEntry *self)
11395n/a/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
11396n/a{
11397n/a#ifdef MS_WINDOWS
11398n/a if (!self->got_file_index) {
11399n/a PyObject *unicode;
11400n/a const wchar_t *path;
11401n/a STRUCT_STAT stat;
11402n/a int result;
11403n/a
11404n/a if (!PyUnicode_FSDecoder(self->path, &unicode))
11405n/a return NULL;
11406n/a path = PyUnicode_AsUnicode(unicode);
11407n/a result = LSTAT(path, &stat);
11408n/a Py_DECREF(unicode);
11409n/a
11410n/a if (result != 0)
11411n/a return path_object_error(self->path);
11412n/a
11413n/a self->win32_file_index = stat.st_ino;
11414n/a self->got_file_index = 1;
11415n/a }
11416n/a return PyLong_FromLongLong((long long)self->win32_file_index);
11417n/a#else /* POSIX */
11418n/a#ifdef HAVE_LARGEFILE_SUPPORT
11419n/a return PyLong_FromLongLong((long long)self->d_ino);
11420n/a#else
11421n/a return PyLong_FromLong((long)self->d_ino);
11422n/a#endif
11423n/a#endif
11424n/a}
11425n/a
11426n/astatic PyObject *
11427n/aDirEntry_repr(DirEntry *self)
11428n/a{
11429n/a return PyUnicode_FromFormat("<DirEntry %R>", self->name);
11430n/a}
11431n/a
11432n/a/*[clinic input]
11433n/aos.DirEntry.__fspath__
11434n/a
11435n/aReturns the path for the entry.
11436n/a[clinic start generated code]*/
11437n/a
11438n/astatic PyObject *
11439n/aos_DirEntry___fspath___impl(DirEntry *self)
11440n/a/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
11441n/a{
11442n/a Py_INCREF(self->path);
11443n/a return self->path;
11444n/a}
11445n/a
11446n/astatic PyMemberDef DirEntry_members[] = {
11447n/a {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
11448n/a "the entry's base filename, relative to scandir() \"path\" argument"},
11449n/a {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
11450n/a "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
11451n/a {NULL}
11452n/a};
11453n/a
11454n/a#include "clinic/posixmodule.c.h"
11455n/a
11456n/astatic PyMethodDef DirEntry_methods[] = {
11457n/a OS_DIRENTRY_IS_DIR_METHODDEF
11458n/a OS_DIRENTRY_IS_FILE_METHODDEF
11459n/a OS_DIRENTRY_IS_SYMLINK_METHODDEF
11460n/a OS_DIRENTRY_STAT_METHODDEF
11461n/a OS_DIRENTRY_INODE_METHODDEF
11462n/a OS_DIRENTRY___FSPATH___METHODDEF
11463n/a {NULL}
11464n/a};
11465n/a
11466n/astatic PyTypeObject DirEntryType = {
11467n/a PyVarObject_HEAD_INIT(NULL, 0)
11468n/a MODNAME ".DirEntry", /* tp_name */
11469n/a sizeof(DirEntry), /* tp_basicsize */
11470n/a 0, /* tp_itemsize */
11471n/a /* methods */
11472n/a (destructor)DirEntry_dealloc, /* tp_dealloc */
11473n/a 0, /* tp_print */
11474n/a 0, /* tp_getattr */
11475n/a 0, /* tp_setattr */
11476n/a 0, /* tp_compare */
11477n/a (reprfunc)DirEntry_repr, /* tp_repr */
11478n/a 0, /* tp_as_number */
11479n/a 0, /* tp_as_sequence */
11480n/a 0, /* tp_as_mapping */
11481n/a 0, /* tp_hash */
11482n/a 0, /* tp_call */
11483n/a 0, /* tp_str */
11484n/a 0, /* tp_getattro */
11485n/a 0, /* tp_setattro */
11486n/a 0, /* tp_as_buffer */
11487n/a Py_TPFLAGS_DEFAULT, /* tp_flags */
11488n/a 0, /* tp_doc */
11489n/a 0, /* tp_traverse */
11490n/a 0, /* tp_clear */
11491n/a 0, /* tp_richcompare */
11492n/a 0, /* tp_weaklistoffset */
11493n/a 0, /* tp_iter */
11494n/a 0, /* tp_iternext */
11495n/a DirEntry_methods, /* tp_methods */
11496n/a DirEntry_members, /* tp_members */
11497n/a};
11498n/a
11499n/a#ifdef MS_WINDOWS
11500n/a
11501n/astatic wchar_t *
11502n/ajoin_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
11503n/a{
11504n/a Py_ssize_t path_len;
11505n/a Py_ssize_t size;
11506n/a wchar_t *result;
11507n/a wchar_t ch;
11508n/a
11509n/a if (!path_wide) { /* Default arg: "." */
11510n/a path_wide = L".";
11511n/a path_len = 1;
11512n/a }
11513n/a else {
11514n/a path_len = wcslen(path_wide);
11515n/a }
11516n/a
11517n/a /* The +1's are for the path separator and the NUL */
11518n/a size = path_len + 1 + wcslen(filename) + 1;
11519n/a result = PyMem_New(wchar_t, size);
11520n/a if (!result) {
11521n/a PyErr_NoMemory();
11522n/a return NULL;
11523n/a }
11524n/a wcscpy(result, path_wide);
11525n/a if (path_len > 0) {
11526n/a ch = result[path_len - 1];
11527n/a if (ch != SEP && ch != ALTSEP && ch != L':')
11528n/a result[path_len++] = SEP;
11529n/a wcscpy(result + path_len, filename);
11530n/a }
11531n/a return result;
11532n/a}
11533n/a
11534n/astatic PyObject *
11535n/aDirEntry_from_find_data(path_t *path, WIN32_FIND_DATAW *dataW)
11536n/a{
11537n/a DirEntry *entry;
11538n/a BY_HANDLE_FILE_INFORMATION file_info;
11539n/a ULONG reparse_tag;
11540n/a wchar_t *joined_path;
11541n/a
11542n/a entry = PyObject_New(DirEntry, &DirEntryType);
11543n/a if (!entry)
11544n/a return NULL;
11545n/a entry->name = NULL;
11546n/a entry->path = NULL;
11547n/a entry->stat = NULL;
11548n/a entry->lstat = NULL;
11549n/a entry->got_file_index = 0;
11550n/a
11551n/a entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
11552n/a if (!entry->name)
11553n/a goto error;
11554n/a if (path->narrow) {
11555n/a Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
11556n/a if (!entry->name)
11557n/a goto error;
11558n/a }
11559n/a
11560n/a joined_path = join_path_filenameW(path->wide, dataW->cFileName);
11561n/a if (!joined_path)
11562n/a goto error;
11563n/a
11564n/a entry->path = PyUnicode_FromWideChar(joined_path, -1);
11565n/a PyMem_Free(joined_path);
11566n/a if (!entry->path)
11567n/a goto error;
11568n/a if (path->narrow) {
11569n/a Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
11570n/a if (!entry->path)
11571n/a goto error;
11572n/a }
11573n/a
11574n/a find_data_to_file_info(dataW, &file_info, &reparse_tag);
11575n/a _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
11576n/a
11577n/a return (PyObject *)entry;
11578n/a
11579n/aerror:
11580n/a Py_DECREF(entry);
11581n/a return NULL;
11582n/a}
11583n/a
11584n/a#else /* POSIX */
11585n/a
11586n/astatic char *
11587n/ajoin_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
11588n/a{
11589n/a Py_ssize_t path_len;
11590n/a Py_ssize_t size;
11591n/a char *result;
11592n/a
11593n/a if (!path_narrow) { /* Default arg: "." */
11594n/a path_narrow = ".";
11595n/a path_len = 1;
11596n/a }
11597n/a else {
11598n/a path_len = strlen(path_narrow);
11599n/a }
11600n/a
11601n/a if (filename_len == -1)
11602n/a filename_len = strlen(filename);
11603n/a
11604n/a /* The +1's are for the path separator and the NUL */
11605n/a size = path_len + 1 + filename_len + 1;
11606n/a result = PyMem_New(char, size);
11607n/a if (!result) {
11608n/a PyErr_NoMemory();
11609n/a return NULL;
11610n/a }
11611n/a strcpy(result, path_narrow);
11612n/a if (path_len > 0 && result[path_len - 1] != '/')
11613n/a result[path_len++] = '/';
11614n/a strcpy(result + path_len, filename);
11615n/a return result;
11616n/a}
11617n/a
11618n/astatic PyObject *
11619n/aDirEntry_from_posix_info(path_t *path, const char *name, Py_ssize_t name_len,
11620n/a ino_t d_ino
11621n/a#ifdef HAVE_DIRENT_D_TYPE
11622n/a , unsigned char d_type
11623n/a#endif
11624n/a )
11625n/a{
11626n/a DirEntry *entry;
11627n/a char *joined_path;
11628n/a
11629n/a entry = PyObject_New(DirEntry, &DirEntryType);
11630n/a if (!entry)
11631n/a return NULL;
11632n/a entry->name = NULL;
11633n/a entry->path = NULL;
11634n/a entry->stat = NULL;
11635n/a entry->lstat = NULL;
11636n/a
11637n/a joined_path = join_path_filename(path->narrow, name, name_len);
11638n/a if (!joined_path)
11639n/a goto error;
11640n/a
11641n/a if (!path->narrow || !PyBytes_Check(path->object)) {
11642n/a entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
11643n/a entry->path = PyUnicode_DecodeFSDefault(joined_path);
11644n/a }
11645n/a else {
11646n/a entry->name = PyBytes_FromStringAndSize(name, name_len);
11647n/a entry->path = PyBytes_FromString(joined_path);
11648n/a }
11649n/a PyMem_Free(joined_path);
11650n/a if (!entry->name || !entry->path)
11651n/a goto error;
11652n/a
11653n/a#ifdef HAVE_DIRENT_D_TYPE
11654n/a entry->d_type = d_type;
11655n/a#endif
11656n/a entry->d_ino = d_ino;
11657n/a
11658n/a return (PyObject *)entry;
11659n/a
11660n/aerror:
11661n/a Py_XDECREF(entry);
11662n/a return NULL;
11663n/a}
11664n/a
11665n/a#endif
11666n/a
11667n/a
11668n/atypedef struct {
11669n/a PyObject_HEAD
11670n/a path_t path;
11671n/a#ifdef MS_WINDOWS
11672n/a HANDLE handle;
11673n/a WIN32_FIND_DATAW file_data;
11674n/a int first_time;
11675n/a#else /* POSIX */
11676n/a DIR *dirp;
11677n/a#endif
11678n/a} ScandirIterator;
11679n/a
11680n/a#ifdef MS_WINDOWS
11681n/a
11682n/astatic int
11683n/aScandirIterator_is_closed(ScandirIterator *iterator)
11684n/a{
11685n/a return iterator->handle == INVALID_HANDLE_VALUE;
11686n/a}
11687n/a
11688n/astatic void
11689n/aScandirIterator_closedir(ScandirIterator *iterator)
11690n/a{
11691n/a HANDLE handle = iterator->handle;
11692n/a
11693n/a if (handle == INVALID_HANDLE_VALUE)
11694n/a return;
11695n/a
11696n/a iterator->handle = INVALID_HANDLE_VALUE;
11697n/a Py_BEGIN_ALLOW_THREADS
11698n/a FindClose(handle);
11699n/a Py_END_ALLOW_THREADS
11700n/a}
11701n/a
11702n/astatic PyObject *
11703n/aScandirIterator_iternext(ScandirIterator *iterator)
11704n/a{
11705n/a WIN32_FIND_DATAW *file_data = &iterator->file_data;
11706n/a BOOL success;
11707n/a PyObject *entry;
11708n/a
11709n/a /* Happens if the iterator is iterated twice, or closed explicitly */
11710n/a if (iterator->handle == INVALID_HANDLE_VALUE)
11711n/a return NULL;
11712n/a
11713n/a while (1) {
11714n/a if (!iterator->first_time) {
11715n/a Py_BEGIN_ALLOW_THREADS
11716n/a success = FindNextFileW(iterator->handle, file_data);
11717n/a Py_END_ALLOW_THREADS
11718n/a if (!success) {
11719n/a /* Error or no more files */
11720n/a if (GetLastError() != ERROR_NO_MORE_FILES)
11721n/a path_error(&iterator->path);
11722n/a break;
11723n/a }
11724n/a }
11725n/a iterator->first_time = 0;
11726n/a
11727n/a /* Skip over . and .. */
11728n/a if (wcscmp(file_data->cFileName, L".") != 0 &&
11729n/a wcscmp(file_data->cFileName, L"..") != 0) {
11730n/a entry = DirEntry_from_find_data(&iterator->path, file_data);
11731n/a if (!entry)
11732n/a break;
11733n/a return entry;
11734n/a }
11735n/a
11736n/a /* Loop till we get a non-dot directory or finish iterating */
11737n/a }
11738n/a
11739n/a /* Error or no more files */
11740n/a ScandirIterator_closedir(iterator);
11741n/a return NULL;
11742n/a}
11743n/a
11744n/a#else /* POSIX */
11745n/a
11746n/astatic int
11747n/aScandirIterator_is_closed(ScandirIterator *iterator)
11748n/a{
11749n/a return !iterator->dirp;
11750n/a}
11751n/a
11752n/astatic void
11753n/aScandirIterator_closedir(ScandirIterator *iterator)
11754n/a{
11755n/a DIR *dirp = iterator->dirp;
11756n/a
11757n/a if (!dirp)
11758n/a return;
11759n/a
11760n/a iterator->dirp = NULL;
11761n/a Py_BEGIN_ALLOW_THREADS
11762n/a closedir(dirp);
11763n/a Py_END_ALLOW_THREADS
11764n/a return;
11765n/a}
11766n/a
11767n/astatic PyObject *
11768n/aScandirIterator_iternext(ScandirIterator *iterator)
11769n/a{
11770n/a struct dirent *direntp;
11771n/a Py_ssize_t name_len;
11772n/a int is_dot;
11773n/a PyObject *entry;
11774n/a
11775n/a /* Happens if the iterator is iterated twice, or closed explicitly */
11776n/a if (!iterator->dirp)
11777n/a return NULL;
11778n/a
11779n/a while (1) {
11780n/a errno = 0;
11781n/a Py_BEGIN_ALLOW_THREADS
11782n/a direntp = readdir(iterator->dirp);
11783n/a Py_END_ALLOW_THREADS
11784n/a
11785n/a if (!direntp) {
11786n/a /* Error or no more files */
11787n/a if (errno != 0)
11788n/a path_error(&iterator->path);
11789n/a break;
11790n/a }
11791n/a
11792n/a /* Skip over . and .. */
11793n/a name_len = NAMLEN(direntp);
11794n/a is_dot = direntp->d_name[0] == '.' &&
11795n/a (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
11796n/a if (!is_dot) {
11797n/a entry = DirEntry_from_posix_info(&iterator->path, direntp->d_name,
11798n/a name_len, direntp->d_ino
11799n/a#ifdef HAVE_DIRENT_D_TYPE
11800n/a , direntp->d_type
11801n/a#endif
11802n/a );
11803n/a if (!entry)
11804n/a break;
11805n/a return entry;
11806n/a }
11807n/a
11808n/a /* Loop till we get a non-dot directory or finish iterating */
11809n/a }
11810n/a
11811n/a /* Error or no more files */
11812n/a ScandirIterator_closedir(iterator);
11813n/a return NULL;
11814n/a}
11815n/a
11816n/a#endif
11817n/a
11818n/astatic PyObject *
11819n/aScandirIterator_close(ScandirIterator *self, PyObject *args)
11820n/a{
11821n/a ScandirIterator_closedir(self);
11822n/a Py_RETURN_NONE;
11823n/a}
11824n/a
11825n/astatic PyObject *
11826n/aScandirIterator_enter(PyObject *self, PyObject *args)
11827n/a{
11828n/a Py_INCREF(self);
11829n/a return self;
11830n/a}
11831n/a
11832n/astatic PyObject *
11833n/aScandirIterator_exit(ScandirIterator *self, PyObject *args)
11834n/a{
11835n/a ScandirIterator_closedir(self);
11836n/a Py_RETURN_NONE;
11837n/a}
11838n/a
11839n/astatic void
11840n/aScandirIterator_finalize(ScandirIterator *iterator)
11841n/a{
11842n/a PyObject *error_type, *error_value, *error_traceback;
11843n/a
11844n/a /* Save the current exception, if any. */
11845n/a PyErr_Fetch(&error_type, &error_value, &error_traceback);
11846n/a
11847n/a if (!ScandirIterator_is_closed(iterator)) {
11848n/a ScandirIterator_closedir(iterator);
11849n/a
11850n/a if (PyErr_ResourceWarning((PyObject *)iterator, 1,
11851n/a "unclosed scandir iterator %R", iterator)) {
11852n/a /* Spurious errors can appear at shutdown */
11853n/a if (PyErr_ExceptionMatches(PyExc_Warning)) {
11854n/a PyErr_WriteUnraisable((PyObject *) iterator);
11855n/a }
11856n/a }
11857n/a }
11858n/a
11859n/a path_cleanup(&iterator->path);
11860n/a
11861n/a /* Restore the saved exception. */
11862n/a PyErr_Restore(error_type, error_value, error_traceback);
11863n/a}
11864n/a
11865n/astatic void
11866n/aScandirIterator_dealloc(ScandirIterator *iterator)
11867n/a{
11868n/a if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
11869n/a return;
11870n/a
11871n/a Py_TYPE(iterator)->tp_free((PyObject *)iterator);
11872n/a}
11873n/a
11874n/astatic PyMethodDef ScandirIterator_methods[] = {
11875n/a {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
11876n/a {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
11877n/a {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
11878n/a {NULL}
11879n/a};
11880n/a
11881n/astatic PyTypeObject ScandirIteratorType = {
11882n/a PyVarObject_HEAD_INIT(NULL, 0)
11883n/a MODNAME ".ScandirIterator", /* tp_name */
11884n/a sizeof(ScandirIterator), /* tp_basicsize */
11885n/a 0, /* tp_itemsize */
11886n/a /* methods */
11887n/a (destructor)ScandirIterator_dealloc, /* tp_dealloc */
11888n/a 0, /* tp_print */
11889n/a 0, /* tp_getattr */
11890n/a 0, /* tp_setattr */
11891n/a 0, /* tp_compare */
11892n/a 0, /* tp_repr */
11893n/a 0, /* tp_as_number */
11894n/a 0, /* tp_as_sequence */
11895n/a 0, /* tp_as_mapping */
11896n/a 0, /* tp_hash */
11897n/a 0, /* tp_call */
11898n/a 0, /* tp_str */
11899n/a 0, /* tp_getattro */
11900n/a 0, /* tp_setattro */
11901n/a 0, /* tp_as_buffer */
11902n/a Py_TPFLAGS_DEFAULT
11903n/a | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */
11904n/a 0, /* tp_doc */
11905n/a 0, /* tp_traverse */
11906n/a 0, /* tp_clear */
11907n/a 0, /* tp_richcompare */
11908n/a 0, /* tp_weaklistoffset */
11909n/a PyObject_SelfIter, /* tp_iter */
11910n/a (iternextfunc)ScandirIterator_iternext, /* tp_iternext */
11911n/a ScandirIterator_methods, /* tp_methods */
11912n/a 0, /* tp_members */
11913n/a 0, /* tp_getset */
11914n/a 0, /* tp_base */
11915n/a 0, /* tp_dict */
11916n/a 0, /* tp_descr_get */
11917n/a 0, /* tp_descr_set */
11918n/a 0, /* tp_dictoffset */
11919n/a 0, /* tp_init */
11920n/a 0, /* tp_alloc */
11921n/a 0, /* tp_new */
11922n/a 0, /* tp_free */
11923n/a 0, /* tp_is_gc */
11924n/a 0, /* tp_bases */
11925n/a 0, /* tp_mro */
11926n/a 0, /* tp_cache */
11927n/a 0, /* tp_subclasses */
11928n/a 0, /* tp_weaklist */
11929n/a 0, /* tp_del */
11930n/a 0, /* tp_version_tag */
11931n/a (destructor)ScandirIterator_finalize, /* tp_finalize */
11932n/a};
11933n/a
11934n/a/*[clinic input]
11935n/aos.scandir
11936n/a
11937n/a path : path_t(nullable=True) = None
11938n/a
11939n/aReturn an iterator of DirEntry objects for given path.
11940n/a
11941n/apath can be specified as either str, bytes or path-like object. If path
11942n/ais bytes, the names of yielded DirEntry objects will also be bytes; in
11943n/aall other circumstances they will be str.
11944n/a
11945n/aIf path is None, uses the path='.'.
11946n/a[clinic start generated code]*/
11947n/a
11948n/astatic PyObject *
11949n/aos_scandir_impl(PyObject *module, path_t *path)
11950n/a/*[clinic end generated code: output=6eb2668b675ca89e input=e62b08b3cd41f604]*/
11951n/a{
11952n/a ScandirIterator *iterator;
11953n/a#ifdef MS_WINDOWS
11954n/a wchar_t *path_strW;
11955n/a#else
11956n/a const char *path_str;
11957n/a#endif
11958n/a
11959n/a iterator = PyObject_New(ScandirIterator, &ScandirIteratorType);
11960n/a if (!iterator)
11961n/a return NULL;
11962n/a
11963n/a#ifdef MS_WINDOWS
11964n/a iterator->handle = INVALID_HANDLE_VALUE;
11965n/a#else
11966n/a iterator->dirp = NULL;
11967n/a#endif
11968n/a
11969n/a memcpy(&iterator->path, path, sizeof(path_t));
11970n/a /* Move the ownership to iterator->path */
11971n/a path->object = NULL;
11972n/a path->cleanup = NULL;
11973n/a
11974n/a#ifdef MS_WINDOWS
11975n/a iterator->first_time = 1;
11976n/a
11977n/a path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
11978n/a if (!path_strW)
11979n/a goto error;
11980n/a
11981n/a Py_BEGIN_ALLOW_THREADS
11982n/a iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
11983n/a Py_END_ALLOW_THREADS
11984n/a
11985n/a PyMem_Free(path_strW);
11986n/a
11987n/a if (iterator->handle == INVALID_HANDLE_VALUE) {
11988n/a path_error(&iterator->path);
11989n/a goto error;
11990n/a }
11991n/a#else /* POSIX */
11992n/a if (iterator->path.narrow)
11993n/a path_str = iterator->path.narrow;
11994n/a else
11995n/a path_str = ".";
11996n/a
11997n/a errno = 0;
11998n/a Py_BEGIN_ALLOW_THREADS
11999n/a iterator->dirp = opendir(path_str);
12000n/a Py_END_ALLOW_THREADS
12001n/a
12002n/a if (!iterator->dirp) {
12003n/a path_error(&iterator->path);
12004n/a goto error;
12005n/a }
12006n/a#endif
12007n/a
12008n/a return (PyObject *)iterator;
12009n/a
12010n/aerror:
12011n/a Py_DECREF(iterator);
12012n/a return NULL;
12013n/a}
12014n/a
12015n/a/*
12016n/a Return the file system path representation of the object.
12017n/a
12018n/a If the object is str or bytes, then allow it to pass through with
12019n/a an incremented refcount. If the object defines __fspath__(), then
12020n/a return the result of that method. All other types raise a TypeError.
12021n/a*/
12022n/aPyObject *
12023n/aPyOS_FSPath(PyObject *path)
12024n/a{
12025n/a /* For error message reasons, this function is manually inlined in
12026n/a path_converter(). */
12027n/a _Py_IDENTIFIER(__fspath__);
12028n/a PyObject *func = NULL;
12029n/a PyObject *path_repr = NULL;
12030n/a
12031n/a if (PyUnicode_Check(path) || PyBytes_Check(path)) {
12032n/a Py_INCREF(path);
12033n/a return path;
12034n/a }
12035n/a
12036n/a func = _PyObject_LookupSpecial(path, &PyId___fspath__);
12037n/a if (NULL == func) {
12038n/a return PyErr_Format(PyExc_TypeError,
12039n/a "expected str, bytes or os.PathLike object, "
12040n/a "not %.200s",
12041n/a Py_TYPE(path)->tp_name);
12042n/a }
12043n/a
12044n/a path_repr = _PyObject_CallNoArg(func);
12045n/a Py_DECREF(func);
12046n/a if (NULL == path_repr) {
12047n/a return NULL;
12048n/a }
12049n/a
12050n/a if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
12051n/a PyErr_Format(PyExc_TypeError,
12052n/a "expected %.200s.__fspath__() to return str or bytes, "
12053n/a "not %.200s", Py_TYPE(path)->tp_name,
12054n/a Py_TYPE(path_repr)->tp_name);
12055n/a Py_DECREF(path_repr);
12056n/a return NULL;
12057n/a }
12058n/a
12059n/a return path_repr;
12060n/a}
12061n/a
12062n/a/*[clinic input]
12063n/aos.fspath
12064n/a
12065n/a path: object
12066n/a
12067n/aReturn the file system path representation of the object.
12068n/a
12069n/aIf the object is str or bytes, then allow it to pass through as-is. If the
12070n/aobject defines __fspath__(), then return the result of that method. All other
12071n/atypes raise a TypeError.
12072n/a[clinic start generated code]*/
12073n/a
12074n/astatic PyObject *
12075n/aos_fspath_impl(PyObject *module, PyObject *path)
12076n/a/*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
12077n/a{
12078n/a return PyOS_FSPath(path);
12079n/a}
12080n/a
12081n/a#ifdef HAVE_GETRANDOM_SYSCALL
12082n/a/*[clinic input]
12083n/aos.getrandom
12084n/a
12085n/a size: Py_ssize_t
12086n/a flags: int=0
12087n/a
12088n/aObtain a series of random bytes.
12089n/a[clinic start generated code]*/
12090n/a
12091n/astatic PyObject *
12092n/aos_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
12093n/a/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
12094n/a{
12095n/a PyObject *bytes;
12096n/a Py_ssize_t n;
12097n/a
12098n/a if (size < 0) {
12099n/a errno = EINVAL;
12100n/a return posix_error();
12101n/a }
12102n/a
12103n/a bytes = PyBytes_FromStringAndSize(NULL, size);
12104n/a if (bytes == NULL) {
12105n/a PyErr_NoMemory();
12106n/a return NULL;
12107n/a }
12108n/a
12109n/a while (1) {
12110n/a n = syscall(SYS_getrandom,
12111n/a PyBytes_AS_STRING(bytes),
12112n/a PyBytes_GET_SIZE(bytes),
12113n/a flags);
12114n/a if (n < 0 && errno == EINTR) {
12115n/a if (PyErr_CheckSignals() < 0) {
12116n/a goto error;
12117n/a }
12118n/a
12119n/a /* getrandom() was interrupted by a signal: retry */
12120n/a continue;
12121n/a }
12122n/a break;
12123n/a }
12124n/a
12125n/a if (n < 0) {
12126n/a PyErr_SetFromErrno(PyExc_OSError);
12127n/a goto error;
12128n/a }
12129n/a
12130n/a if (n != size) {
12131n/a _PyBytes_Resize(&bytes, n);
12132n/a }
12133n/a
12134n/a return bytes;
12135n/a
12136n/aerror:
12137n/a Py_DECREF(bytes);
12138n/a return NULL;
12139n/a}
12140n/a#endif /* HAVE_GETRANDOM_SYSCALL */
12141n/a
12142n/a
12143n/astatic PyMethodDef posix_methods[] = {
12144n/a
12145n/a OS_STAT_METHODDEF
12146n/a OS_ACCESS_METHODDEF
12147n/a OS_TTYNAME_METHODDEF
12148n/a OS_CHDIR_METHODDEF
12149n/a OS_CHFLAGS_METHODDEF
12150n/a OS_CHMOD_METHODDEF
12151n/a OS_FCHMOD_METHODDEF
12152n/a OS_LCHMOD_METHODDEF
12153n/a OS_CHOWN_METHODDEF
12154n/a OS_FCHOWN_METHODDEF
12155n/a OS_LCHOWN_METHODDEF
12156n/a OS_LCHFLAGS_METHODDEF
12157n/a OS_CHROOT_METHODDEF
12158n/a OS_CTERMID_METHODDEF
12159n/a OS_GETCWD_METHODDEF
12160n/a OS_GETCWDB_METHODDEF
12161n/a OS_LINK_METHODDEF
12162n/a OS_LISTDIR_METHODDEF
12163n/a OS_LSTAT_METHODDEF
12164n/a OS_MKDIR_METHODDEF
12165n/a OS_NICE_METHODDEF
12166n/a OS_GETPRIORITY_METHODDEF
12167n/a OS_SETPRIORITY_METHODDEF
12168n/a#ifdef HAVE_READLINK
12169n/a {"readlink", (PyCFunction)posix_readlink,
12170n/a METH_VARARGS | METH_KEYWORDS,
12171n/a readlink__doc__},
12172n/a#endif /* HAVE_READLINK */
12173n/a#if !defined(HAVE_READLINK) && defined(MS_WINDOWS)
12174n/a {"readlink", (PyCFunction)win_readlink,
12175n/a METH_VARARGS | METH_KEYWORDS,
12176n/a readlink__doc__},
12177n/a#endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */
12178n/a OS_RENAME_METHODDEF
12179n/a OS_REPLACE_METHODDEF
12180n/a OS_RMDIR_METHODDEF
12181n/a {"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__},
12182n/a OS_SYMLINK_METHODDEF
12183n/a OS_SYSTEM_METHODDEF
12184n/a OS_UMASK_METHODDEF
12185n/a OS_UNAME_METHODDEF
12186n/a OS_UNLINK_METHODDEF
12187n/a OS_REMOVE_METHODDEF
12188n/a OS_UTIME_METHODDEF
12189n/a OS_TIMES_METHODDEF
12190n/a OS__EXIT_METHODDEF
12191n/a OS_EXECV_METHODDEF
12192n/a OS_EXECVE_METHODDEF
12193n/a OS_SPAWNV_METHODDEF
12194n/a OS_SPAWNVE_METHODDEF
12195n/a OS_FORK1_METHODDEF
12196n/a OS_FORK_METHODDEF
12197n/a OS_SCHED_GET_PRIORITY_MAX_METHODDEF
12198n/a OS_SCHED_GET_PRIORITY_MIN_METHODDEF
12199n/a OS_SCHED_GETPARAM_METHODDEF
12200n/a OS_SCHED_GETSCHEDULER_METHODDEF
12201n/a OS_SCHED_RR_GET_INTERVAL_METHODDEF
12202n/a OS_SCHED_SETPARAM_METHODDEF
12203n/a OS_SCHED_SETSCHEDULER_METHODDEF
12204n/a OS_SCHED_YIELD_METHODDEF
12205n/a OS_SCHED_SETAFFINITY_METHODDEF
12206n/a OS_SCHED_GETAFFINITY_METHODDEF
12207n/a OS_OPENPTY_METHODDEF
12208n/a OS_FORKPTY_METHODDEF
12209n/a OS_GETEGID_METHODDEF
12210n/a OS_GETEUID_METHODDEF
12211n/a OS_GETGID_METHODDEF
12212n/a#ifdef HAVE_GETGROUPLIST
12213n/a {"getgrouplist", posix_getgrouplist, METH_VARARGS, posix_getgrouplist__doc__},
12214n/a#endif
12215n/a OS_GETGROUPS_METHODDEF
12216n/a OS_GETPID_METHODDEF
12217n/a OS_GETPGRP_METHODDEF
12218n/a OS_GETPPID_METHODDEF
12219n/a OS_GETUID_METHODDEF
12220n/a OS_GETLOGIN_METHODDEF
12221n/a OS_KILL_METHODDEF
12222n/a OS_KILLPG_METHODDEF
12223n/a OS_PLOCK_METHODDEF
12224n/a#ifdef MS_WINDOWS
12225n/a OS_STARTFILE_METHODDEF
12226n/a#endif
12227n/a OS_SETUID_METHODDEF
12228n/a OS_SETEUID_METHODDEF
12229n/a OS_SETREUID_METHODDEF
12230n/a OS_SETGID_METHODDEF
12231n/a OS_SETEGID_METHODDEF
12232n/a OS_SETREGID_METHODDEF
12233n/a OS_SETGROUPS_METHODDEF
12234n/a#ifdef HAVE_INITGROUPS
12235n/a {"initgroups", posix_initgroups, METH_VARARGS, posix_initgroups__doc__},
12236n/a#endif /* HAVE_INITGROUPS */
12237n/a OS_GETPGID_METHODDEF
12238n/a OS_SETPGRP_METHODDEF
12239n/a OS_WAIT_METHODDEF
12240n/a OS_WAIT3_METHODDEF
12241n/a OS_WAIT4_METHODDEF
12242n/a OS_WAITID_METHODDEF
12243n/a OS_WAITPID_METHODDEF
12244n/a OS_GETSID_METHODDEF
12245n/a OS_SETSID_METHODDEF
12246n/a OS_SETPGID_METHODDEF
12247n/a OS_TCGETPGRP_METHODDEF
12248n/a OS_TCSETPGRP_METHODDEF
12249n/a OS_OPEN_METHODDEF
12250n/a OS_CLOSE_METHODDEF
12251n/a OS_CLOSERANGE_METHODDEF
12252n/a OS_DEVICE_ENCODING_METHODDEF
12253n/a OS_DUP_METHODDEF
12254n/a OS_DUP2_METHODDEF
12255n/a OS_LOCKF_METHODDEF
12256n/a OS_LSEEK_METHODDEF
12257n/a OS_READ_METHODDEF
12258n/a OS_READV_METHODDEF
12259n/a OS_PREAD_METHODDEF
12260n/a OS_WRITE_METHODDEF
12261n/a OS_WRITEV_METHODDEF
12262n/a OS_PWRITE_METHODDEF
12263n/a#ifdef HAVE_SENDFILE
12264n/a {"sendfile", (PyCFunction)posix_sendfile, METH_VARARGS | METH_KEYWORDS,
12265n/a posix_sendfile__doc__},
12266n/a#endif
12267n/a OS_FSTAT_METHODDEF
12268n/a OS_ISATTY_METHODDEF
12269n/a OS_PIPE_METHODDEF
12270n/a OS_PIPE2_METHODDEF
12271n/a OS_MKFIFO_METHODDEF
12272n/a OS_MKNOD_METHODDEF
12273n/a OS_MAJOR_METHODDEF
12274n/a OS_MINOR_METHODDEF
12275n/a OS_MAKEDEV_METHODDEF
12276n/a OS_FTRUNCATE_METHODDEF
12277n/a OS_TRUNCATE_METHODDEF
12278n/a OS_POSIX_FALLOCATE_METHODDEF
12279n/a OS_POSIX_FADVISE_METHODDEF
12280n/a OS_PUTENV_METHODDEF
12281n/a OS_UNSETENV_METHODDEF
12282n/a OS_STRERROR_METHODDEF
12283n/a OS_FCHDIR_METHODDEF
12284n/a OS_FSYNC_METHODDEF
12285n/a OS_SYNC_METHODDEF
12286n/a OS_FDATASYNC_METHODDEF
12287n/a OS_WCOREDUMP_METHODDEF
12288n/a OS_WIFCONTINUED_METHODDEF
12289n/a OS_WIFSTOPPED_METHODDEF
12290n/a OS_WIFSIGNALED_METHODDEF
12291n/a OS_WIFEXITED_METHODDEF
12292n/a OS_WEXITSTATUS_METHODDEF
12293n/a OS_WTERMSIG_METHODDEF
12294n/a OS_WSTOPSIG_METHODDEF
12295n/a OS_FSTATVFS_METHODDEF
12296n/a OS_STATVFS_METHODDEF
12297n/a OS_CONFSTR_METHODDEF
12298n/a OS_SYSCONF_METHODDEF
12299n/a OS_FPATHCONF_METHODDEF
12300n/a OS_PATHCONF_METHODDEF
12301n/a OS_ABORT_METHODDEF
12302n/a OS__GETFULLPATHNAME_METHODDEF
12303n/a OS__ISDIR_METHODDEF
12304n/a OS__GETDISKUSAGE_METHODDEF
12305n/a OS__GETFINALPATHNAME_METHODDEF
12306n/a OS__GETVOLUMEPATHNAME_METHODDEF
12307n/a OS_GETLOADAVG_METHODDEF
12308n/a OS_URANDOM_METHODDEF
12309n/a OS_SETRESUID_METHODDEF
12310n/a OS_SETRESGID_METHODDEF
12311n/a OS_GETRESUID_METHODDEF
12312n/a OS_GETRESGID_METHODDEF
12313n/a
12314n/a OS_GETXATTR_METHODDEF
12315n/a OS_SETXATTR_METHODDEF
12316n/a OS_REMOVEXATTR_METHODDEF
12317n/a OS_LISTXATTR_METHODDEF
12318n/a
12319n/a#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
12320n/a {"get_terminal_size", get_terminal_size, METH_VARARGS, termsize__doc__},
12321n/a#endif
12322n/a OS_CPU_COUNT_METHODDEF
12323n/a OS_GET_INHERITABLE_METHODDEF
12324n/a OS_SET_INHERITABLE_METHODDEF
12325n/a OS_GET_HANDLE_INHERITABLE_METHODDEF
12326n/a OS_SET_HANDLE_INHERITABLE_METHODDEF
12327n/a#ifndef MS_WINDOWS
12328n/a {"get_blocking", posix_get_blocking, METH_VARARGS, get_blocking__doc__},
12329n/a {"set_blocking", posix_set_blocking, METH_VARARGS, set_blocking__doc__},
12330n/a#endif
12331n/a OS_SCANDIR_METHODDEF
12332n/a OS_FSPATH_METHODDEF
12333n/a OS_GETRANDOM_METHODDEF
12334n/a {NULL, NULL} /* Sentinel */
12335n/a};
12336n/a
12337n/a
12338n/a#if defined(HAVE_SYMLINK) && defined(MS_WINDOWS)
12339n/astatic int
12340n/aenable_symlink()
12341n/a{
12342n/a HANDLE tok;
12343n/a TOKEN_PRIVILEGES tok_priv;
12344n/a LUID luid;
12345n/a
12346n/a if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &tok))
12347n/a return 0;
12348n/a
12349n/a if (!LookupPrivilegeValue(NULL, SE_CREATE_SYMBOLIC_LINK_NAME, &luid))
12350n/a return 0;
12351n/a
12352n/a tok_priv.PrivilegeCount = 1;
12353n/a tok_priv.Privileges[0].Luid = luid;
12354n/a tok_priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
12355n/a
12356n/a if (!AdjustTokenPrivileges(tok, FALSE, &tok_priv,
12357n/a sizeof(TOKEN_PRIVILEGES),
12358n/a (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL))
12359n/a return 0;
12360n/a
12361n/a /* ERROR_NOT_ALL_ASSIGNED returned when the privilege can't be assigned. */
12362n/a return GetLastError() == ERROR_NOT_ALL_ASSIGNED ? 0 : 1;
12363n/a}
12364n/a#endif /* defined(HAVE_SYMLINK) && defined(MS_WINDOWS) */
12365n/a
12366n/astatic int
12367n/aall_ins(PyObject *m)
12368n/a{
12369n/a#ifdef F_OK
12370n/a if (PyModule_AddIntMacro(m, F_OK)) return -1;
12371n/a#endif
12372n/a#ifdef R_OK
12373n/a if (PyModule_AddIntMacro(m, R_OK)) return -1;
12374n/a#endif
12375n/a#ifdef W_OK
12376n/a if (PyModule_AddIntMacro(m, W_OK)) return -1;
12377n/a#endif
12378n/a#ifdef X_OK
12379n/a if (PyModule_AddIntMacro(m, X_OK)) return -1;
12380n/a#endif
12381n/a#ifdef NGROUPS_MAX
12382n/a if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
12383n/a#endif
12384n/a#ifdef TMP_MAX
12385n/a if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
12386n/a#endif
12387n/a#ifdef WCONTINUED
12388n/a if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
12389n/a#endif
12390n/a#ifdef WNOHANG
12391n/a if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
12392n/a#endif
12393n/a#ifdef WUNTRACED
12394n/a if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
12395n/a#endif
12396n/a#ifdef O_RDONLY
12397n/a if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
12398n/a#endif
12399n/a#ifdef O_WRONLY
12400n/a if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
12401n/a#endif
12402n/a#ifdef O_RDWR
12403n/a if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
12404n/a#endif
12405n/a#ifdef O_NDELAY
12406n/a if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
12407n/a#endif
12408n/a#ifdef O_NONBLOCK
12409n/a if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
12410n/a#endif
12411n/a#ifdef O_APPEND
12412n/a if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
12413n/a#endif
12414n/a#ifdef O_DSYNC
12415n/a if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
12416n/a#endif
12417n/a#ifdef O_RSYNC
12418n/a if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
12419n/a#endif
12420n/a#ifdef O_SYNC
12421n/a if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
12422n/a#endif
12423n/a#ifdef O_NOCTTY
12424n/a if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
12425n/a#endif
12426n/a#ifdef O_CREAT
12427n/a if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
12428n/a#endif
12429n/a#ifdef O_EXCL
12430n/a if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
12431n/a#endif
12432n/a#ifdef O_TRUNC
12433n/a if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
12434n/a#endif
12435n/a#ifdef O_BINARY
12436n/a if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
12437n/a#endif
12438n/a#ifdef O_TEXT
12439n/a if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
12440n/a#endif
12441n/a#ifdef O_XATTR
12442n/a if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
12443n/a#endif
12444n/a#ifdef O_LARGEFILE
12445n/a if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
12446n/a#endif
12447n/a#ifndef __GNU__
12448n/a#ifdef O_SHLOCK
12449n/a if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
12450n/a#endif
12451n/a#ifdef O_EXLOCK
12452n/a if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
12453n/a#endif
12454n/a#endif
12455n/a#ifdef O_EXEC
12456n/a if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
12457n/a#endif
12458n/a#ifdef O_SEARCH
12459n/a if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
12460n/a#endif
12461n/a#ifdef O_PATH
12462n/a if (PyModule_AddIntMacro(m, O_PATH)) return -1;
12463n/a#endif
12464n/a#ifdef O_TTY_INIT
12465n/a if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
12466n/a#endif
12467n/a#ifdef O_TMPFILE
12468n/a if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
12469n/a#endif
12470n/a#ifdef PRIO_PROCESS
12471n/a if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
12472n/a#endif
12473n/a#ifdef PRIO_PGRP
12474n/a if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
12475n/a#endif
12476n/a#ifdef PRIO_USER
12477n/a if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
12478n/a#endif
12479n/a#ifdef O_CLOEXEC
12480n/a if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
12481n/a#endif
12482n/a#ifdef O_ACCMODE
12483n/a if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
12484n/a#endif
12485n/a
12486n/a
12487n/a#ifdef SEEK_HOLE
12488n/a if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
12489n/a#endif
12490n/a#ifdef SEEK_DATA
12491n/a if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
12492n/a#endif
12493n/a
12494n/a/* MS Windows */
12495n/a#ifdef O_NOINHERIT
12496n/a /* Don't inherit in child processes. */
12497n/a if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
12498n/a#endif
12499n/a#ifdef _O_SHORT_LIVED
12500n/a /* Optimize for short life (keep in memory). */
12501n/a /* MS forgot to define this one with a non-underscore form too. */
12502n/a if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
12503n/a#endif
12504n/a#ifdef O_TEMPORARY
12505n/a /* Automatically delete when last handle is closed. */
12506n/a if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
12507n/a#endif
12508n/a#ifdef O_RANDOM
12509n/a /* Optimize for random access. */
12510n/a if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
12511n/a#endif
12512n/a#ifdef O_SEQUENTIAL
12513n/a /* Optimize for sequential access. */
12514n/a if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
12515n/a#endif
12516n/a
12517n/a/* GNU extensions. */
12518n/a#ifdef O_ASYNC
12519n/a /* Send a SIGIO signal whenever input or output
12520n/a becomes available on file descriptor */
12521n/a if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
12522n/a#endif
12523n/a#ifdef O_DIRECT
12524n/a /* Direct disk access. */
12525n/a if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
12526n/a#endif
12527n/a#ifdef O_DIRECTORY
12528n/a /* Must be a directory. */
12529n/a if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
12530n/a#endif
12531n/a#ifdef O_NOFOLLOW
12532n/a /* Do not follow links. */
12533n/a if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
12534n/a#endif
12535n/a#ifdef O_NOLINKS
12536n/a /* Fails if link count of the named file is greater than 1 */
12537n/a if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
12538n/a#endif
12539n/a#ifdef O_NOATIME
12540n/a /* Do not update the access time. */
12541n/a if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
12542n/a#endif
12543n/a
12544n/a /* These come from sysexits.h */
12545n/a#ifdef EX_OK
12546n/a if (PyModule_AddIntMacro(m, EX_OK)) return -1;
12547n/a#endif /* EX_OK */
12548n/a#ifdef EX_USAGE
12549n/a if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
12550n/a#endif /* EX_USAGE */
12551n/a#ifdef EX_DATAERR
12552n/a if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
12553n/a#endif /* EX_DATAERR */
12554n/a#ifdef EX_NOINPUT
12555n/a if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
12556n/a#endif /* EX_NOINPUT */
12557n/a#ifdef EX_NOUSER
12558n/a if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
12559n/a#endif /* EX_NOUSER */
12560n/a#ifdef EX_NOHOST
12561n/a if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
12562n/a#endif /* EX_NOHOST */
12563n/a#ifdef EX_UNAVAILABLE
12564n/a if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
12565n/a#endif /* EX_UNAVAILABLE */
12566n/a#ifdef EX_SOFTWARE
12567n/a if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
12568n/a#endif /* EX_SOFTWARE */
12569n/a#ifdef EX_OSERR
12570n/a if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
12571n/a#endif /* EX_OSERR */
12572n/a#ifdef EX_OSFILE
12573n/a if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
12574n/a#endif /* EX_OSFILE */
12575n/a#ifdef EX_CANTCREAT
12576n/a if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
12577n/a#endif /* EX_CANTCREAT */
12578n/a#ifdef EX_IOERR
12579n/a if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
12580n/a#endif /* EX_IOERR */
12581n/a#ifdef EX_TEMPFAIL
12582n/a if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
12583n/a#endif /* EX_TEMPFAIL */
12584n/a#ifdef EX_PROTOCOL
12585n/a if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
12586n/a#endif /* EX_PROTOCOL */
12587n/a#ifdef EX_NOPERM
12588n/a if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
12589n/a#endif /* EX_NOPERM */
12590n/a#ifdef EX_CONFIG
12591n/a if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
12592n/a#endif /* EX_CONFIG */
12593n/a#ifdef EX_NOTFOUND
12594n/a if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
12595n/a#endif /* EX_NOTFOUND */
12596n/a
12597n/a /* statvfs */
12598n/a#ifdef ST_RDONLY
12599n/a if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
12600n/a#endif /* ST_RDONLY */
12601n/a#ifdef ST_NOSUID
12602n/a if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
12603n/a#endif /* ST_NOSUID */
12604n/a
12605n/a /* GNU extensions */
12606n/a#ifdef ST_NODEV
12607n/a if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
12608n/a#endif /* ST_NODEV */
12609n/a#ifdef ST_NOEXEC
12610n/a if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
12611n/a#endif /* ST_NOEXEC */
12612n/a#ifdef ST_SYNCHRONOUS
12613n/a if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
12614n/a#endif /* ST_SYNCHRONOUS */
12615n/a#ifdef ST_MANDLOCK
12616n/a if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
12617n/a#endif /* ST_MANDLOCK */
12618n/a#ifdef ST_WRITE
12619n/a if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
12620n/a#endif /* ST_WRITE */
12621n/a#ifdef ST_APPEND
12622n/a if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
12623n/a#endif /* ST_APPEND */
12624n/a#ifdef ST_NOATIME
12625n/a if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
12626n/a#endif /* ST_NOATIME */
12627n/a#ifdef ST_NODIRATIME
12628n/a if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
12629n/a#endif /* ST_NODIRATIME */
12630n/a#ifdef ST_RELATIME
12631n/a if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
12632n/a#endif /* ST_RELATIME */
12633n/a
12634n/a /* FreeBSD sendfile() constants */
12635n/a#ifdef SF_NODISKIO
12636n/a if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
12637n/a#endif
12638n/a#ifdef SF_MNOWAIT
12639n/a if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
12640n/a#endif
12641n/a#ifdef SF_SYNC
12642n/a if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
12643n/a#endif
12644n/a
12645n/a /* constants for posix_fadvise */
12646n/a#ifdef POSIX_FADV_NORMAL
12647n/a if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
12648n/a#endif
12649n/a#ifdef POSIX_FADV_SEQUENTIAL
12650n/a if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
12651n/a#endif
12652n/a#ifdef POSIX_FADV_RANDOM
12653n/a if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
12654n/a#endif
12655n/a#ifdef POSIX_FADV_NOREUSE
12656n/a if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
12657n/a#endif
12658n/a#ifdef POSIX_FADV_WILLNEED
12659n/a if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
12660n/a#endif
12661n/a#ifdef POSIX_FADV_DONTNEED
12662n/a if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
12663n/a#endif
12664n/a
12665n/a /* constants for waitid */
12666n/a#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
12667n/a if (PyModule_AddIntMacro(m, P_PID)) return -1;
12668n/a if (PyModule_AddIntMacro(m, P_PGID)) return -1;
12669n/a if (PyModule_AddIntMacro(m, P_ALL)) return -1;
12670n/a#endif
12671n/a#ifdef WEXITED
12672n/a if (PyModule_AddIntMacro(m, WEXITED)) return -1;
12673n/a#endif
12674n/a#ifdef WNOWAIT
12675n/a if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
12676n/a#endif
12677n/a#ifdef WSTOPPED
12678n/a if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
12679n/a#endif
12680n/a#ifdef CLD_EXITED
12681n/a if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
12682n/a#endif
12683n/a#ifdef CLD_DUMPED
12684n/a if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
12685n/a#endif
12686n/a#ifdef CLD_TRAPPED
12687n/a if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
12688n/a#endif
12689n/a#ifdef CLD_CONTINUED
12690n/a if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
12691n/a#endif
12692n/a
12693n/a /* constants for lockf */
12694n/a#ifdef F_LOCK
12695n/a if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
12696n/a#endif
12697n/a#ifdef F_TLOCK
12698n/a if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
12699n/a#endif
12700n/a#ifdef F_ULOCK
12701n/a if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
12702n/a#endif
12703n/a#ifdef F_TEST
12704n/a if (PyModule_AddIntMacro(m, F_TEST)) return -1;
12705n/a#endif
12706n/a
12707n/a#ifdef HAVE_SPAWNV
12708n/a if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
12709n/a if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
12710n/a if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
12711n/a if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
12712n/a if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
12713n/a#endif
12714n/a
12715n/a#ifdef HAVE_SCHED_H
12716n/a#ifdef SCHED_OTHER
12717n/a if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
12718n/a#endif
12719n/a#ifdef SCHED_FIFO
12720n/a if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
12721n/a#endif
12722n/a#ifdef SCHED_RR
12723n/a if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
12724n/a#endif
12725n/a#ifdef SCHED_SPORADIC
12726n/a if (PyModule_AddIntMacro(m, SCHED_SPORADIC) return -1;
12727n/a#endif
12728n/a#ifdef SCHED_BATCH
12729n/a if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
12730n/a#endif
12731n/a#ifdef SCHED_IDLE
12732n/a if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
12733n/a#endif
12734n/a#ifdef SCHED_RESET_ON_FORK
12735n/a if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
12736n/a#endif
12737n/a#ifdef SCHED_SYS
12738n/a if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
12739n/a#endif
12740n/a#ifdef SCHED_IA
12741n/a if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
12742n/a#endif
12743n/a#ifdef SCHED_FSS
12744n/a if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
12745n/a#endif
12746n/a#ifdef SCHED_FX
12747n/a if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
12748n/a#endif
12749n/a#endif
12750n/a
12751n/a#ifdef USE_XATTRS
12752n/a if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
12753n/a if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
12754n/a if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
12755n/a#endif
12756n/a
12757n/a#if HAVE_DECL_RTLD_LAZY
12758n/a if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
12759n/a#endif
12760n/a#if HAVE_DECL_RTLD_NOW
12761n/a if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
12762n/a#endif
12763n/a#if HAVE_DECL_RTLD_GLOBAL
12764n/a if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
12765n/a#endif
12766n/a#if HAVE_DECL_RTLD_LOCAL
12767n/a if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
12768n/a#endif
12769n/a#if HAVE_DECL_RTLD_NODELETE
12770n/a if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
12771n/a#endif
12772n/a#if HAVE_DECL_RTLD_NOLOAD
12773n/a if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
12774n/a#endif
12775n/a#if HAVE_DECL_RTLD_DEEPBIND
12776n/a if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
12777n/a#endif
12778n/a
12779n/a#ifdef HAVE_GETRANDOM_SYSCALL
12780n/a if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
12781n/a if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
12782n/a#endif
12783n/a
12784n/a return 0;
12785n/a}
12786n/a
12787n/a
12788n/astatic struct PyModuleDef posixmodule = {
12789n/a PyModuleDef_HEAD_INIT,
12790n/a MODNAME,
12791n/a posix__doc__,
12792n/a -1,
12793n/a posix_methods,
12794n/a NULL,
12795n/a NULL,
12796n/a NULL,
12797n/a NULL
12798n/a};
12799n/a
12800n/a
12801n/astatic const char * const have_functions[] = {
12802n/a
12803n/a#ifdef HAVE_FACCESSAT
12804n/a "HAVE_FACCESSAT",
12805n/a#endif
12806n/a
12807n/a#ifdef HAVE_FCHDIR
12808n/a "HAVE_FCHDIR",
12809n/a#endif
12810n/a
12811n/a#ifdef HAVE_FCHMOD
12812n/a "HAVE_FCHMOD",
12813n/a#endif
12814n/a
12815n/a#ifdef HAVE_FCHMODAT
12816n/a "HAVE_FCHMODAT",
12817n/a#endif
12818n/a
12819n/a#ifdef HAVE_FCHOWN
12820n/a "HAVE_FCHOWN",
12821n/a#endif
12822n/a
12823n/a#ifdef HAVE_FCHOWNAT
12824n/a "HAVE_FCHOWNAT",
12825n/a#endif
12826n/a
12827n/a#ifdef HAVE_FEXECVE
12828n/a "HAVE_FEXECVE",
12829n/a#endif
12830n/a
12831n/a#ifdef HAVE_FDOPENDIR
12832n/a "HAVE_FDOPENDIR",
12833n/a#endif
12834n/a
12835n/a#ifdef HAVE_FPATHCONF
12836n/a "HAVE_FPATHCONF",
12837n/a#endif
12838n/a
12839n/a#ifdef HAVE_FSTATAT
12840n/a "HAVE_FSTATAT",
12841n/a#endif
12842n/a
12843n/a#ifdef HAVE_FSTATVFS
12844n/a "HAVE_FSTATVFS",
12845n/a#endif
12846n/a
12847n/a#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
12848n/a "HAVE_FTRUNCATE",
12849n/a#endif
12850n/a
12851n/a#ifdef HAVE_FUTIMENS
12852n/a "HAVE_FUTIMENS",
12853n/a#endif
12854n/a
12855n/a#ifdef HAVE_FUTIMES
12856n/a "HAVE_FUTIMES",
12857n/a#endif
12858n/a
12859n/a#ifdef HAVE_FUTIMESAT
12860n/a "HAVE_FUTIMESAT",
12861n/a#endif
12862n/a
12863n/a#ifdef HAVE_LINKAT
12864n/a "HAVE_LINKAT",
12865n/a#endif
12866n/a
12867n/a#ifdef HAVE_LCHFLAGS
12868n/a "HAVE_LCHFLAGS",
12869n/a#endif
12870n/a
12871n/a#ifdef HAVE_LCHMOD
12872n/a "HAVE_LCHMOD",
12873n/a#endif
12874n/a
12875n/a#ifdef HAVE_LCHOWN
12876n/a "HAVE_LCHOWN",
12877n/a#endif
12878n/a
12879n/a#ifdef HAVE_LSTAT
12880n/a "HAVE_LSTAT",
12881n/a#endif
12882n/a
12883n/a#ifdef HAVE_LUTIMES
12884n/a "HAVE_LUTIMES",
12885n/a#endif
12886n/a
12887n/a#ifdef HAVE_MKDIRAT
12888n/a "HAVE_MKDIRAT",
12889n/a#endif
12890n/a
12891n/a#ifdef HAVE_MKFIFOAT
12892n/a "HAVE_MKFIFOAT",
12893n/a#endif
12894n/a
12895n/a#ifdef HAVE_MKNODAT
12896n/a "HAVE_MKNODAT",
12897n/a#endif
12898n/a
12899n/a#ifdef HAVE_OPENAT
12900n/a "HAVE_OPENAT",
12901n/a#endif
12902n/a
12903n/a#ifdef HAVE_READLINKAT
12904n/a "HAVE_READLINKAT",
12905n/a#endif
12906n/a
12907n/a#ifdef HAVE_RENAMEAT
12908n/a "HAVE_RENAMEAT",
12909n/a#endif
12910n/a
12911n/a#ifdef HAVE_SYMLINKAT
12912n/a "HAVE_SYMLINKAT",
12913n/a#endif
12914n/a
12915n/a#ifdef HAVE_UNLINKAT
12916n/a "HAVE_UNLINKAT",
12917n/a#endif
12918n/a
12919n/a#ifdef HAVE_UTIMENSAT
12920n/a "HAVE_UTIMENSAT",
12921n/a#endif
12922n/a
12923n/a#ifdef MS_WINDOWS
12924n/a "MS_WINDOWS",
12925n/a#endif
12926n/a
12927n/a NULL
12928n/a};
12929n/a
12930n/a
12931n/aPyMODINIT_FUNC
12932n/aINITFUNC(void)
12933n/a{
12934n/a PyObject *m, *v;
12935n/a PyObject *list;
12936n/a const char * const *trace;
12937n/a
12938n/a#if defined(HAVE_SYMLINK) && defined(MS_WINDOWS)
12939n/a win32_can_symlink = enable_symlink();
12940n/a#endif
12941n/a
12942n/a m = PyModule_Create(&posixmodule);
12943n/a if (m == NULL)
12944n/a return NULL;
12945n/a
12946n/a /* Initialize environ dictionary */
12947n/a v = convertenviron();
12948n/a Py_XINCREF(v);
12949n/a if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
12950n/a return NULL;
12951n/a Py_DECREF(v);
12952n/a
12953n/a if (all_ins(m))
12954n/a return NULL;
12955n/a
12956n/a if (setup_confname_tables(m))
12957n/a return NULL;
12958n/a
12959n/a Py_INCREF(PyExc_OSError);
12960n/a PyModule_AddObject(m, "error", PyExc_OSError);
12961n/a
12962n/a#ifdef HAVE_PUTENV
12963n/a if (posix_putenv_garbage == NULL)
12964n/a posix_putenv_garbage = PyDict_New();
12965n/a#endif
12966n/a
12967n/a if (!initialized) {
12968n/a#if defined(HAVE_WAITID) && !defined(__APPLE__)
12969n/a waitid_result_desc.name = MODNAME ".waitid_result";
12970n/a if (PyStructSequence_InitType2(&WaitidResultType, &waitid_result_desc) < 0)
12971n/a return NULL;
12972n/a#endif
12973n/a
12974n/a stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
12975n/a stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
12976n/a stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
12977n/a stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
12978n/a if (PyStructSequence_InitType2(&StatResultType, &stat_result_desc) < 0)
12979n/a return NULL;
12980n/a structseq_new = StatResultType.tp_new;
12981n/a StatResultType.tp_new = statresult_new;
12982n/a
12983n/a statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
12984n/a if (PyStructSequence_InitType2(&StatVFSResultType,
12985n/a &statvfs_result_desc) < 0)
12986n/a return NULL;
12987n/a#ifdef NEED_TICKS_PER_SECOND
12988n/a# if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
12989n/a ticks_per_second = sysconf(_SC_CLK_TCK);
12990n/a# elif defined(HZ)
12991n/a ticks_per_second = HZ;
12992n/a# else
12993n/a ticks_per_second = 60; /* magic fallback value; may be bogus */
12994n/a# endif
12995n/a#endif
12996n/a
12997n/a#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER)
12998n/a sched_param_desc.name = MODNAME ".sched_param";
12999n/a if (PyStructSequence_InitType2(&SchedParamType, &sched_param_desc) < 0)
13000n/a return NULL;
13001n/a SchedParamType.tp_new = os_sched_param;
13002n/a#endif
13003n/a
13004n/a /* initialize TerminalSize_info */
13005n/a if (PyStructSequence_InitType2(&TerminalSizeType,
13006n/a &TerminalSize_desc) < 0)
13007n/a return NULL;
13008n/a
13009n/a /* initialize scandir types */
13010n/a if (PyType_Ready(&ScandirIteratorType) < 0)
13011n/a return NULL;
13012n/a if (PyType_Ready(&DirEntryType) < 0)
13013n/a return NULL;
13014n/a }
13015n/a#if defined(HAVE_WAITID) && !defined(__APPLE__)
13016n/a Py_INCREF((PyObject*) &WaitidResultType);
13017n/a PyModule_AddObject(m, "waitid_result", (PyObject*) &WaitidResultType);
13018n/a#endif
13019n/a Py_INCREF((PyObject*) &StatResultType);
13020n/a PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType);
13021n/a Py_INCREF((PyObject*) &StatVFSResultType);
13022n/a PyModule_AddObject(m, "statvfs_result",
13023n/a (PyObject*) &StatVFSResultType);
13024n/a
13025n/a#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER)
13026n/a Py_INCREF(&SchedParamType);
13027n/a PyModule_AddObject(m, "sched_param", (PyObject *)&SchedParamType);
13028n/a#endif
13029n/a
13030n/a times_result_desc.name = MODNAME ".times_result";
13031n/a if (PyStructSequence_InitType2(&TimesResultType, &times_result_desc) < 0)
13032n/a return NULL;
13033n/a PyModule_AddObject(m, "times_result", (PyObject *)&TimesResultType);
13034n/a
13035n/a uname_result_desc.name = MODNAME ".uname_result";
13036n/a if (PyStructSequence_InitType2(&UnameResultType, &uname_result_desc) < 0)
13037n/a return NULL;
13038n/a PyModule_AddObject(m, "uname_result", (PyObject *)&UnameResultType);
13039n/a
13040n/a#ifdef __APPLE__
13041n/a /*
13042n/a * Step 2 of weak-linking support on Mac OS X.
13043n/a *
13044n/a * The code below removes functions that are not available on the
13045n/a * currently active platform.
13046n/a *
13047n/a * This block allow one to use a python binary that was build on
13048n/a * OSX 10.4 on OSX 10.3, without losing access to new APIs on
13049n/a * OSX 10.4.
13050n/a */
13051n/a#ifdef HAVE_FSTATVFS
13052n/a if (fstatvfs == NULL) {
13053n/a if (PyObject_DelAttrString(m, "fstatvfs") == -1) {
13054n/a return NULL;
13055n/a }
13056n/a }
13057n/a#endif /* HAVE_FSTATVFS */
13058n/a
13059n/a#ifdef HAVE_STATVFS
13060n/a if (statvfs == NULL) {
13061n/a if (PyObject_DelAttrString(m, "statvfs") == -1) {
13062n/a return NULL;
13063n/a }
13064n/a }
13065n/a#endif /* HAVE_STATVFS */
13066n/a
13067n/a# ifdef HAVE_LCHOWN
13068n/a if (lchown == NULL) {
13069n/a if (PyObject_DelAttrString(m, "lchown") == -1) {
13070n/a return NULL;
13071n/a }
13072n/a }
13073n/a#endif /* HAVE_LCHOWN */
13074n/a
13075n/a
13076n/a#endif /* __APPLE__ */
13077n/a
13078n/a Py_INCREF(&TerminalSizeType);
13079n/a PyModule_AddObject(m, "terminal_size", (PyObject*) &TerminalSizeType);
13080n/a
13081n/a billion = PyLong_FromLong(1000000000);
13082n/a if (!billion)
13083n/a return NULL;
13084n/a
13085n/a /* suppress "function not used" warnings */
13086n/a {
13087n/a int ignored;
13088n/a fd_specified("", -1);
13089n/a follow_symlinks_specified("", 1);
13090n/a dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
13091n/a dir_fd_converter(Py_None, &ignored);
13092n/a dir_fd_unavailable(Py_None, &ignored);
13093n/a }
13094n/a
13095n/a /*
13096n/a * provide list of locally available functions
13097n/a * so os.py can populate support_* lists
13098n/a */
13099n/a list = PyList_New(0);
13100n/a if (!list)
13101n/a return NULL;
13102n/a for (trace = have_functions; *trace; trace++) {
13103n/a PyObject *unicode = PyUnicode_DecodeASCII(*trace, strlen(*trace), NULL);
13104n/a if (!unicode)
13105n/a return NULL;
13106n/a if (PyList_Append(list, unicode))
13107n/a return NULL;
13108n/a Py_DECREF(unicode);
13109n/a }
13110n/a PyModule_AddObject(m, "_have_functions", list);
13111n/a
13112n/a Py_INCREF((PyObject *) &DirEntryType);
13113n/a PyModule_AddObject(m, "DirEntry", (PyObject *)&DirEntryType);
13114n/a
13115n/a initialized = 1;
13116n/a
13117n/a return m;
13118n/a}
13119n/a
13120n/a#ifdef __cplusplus
13121n/a}
13122n/a#endif