ยป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 statu