Issue #7333: The `posix` module gains an `initgroups()` function providing
[python.git] / Modules / posixmodule.c
blob8956e939c2be24c553463ebafc889bbd790cf9d2
2 /* POSIX module implementation */
4 /* This file is also used for Windows NT/MS-Win and OS/2. In that case the
5 module actually calls itself 'nt' or 'os2', not 'posix', and a few
6 functions are either unimplemented or implemented differently. The source
7 assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
8 of the compiler used. Different compilers define their own feature
9 test macro, e.g. '__BORLANDC__' or '_MSC_VER'. For OS/2, the compiler
10 independent macro PYOS_OS2 should be defined. On OS/2 the default
11 compiler is assumed to be IBM's VisualAge C++ (VACPP). PYCC_GCC is used
12 as the compiler specific macro for the EMX port of gcc to OS/2. */
14 /* See also ../Dos/dosmodule.c */
16 #ifdef __APPLE__
18 * Step 1 of support for weak-linking a number of symbols existing on
19 * OSX 10.4 and later, see the comment in the #ifdef __APPLE__ block
20 * at the end of this file for more information.
22 # pragma weak lchown
23 # pragma weak statvfs
24 # pragma weak fstatvfs
26 #endif /* __APPLE__ */
28 #define PY_SSIZE_T_CLEAN
30 #include "Python.h"
31 #include "structseq.h"
33 #if defined(__VMS)
34 # include <unixio.h>
35 #endif /* defined(__VMS) */
37 #ifdef __cplusplus
38 extern "C" {
39 #endif
41 PyDoc_STRVAR(posix__doc__,
42 "This module provides access to operating system functionality that is\n\
43 standardized by the C Standard and the POSIX standard (a thinly\n\
44 disguised Unix interface). Refer to the library manual and\n\
45 corresponding Unix manual entries for more information on calls.");
47 #ifndef Py_USING_UNICODE
48 /* This is used in signatures of functions. */
49 #define Py_UNICODE void
50 #endif
52 #if defined(PYOS_OS2)
53 #define INCL_DOS
54 #define INCL_DOSERRORS
55 #define INCL_DOSPROCESS
56 #define INCL_NOPMAPI
57 #include <os2.h>
58 #if defined(PYCC_GCC)
59 #include <ctype.h>
60 #include <io.h>
61 #include <stdio.h>
62 #include <process.h>
63 #endif
64 #include "osdefs.h"
65 #endif
67 #ifdef HAVE_SYS_TYPES_H
68 #include <sys/types.h>
69 #endif /* HAVE_SYS_TYPES_H */
71 #ifdef HAVE_SYS_STAT_H
72 #include <sys/stat.h>
73 #endif /* HAVE_SYS_STAT_H */
75 #ifdef HAVE_SYS_WAIT_H
76 #include <sys/wait.h> /* For WNOHANG */
77 #endif
79 #ifdef HAVE_SIGNAL_H
80 #include <signal.h>
81 #endif
83 #ifdef HAVE_FCNTL_H
84 #include <fcntl.h>
85 #endif /* HAVE_FCNTL_H */
87 #ifdef HAVE_GRP_H
88 #include <grp.h>
89 #endif
91 #ifdef HAVE_SYSEXITS_H
92 #include <sysexits.h>
93 #endif /* HAVE_SYSEXITS_H */
95 #ifdef HAVE_SYS_LOADAVG_H
96 #include <sys/loadavg.h>
97 #endif
99 /* Various compilers have only certain posix functions */
100 /* XXX Gosh I wish these were all moved into pyconfig.h */
101 #if defined(PYCC_VACPP) && defined(PYOS_OS2)
102 #include <process.h>
103 #else
104 #if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */
105 #define HAVE_GETCWD 1
106 #define HAVE_OPENDIR 1
107 #define HAVE_SYSTEM 1
108 #if defined(__OS2__)
109 #define HAVE_EXECV 1
110 #define HAVE_WAIT 1
111 #endif
112 #include <process.h>
113 #else
114 #ifdef __BORLANDC__ /* Borland compiler */
115 #define HAVE_EXECV 1
116 #define HAVE_GETCWD 1
117 #define HAVE_OPENDIR 1
118 #define HAVE_PIPE 1
119 #define HAVE_POPEN 1
120 #define HAVE_SYSTEM 1
121 #define HAVE_WAIT 1
122 #else
123 #ifdef _MSC_VER /* Microsoft compiler */
124 #define HAVE_GETCWD 1
125 #define HAVE_SPAWNV 1
126 #define HAVE_EXECV 1
127 #define HAVE_PIPE 1
128 #define HAVE_POPEN 1
129 #define HAVE_SYSTEM 1
130 #define HAVE_CWAIT 1
131 #define HAVE_FSYNC 1
132 #define fsync _commit
133 #else
134 #if defined(PYOS_OS2) && defined(PYCC_GCC) || defined(__VMS)
135 /* Everything needed is defined in PC/os2emx/pyconfig.h or vms/pyconfig.h */
136 #else /* all other compilers */
137 /* Unix functions that the configure script doesn't check for */
138 #define HAVE_EXECV 1
139 #define HAVE_FORK 1
140 #if defined(__USLC__) && defined(__SCO_VERSION__) /* SCO UDK Compiler */
141 #define HAVE_FORK1 1
142 #endif
143 #define HAVE_GETCWD 1
144 #define HAVE_GETEGID 1
145 #define HAVE_GETEUID 1
146 #define HAVE_GETGID 1
147 #define HAVE_GETPPID 1
148 #define HAVE_GETUID 1
149 #define HAVE_KILL 1
150 #define HAVE_OPENDIR 1
151 #define HAVE_PIPE 1
152 #ifndef __rtems__
153 #define HAVE_POPEN 1
154 #endif
155 #define HAVE_SYSTEM 1
156 #define HAVE_WAIT 1
157 #define HAVE_TTYNAME 1
158 #endif /* PYOS_OS2 && PYCC_GCC && __VMS */
159 #endif /* _MSC_VER */
160 #endif /* __BORLANDC__ */
161 #endif /* ! __WATCOMC__ || __QNX__ */
162 #endif /* ! __IBMC__ */
164 #ifndef _MSC_VER
166 #if defined(__sgi)&&_COMPILER_VERSION>=700
167 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
168 (default) */
169 extern char *ctermid_r(char *);
170 #endif
172 #ifndef HAVE_UNISTD_H
173 #if defined(PYCC_VACPP)
174 extern int mkdir(char *);
175 #else
176 #if ( defined(__WATCOMC__) || defined(_MSC_VER) ) && !defined(__QNX__)
177 extern int mkdir(const char *);
178 #else
179 extern int mkdir(const char *, mode_t);
180 #endif
181 #endif
182 #if defined(__IBMC__) || defined(__IBMCPP__)
183 extern int chdir(char *);
184 extern int rmdir(char *);
185 #else
186 extern int chdir(const char *);
187 extern int rmdir(const char *);
188 #endif
189 #ifdef __BORLANDC__
190 extern int chmod(const char *, int);
191 #else
192 extern int chmod(const char *, mode_t);
193 #endif
194 /*#ifdef HAVE_FCHMOD
195 extern int fchmod(int, mode_t);
196 #endif*/
197 /*#ifdef HAVE_LCHMOD
198 extern int lchmod(const char *, mode_t);
199 #endif*/
200 extern int chown(const char *, uid_t, gid_t);
201 extern char *getcwd(char *, int);
202 extern char *strerror(int);
203 extern int link(const char *, const char *);
204 extern int rename(const char *, const char *);
205 extern int stat(const char *, struct stat *);
206 extern int unlink(const char *);
207 extern int pclose(FILE *);
208 #ifdef HAVE_SYMLINK
209 extern int symlink(const char *, const char *);
210 #endif /* HAVE_SYMLINK */
211 #ifdef HAVE_LSTAT
212 extern int lstat(const char *, struct stat *);
213 #endif /* HAVE_LSTAT */
214 #endif /* !HAVE_UNISTD_H */
216 #endif /* !_MSC_VER */
218 #ifdef HAVE_UTIME_H
219 #include <utime.h>
220 #endif /* HAVE_UTIME_H */
222 #ifdef HAVE_SYS_UTIME_H
223 #include <sys/utime.h>
224 #define HAVE_UTIME_H /* pretend we do for the rest of this file */
225 #endif /* HAVE_SYS_UTIME_H */
227 #ifdef HAVE_SYS_TIMES_H
228 #include <sys/times.h>
229 #endif /* HAVE_SYS_TIMES_H */
231 #ifdef HAVE_SYS_PARAM_H
232 #include <sys/param.h>
233 #endif /* HAVE_SYS_PARAM_H */
235 #ifdef HAVE_SYS_UTSNAME_H
236 #include <sys/utsname.h>
237 #endif /* HAVE_SYS_UTSNAME_H */
239 #ifdef HAVE_DIRENT_H
240 #include <dirent.h>
241 #define NAMLEN(dirent) strlen((dirent)->d_name)
242 #else
243 #if defined(__WATCOMC__) && !defined(__QNX__)
244 #include <direct.h>
245 #define NAMLEN(dirent) strlen((dirent)->d_name)
246 #else
247 #define dirent direct
248 #define NAMLEN(dirent) (dirent)->d_namlen
249 #endif
250 #ifdef HAVE_SYS_NDIR_H
251 #include <sys/ndir.h>
252 #endif
253 #ifdef HAVE_SYS_DIR_H
254 #include <sys/dir.h>
255 #endif
256 #ifdef HAVE_NDIR_H
257 #include <ndir.h>
258 #endif
259 #endif
261 #ifdef _MSC_VER
262 #ifdef HAVE_DIRECT_H
263 #include <direct.h>
264 #endif
265 #ifdef HAVE_IO_H
266 #include <io.h>
267 #endif
268 #ifdef HAVE_PROCESS_H
269 #include <process.h>
270 #endif
271 #include "osdefs.h"
272 #include <malloc.h>
273 #include <windows.h>
274 #include <shellapi.h> /* for ShellExecute() */
275 #define popen _popen
276 #define pclose _pclose
277 #endif /* _MSC_VER */
279 #if defined(PYCC_VACPP) && defined(PYOS_OS2)
280 #include <io.h>
281 #endif /* OS2 */
283 #ifndef MAXPATHLEN
284 #if defined(PATH_MAX) && PATH_MAX > 1024
285 #define MAXPATHLEN PATH_MAX
286 #else
287 #define MAXPATHLEN 1024
288 #endif
289 #endif /* MAXPATHLEN */
291 #ifdef UNION_WAIT
292 /* Emulate some macros on systems that have a union instead of macros */
294 #ifndef WIFEXITED
295 #define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
296 #endif
298 #ifndef WEXITSTATUS
299 #define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
300 #endif
302 #ifndef WTERMSIG
303 #define WTERMSIG(u_wait) ((u_wait).w_termsig)
304 #endif
306 #define WAIT_TYPE union wait
307 #define WAIT_STATUS_INT(s) (s.w_status)
309 #else /* !UNION_WAIT */
310 #define WAIT_TYPE int
311 #define WAIT_STATUS_INT(s) (s)
312 #endif /* UNION_WAIT */
314 /* Issue #1983: pid_t can be longer than a C long on some systems */
315 #if !defined(SIZEOF_PID_T) || SIZEOF_PID_T == SIZEOF_INT
316 #define PARSE_PID "i"
317 #define PyLong_FromPid PyInt_FromLong
318 #define PyLong_AsPid PyInt_AsLong
319 #elif SIZEOF_PID_T == SIZEOF_LONG
320 #define PARSE_PID "l"
321 #define PyLong_FromPid PyInt_FromLong
322 #define PyLong_AsPid PyInt_AsLong
323 #elif defined(SIZEOF_LONG_LONG) && SIZEOF_PID_T == SIZEOF_LONG_LONG
324 #define PARSE_PID "L"
325 #define PyLong_FromPid PyLong_FromLongLong
326 #define PyLong_AsPid PyInt_AsLongLong
327 #else
328 #error "sizeof(pid_t) is neither sizeof(int), sizeof(long) or sizeof(long long)"
329 #endif /* SIZEOF_PID_T */
331 /* Don't use the "_r" form if we don't need it (also, won't have a
332 prototype for it, at least on Solaris -- maybe others as well?). */
333 #if defined(HAVE_CTERMID_R) && defined(WITH_THREAD)
334 #define USE_CTERMID_R
335 #endif
337 #if defined(HAVE_TMPNAM_R) && defined(WITH_THREAD)
338 #define USE_TMPNAM_R
339 #endif
341 /* choose the appropriate stat and fstat functions and return structs */
342 #undef STAT
343 #if defined(MS_WIN64) || defined(MS_WINDOWS)
344 # define STAT win32_stat
345 # define FSTAT win32_fstat
346 # define STRUCT_STAT struct win32_stat
347 #else
348 # define STAT stat
349 # define FSTAT fstat
350 # define STRUCT_STAT struct stat
351 #endif
353 #if defined(MAJOR_IN_MKDEV)
354 #include <sys/mkdev.h>
355 #else
356 #if defined(MAJOR_IN_SYSMACROS)
357 #include <sys/sysmacros.h>
358 #endif
359 #if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
360 #include <sys/mkdev.h>
361 #endif
362 #endif
364 #if defined _MSC_VER && _MSC_VER >= 1400
365 /* Microsoft CRT in VS2005 and higher will verify that a filehandle is
366 * valid and throw an assertion if it isn't.
367 * Normally, an invalid fd is likely to be a C program error and therefore
368 * an assertion can be useful, but it does contradict the POSIX standard
369 * which for write(2) states:
370 * "Otherwise, -1 shall be returned and errno set to indicate the error."
371 * "[EBADF] The fildes argument is not a valid file descriptor open for
372 * writing."
373 * Furthermore, python allows the user to enter any old integer
374 * as a fd and should merely raise a python exception on error.
375 * The Microsoft CRT doesn't provide an official way to check for the
376 * validity of a file descriptor, but we can emulate its internal behaviour
377 * by using the exported __pinfo data member and knowledge of the
378 * internal structures involved.
379 * The structures below must be updated for each version of visual studio
380 * according to the file internal.h in the CRT source, until MS comes
381 * up with a less hacky way to do this.
382 * (all of this is to avoid globally modifying the CRT behaviour using
383 * _set_invalid_parameter_handler() and _CrtSetReportMode())
385 /* The actual size of the structure is determined at runtime.
386 * Only the first items must be present.
388 typedef struct {
389 intptr_t osfhnd;
390 char osfile;
391 } my_ioinfo;
393 extern __declspec(dllimport) char * __pioinfo[];
394 #define IOINFO_L2E 5
395 #define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
396 #define IOINFO_ARRAYS 64
397 #define _NHANDLE_ (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS)
398 #define FOPEN 0x01
399 #define _NO_CONSOLE_FILENO (intptr_t)-2
401 /* This function emulates what the windows CRT does to validate file handles */
403 _PyVerify_fd(int fd)
405 const int i1 = fd >> IOINFO_L2E;
406 const int i2 = fd & ((1 << IOINFO_L2E) - 1);
408 static int sizeof_ioinfo = 0;
410 /* Determine the actual size of the ioinfo structure,
411 * as used by the CRT loaded in memory
413 if (sizeof_ioinfo == 0 && __pioinfo[0] != NULL) {
414 sizeof_ioinfo = _msize(__pioinfo[0]) / IOINFO_ARRAY_ELTS;
416 if (sizeof_ioinfo == 0) {
417 /* This should not happen... */
418 goto fail;
421 /* See that it isn't a special CLEAR fileno */
422 if (fd != _NO_CONSOLE_FILENO) {
423 /* Microsoft CRT would check that 0<=fd<_nhandle but we can't do that. Instead
424 * we check pointer validity and other info
426 if (0 <= i1 && i1 < IOINFO_ARRAYS && __pioinfo[i1] != NULL) {
427 /* finally, check that the file is open */
428 my_ioinfo* info = (my_ioinfo*)(__pioinfo[i1] + i2 * sizeof_ioinfo);
429 if (info->osfile & FOPEN) {
430 return 1;
434 fail:
435 errno = EBADF;
436 return 0;
439 /* the special case of checking dup2. The target fd must be in a sensible range */
440 static int
441 _PyVerify_fd_dup2(int fd1, int fd2)
443 if (!_PyVerify_fd(fd1))
444 return 0;
445 if (fd2 == _NO_CONSOLE_FILENO)
446 return 0;
447 if ((unsigned)fd2 < _NHANDLE_)
448 return 1;
449 else
450 return 0;
452 #else
453 /* dummy version. _PyVerify_fd() is already defined in fileobject.h */
454 #define _PyVerify_fd_dup2(A, B) (1)
455 #endif
457 /* Return a dictionary corresponding to the POSIX environment table */
458 #ifdef WITH_NEXT_FRAMEWORK
459 /* On Darwin/MacOSX a shared library or framework has no access to
460 ** environ directly, we must obtain it with _NSGetEnviron().
462 #include <crt_externs.h>
463 static char **environ;
464 #elif !defined(_MSC_VER) && ( !defined(__WATCOMC__) || defined(__QNX__) )
465 extern char **environ;
466 #endif /* !_MSC_VER */
468 static PyObject *
469 convertenviron(void)
471 PyObject *d;
472 char **e;
473 d = PyDict_New();
474 if (d == NULL)
475 return NULL;
476 #ifdef WITH_NEXT_FRAMEWORK
477 if (environ == NULL)
478 environ = *_NSGetEnviron();
479 #endif
480 if (environ == NULL)
481 return d;
482 /* This part ignores errors */
483 for (e = environ; *e != NULL; e++) {
484 PyObject *k;
485 PyObject *v;
486 char *p = strchr(*e, '=');
487 if (p == NULL)
488 continue;
489 k = PyString_FromStringAndSize(*e, (int)(p-*e));
490 if (k == NULL) {
491 PyErr_Clear();
492 continue;
494 v = PyString_FromString(p+1);
495 if (v == NULL) {
496 PyErr_Clear();
497 Py_DECREF(k);
498 continue;
500 if (PyDict_GetItem(d, k) == NULL) {
501 if (PyDict_SetItem(d, k, v) != 0)
502 PyErr_Clear();
504 Py_DECREF(k);
505 Py_DECREF(v);
507 #if defined(PYOS_OS2)
509 APIRET rc;
510 char buffer[1024]; /* OS/2 Provides a Documented Max of 1024 Chars */
512 rc = DosQueryExtLIBPATH(buffer, BEGIN_LIBPATH);
513 if (rc == NO_ERROR) { /* (not a type, envname is NOT 'BEGIN_LIBPATH') */
514 PyObject *v = PyString_FromString(buffer);
515 PyDict_SetItemString(d, "BEGINLIBPATH", v);
516 Py_DECREF(v);
518 rc = DosQueryExtLIBPATH(buffer, END_LIBPATH);
519 if (rc == NO_ERROR) { /* (not a typo, envname is NOT 'END_LIBPATH') */
520 PyObject *v = PyString_FromString(buffer);
521 PyDict_SetItemString(d, "ENDLIBPATH", v);
522 Py_DECREF(v);
525 #endif
526 return d;
530 /* Set a POSIX-specific error from errno, and return NULL */
532 static PyObject *
533 posix_error(void)
535 return PyErr_SetFromErrno(PyExc_OSError);
537 static PyObject *
538 posix_error_with_filename(char* name)
540 return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
543 #ifdef MS_WINDOWS
544 static PyObject *
545 posix_error_with_unicode_filename(Py_UNICODE* name)
547 return PyErr_SetFromErrnoWithUnicodeFilename(PyExc_OSError, name);
549 #endif /* MS_WINDOWS */
552 static PyObject *
553 posix_error_with_allocated_filename(char* name)
555 PyObject *rc = PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
556 PyMem_Free(name);
557 return rc;
560 #ifdef MS_WINDOWS
561 static PyObject *
562 win32_error(char* function, char* filename)
564 /* XXX We should pass the function name along in the future.
565 (_winreg.c also wants to pass the function name.)
566 This would however require an additional param to the
567 Windows error object, which is non-trivial.
569 errno = GetLastError();
570 if (filename)
571 return PyErr_SetFromWindowsErrWithFilename(errno, filename);
572 else
573 return PyErr_SetFromWindowsErr(errno);
576 static PyObject *
577 win32_error_unicode(char* function, Py_UNICODE* filename)
579 /* XXX - see win32_error for comments on 'function' */
580 errno = GetLastError();
581 if (filename)
582 return PyErr_SetFromWindowsErrWithUnicodeFilename(errno, filename);
583 else
584 return PyErr_SetFromWindowsErr(errno);
587 static int
588 convert_to_unicode(PyObject **param)
590 if (PyUnicode_CheckExact(*param))
591 Py_INCREF(*param);
592 else if (PyUnicode_Check(*param))
593 /* For a Unicode subtype that's not a Unicode object,
594 return a true Unicode object with the same data. */
595 *param = PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(*param),
596 PyUnicode_GET_SIZE(*param));
597 else
598 *param = PyUnicode_FromEncodedObject(*param,
599 Py_FileSystemDefaultEncoding,
600 "strict");
601 return (*param) != NULL;
604 #endif /* MS_WINDOWS */
606 #if defined(PYOS_OS2)
607 /**********************************************************************
608 * Helper Function to Trim and Format OS/2 Messages
609 **********************************************************************/
610 static void
611 os2_formatmsg(char *msgbuf, int msglen, char *reason)
613 msgbuf[msglen] = '\0'; /* OS/2 Doesn't Guarantee a Terminator */
615 if (strlen(msgbuf) > 0) { /* If Non-Empty Msg, Trim CRLF */
616 char *lastc = &msgbuf[ strlen(msgbuf)-1 ];
618 while (lastc > msgbuf && isspace(Py_CHARMASK(*lastc)))
619 *lastc-- = '\0'; /* Trim Trailing Whitespace (CRLF) */
622 /* Add Optional Reason Text */
623 if (reason) {
624 strcat(msgbuf, " : ");
625 strcat(msgbuf, reason);
629 /**********************************************************************
630 * Decode an OS/2 Operating System Error Code
632 * A convenience function to lookup an OS/2 error code and return a
633 * text message we can use to raise a Python exception.
635 * Notes:
636 * The messages for errors returned from the OS/2 kernel reside in
637 * the file OSO001.MSG in the \OS2 directory hierarchy.
639 **********************************************************************/
640 static char *
641 os2_strerror(char *msgbuf, int msgbuflen, int errorcode, char *reason)
643 APIRET rc;
644 ULONG msglen;
646 /* Retrieve Kernel-Related Error Message from OSO001.MSG File */
647 Py_BEGIN_ALLOW_THREADS
648 rc = DosGetMessage(NULL, 0, msgbuf, msgbuflen,
649 errorcode, "oso001.msg", &msglen);
650 Py_END_ALLOW_THREADS
652 if (rc == NO_ERROR)
653 os2_formatmsg(msgbuf, msglen, reason);
654 else
655 PyOS_snprintf(msgbuf, msgbuflen,
656 "unknown OS error #%d", errorcode);
658 return msgbuf;
661 /* Set an OS/2-specific error and return NULL. OS/2 kernel
662 errors are not in a global variable e.g. 'errno' nor are
663 they congruent with posix error numbers. */
665 static PyObject * os2_error(int code)
667 char text[1024];
668 PyObject *v;
670 os2_strerror(text, sizeof(text), code, "");
672 v = Py_BuildValue("(is)", code, text);
673 if (v != NULL) {
674 PyErr_SetObject(PyExc_OSError, v);
675 Py_DECREF(v);
677 return NULL; /* Signal to Python that an Exception is Pending */
680 #endif /* OS2 */
682 /* POSIX generic methods */
684 static PyObject *
685 posix_fildes(PyObject *fdobj, int (*func)(int))
687 int fd;
688 int res;
689 fd = PyObject_AsFileDescriptor(fdobj);
690 if (fd < 0)
691 return NULL;
692 if (!_PyVerify_fd(fd))
693 return posix_error();
694 Py_BEGIN_ALLOW_THREADS
695 res = (*func)(fd);
696 Py_END_ALLOW_THREADS
697 if (res < 0)
698 return posix_error();
699 Py_INCREF(Py_None);
700 return Py_None;
703 static PyObject *
704 posix_1str(PyObject *args, char *format, int (*func)(const char*))
706 char *path1 = NULL;
707 int res;
708 if (!PyArg_ParseTuple(args, format,
709 Py_FileSystemDefaultEncoding, &path1))
710 return NULL;
711 Py_BEGIN_ALLOW_THREADS
712 res = (*func)(path1);
713 Py_END_ALLOW_THREADS
714 if (res < 0)
715 return posix_error_with_allocated_filename(path1);
716 PyMem_Free(path1);
717 Py_INCREF(Py_None);
718 return Py_None;
721 static PyObject *
722 posix_2str(PyObject *args,
723 char *format,
724 int (*func)(const char *, const char *))
726 char *path1 = NULL, *path2 = NULL;
727 int res;
728 if (!PyArg_ParseTuple(args, format,
729 Py_FileSystemDefaultEncoding, &path1,
730 Py_FileSystemDefaultEncoding, &path2))
731 return NULL;
732 Py_BEGIN_ALLOW_THREADS
733 res = (*func)(path1, path2);
734 Py_END_ALLOW_THREADS
735 PyMem_Free(path1);
736 PyMem_Free(path2);
737 if (res != 0)
738 /* XXX how to report both path1 and path2??? */
739 return posix_error();
740 Py_INCREF(Py_None);
741 return Py_None;
744 #ifdef MS_WINDOWS
745 static PyObject*
746 win32_1str(PyObject* args, char* func,
747 char* format, BOOL (__stdcall *funcA)(LPCSTR),
748 char* wformat, BOOL (__stdcall *funcW)(LPWSTR))
750 PyObject *uni;
751 char *ansi;
752 BOOL result;
754 if (!PyArg_ParseTuple(args, wformat, &uni))
755 PyErr_Clear();
756 else {
757 Py_BEGIN_ALLOW_THREADS
758 result = funcW(PyUnicode_AsUnicode(uni));
759 Py_END_ALLOW_THREADS
760 if (!result)
761 return win32_error_unicode(func, PyUnicode_AsUnicode(uni));
762 Py_INCREF(Py_None);
763 return Py_None;
765 if (!PyArg_ParseTuple(args, format, &ansi))
766 return NULL;
767 Py_BEGIN_ALLOW_THREADS
768 result = funcA(ansi);
769 Py_END_ALLOW_THREADS
770 if (!result)
771 return win32_error(func, ansi);
772 Py_INCREF(Py_None);
773 return Py_None;
777 /* This is a reimplementation of the C library's chdir function,
778 but one that produces Win32 errors instead of DOS error codes.
779 chdir is essentially a wrapper around SetCurrentDirectory; however,
780 it also needs to set "magic" environment variables indicating
781 the per-drive current directory, which are of the form =<drive>: */
782 static BOOL __stdcall
783 win32_chdir(LPCSTR path)
785 char new_path[MAX_PATH+1];
786 int result;
787 char env[4] = "=x:";
789 if(!SetCurrentDirectoryA(path))
790 return FALSE;
791 result = GetCurrentDirectoryA(MAX_PATH+1, new_path);
792 if (!result)
793 return FALSE;
794 /* In the ANSI API, there should not be any paths longer
795 than MAX_PATH. */
796 assert(result <= MAX_PATH+1);
797 if (strncmp(new_path, "\\\\", 2) == 0 ||
798 strncmp(new_path, "//", 2) == 0)
799 /* UNC path, nothing to do. */
800 return TRUE;
801 env[1] = new_path[0];
802 return SetEnvironmentVariableA(env, new_path);
805 /* The Unicode version differs from the ANSI version
806 since the current directory might exceed MAX_PATH characters */
807 static BOOL __stdcall
808 win32_wchdir(LPCWSTR path)
810 wchar_t _new_path[MAX_PATH+1], *new_path = _new_path;
811 int result;
812 wchar_t env[4] = L"=x:";
814 if(!SetCurrentDirectoryW(path))
815 return FALSE;
816 result = GetCurrentDirectoryW(MAX_PATH+1, new_path);
817 if (!result)
818 return FALSE;
819 if (result > MAX_PATH+1) {
820 new_path = malloc(result * sizeof(wchar_t));
821 if (!new_path) {
822 SetLastError(ERROR_OUTOFMEMORY);
823 return FALSE;
825 result = GetCurrentDirectoryW(result, new_path);
826 if (!result) {
827 free(new_path);
828 return FALSE;
831 if (wcsncmp(new_path, L"\\\\", 2) == 0 ||
832 wcsncmp(new_path, L"//", 2) == 0)
833 /* UNC path, nothing to do. */
834 return TRUE;
835 env[1] = new_path[0];
836 result = SetEnvironmentVariableW(env, new_path);
837 if (new_path != _new_path)
838 free(new_path);
839 return result;
841 #endif
843 #ifdef MS_WINDOWS
844 /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
845 - time stamps are restricted to second resolution
846 - file modification times suffer from forth-and-back conversions between
847 UTC and local time
848 Therefore, we implement our own stat, based on the Win32 API directly.
850 #define HAVE_STAT_NSEC 1
852 struct win32_stat{
853 int st_dev;
854 __int64 st_ino;
855 unsigned short st_mode;
856 int st_nlink;
857 int st_uid;
858 int st_gid;
859 int st_rdev;
860 __int64 st_size;
861 int st_atime;
862 int st_atime_nsec;
863 int st_mtime;
864 int st_mtime_nsec;
865 int st_ctime;
866 int st_ctime_nsec;
869 static __int64 secs_between_epochs = 11644473600; /* Seconds between 1.1.1601 and 1.1.1970 */
871 static void
872 FILE_TIME_to_time_t_nsec(FILETIME *in_ptr, int *time_out, int* nsec_out)
874 /* XXX endianness. Shouldn't matter, as all Windows implementations are little-endian */
875 /* Cannot simply cast and dereference in_ptr,
876 since it might not be aligned properly */
877 __int64 in;
878 memcpy(&in, in_ptr, sizeof(in));
879 *nsec_out = (int)(in % 10000000) * 100; /* FILETIME is in units of 100 nsec. */
880 /* XXX Win32 supports time stamps past 2038; we currently don't */
881 *time_out = Py_SAFE_DOWNCAST((in / 10000000) - secs_between_epochs, __int64, int);
884 static void
885 time_t_to_FILE_TIME(int time_in, int nsec_in, FILETIME *out_ptr)
887 /* XXX endianness */
888 __int64 out;
889 out = time_in + secs_between_epochs;
890 out = out * 10000000 + nsec_in / 100;
891 memcpy(out_ptr, &out, sizeof(out));
894 /* Below, we *know* that ugo+r is 0444 */
895 #if _S_IREAD != 0400
896 #error Unsupported C library
897 #endif
898 static int
899 attributes_to_mode(DWORD attr)
901 int m = 0;
902 if (attr & FILE_ATTRIBUTE_DIRECTORY)
903 m |= _S_IFDIR | 0111; /* IFEXEC for user,group,other */
904 else
905 m |= _S_IFREG;
906 if (attr & FILE_ATTRIBUTE_READONLY)
907 m |= 0444;
908 else
909 m |= 0666;
910 return m;
913 static int
914 attribute_data_to_stat(WIN32_FILE_ATTRIBUTE_DATA *info, struct win32_stat *result)
916 memset(result, 0, sizeof(*result));
917 result->st_mode = attributes_to_mode(info->dwFileAttributes);
918 result->st_size = (((__int64)info->nFileSizeHigh)<<32) + info->nFileSizeLow;
919 FILE_TIME_to_time_t_nsec(&info->ftCreationTime, &result->st_ctime, &result->st_ctime_nsec);
920 FILE_TIME_to_time_t_nsec(&info->ftLastWriteTime, &result->st_mtime, &result->st_mtime_nsec);
921 FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime, &result->st_atime_nsec);
923 return 0;
926 static BOOL
927 attributes_from_dir(LPCSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad)
929 HANDLE hFindFile;
930 WIN32_FIND_DATAA FileData;
931 hFindFile = FindFirstFileA(pszFile, &FileData);
932 if (hFindFile == INVALID_HANDLE_VALUE)
933 return FALSE;
934 FindClose(hFindFile);
935 pfad->dwFileAttributes = FileData.dwFileAttributes;
936 pfad->ftCreationTime = FileData.ftCreationTime;
937 pfad->ftLastAccessTime = FileData.ftLastAccessTime;
938 pfad->ftLastWriteTime = FileData.ftLastWriteTime;
939 pfad->nFileSizeHigh = FileData.nFileSizeHigh;
940 pfad->nFileSizeLow = FileData.nFileSizeLow;
941 return TRUE;
944 static BOOL
945 attributes_from_dir_w(LPCWSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad)
947 HANDLE hFindFile;
948 WIN32_FIND_DATAW FileData;
949 hFindFile = FindFirstFileW(pszFile, &FileData);
950 if (hFindFile == INVALID_HANDLE_VALUE)
951 return FALSE;
952 FindClose(hFindFile);
953 pfad->dwFileAttributes = FileData.dwFileAttributes;
954 pfad->ftCreationTime = FileData.ftCreationTime;
955 pfad->ftLastAccessTime = FileData.ftLastAccessTime;
956 pfad->ftLastWriteTime = FileData.ftLastWriteTime;
957 pfad->nFileSizeHigh = FileData.nFileSizeHigh;
958 pfad->nFileSizeLow = FileData.nFileSizeLow;
959 return TRUE;
962 static int
963 win32_stat(const char* path, struct win32_stat *result)
965 WIN32_FILE_ATTRIBUTE_DATA info;
966 int code;
967 char *dot;
968 if (!GetFileAttributesExA(path, GetFileExInfoStandard, &info)) {
969 if (GetLastError() != ERROR_SHARING_VIOLATION) {
970 /* Protocol violation: we explicitly clear errno, instead of
971 setting it to a POSIX error. Callers should use GetLastError. */
972 errno = 0;
973 return -1;
974 } else {
975 /* Could not get attributes on open file. Fall back to
976 reading the directory. */
977 if (!attributes_from_dir(path, &info)) {
978 /* Very strange. This should not fail now */
979 errno = 0;
980 return -1;
984 code = attribute_data_to_stat(&info, result);
985 if (code != 0)
986 return code;
987 /* Set S_IFEXEC if it is an .exe, .bat, ... */
988 dot = strrchr(path, '.');
989 if (dot) {
990 if (stricmp(dot, ".bat") == 0 ||
991 stricmp(dot, ".cmd") == 0 ||
992 stricmp(dot, ".exe") == 0 ||
993 stricmp(dot, ".com") == 0)
994 result->st_mode |= 0111;
996 return code;
999 static int
1000 win32_wstat(const wchar_t* path, struct win32_stat *result)
1002 int code;
1003 const wchar_t *dot;
1004 WIN32_FILE_ATTRIBUTE_DATA info;
1005 if (!GetFileAttributesExW(path, GetFileExInfoStandard, &info)) {
1006 if (GetLastError() != ERROR_SHARING_VIOLATION) {
1007 /* Protocol violation: we explicitly clear errno, instead of
1008 setting it to a POSIX error. Callers should use GetLastError. */
1009 errno = 0;
1010 return -1;
1011 } else {
1012 /* Could not get attributes on open file. Fall back to
1013 reading the directory. */
1014 if (!attributes_from_dir_w(path, &info)) {
1015 /* Very strange. This should not fail now */
1016 errno = 0;
1017 return -1;
1021 code = attribute_data_to_stat(&info, result);
1022 if (code < 0)
1023 return code;
1024 /* Set IFEXEC if it is an .exe, .bat, ... */
1025 dot = wcsrchr(path, '.');
1026 if (dot) {
1027 if (_wcsicmp(dot, L".bat") == 0 ||
1028 _wcsicmp(dot, L".cmd") == 0 ||
1029 _wcsicmp(dot, L".exe") == 0 ||
1030 _wcsicmp(dot, L".com") == 0)
1031 result->st_mode |= 0111;
1033 return code;
1036 static int
1037 win32_fstat(int file_number, struct win32_stat *result)
1039 BY_HANDLE_FILE_INFORMATION info;
1040 HANDLE h;
1041 int type;
1043 h = (HANDLE)_get_osfhandle(file_number);
1045 /* Protocol violation: we explicitly clear errno, instead of
1046 setting it to a POSIX error. Callers should use GetLastError. */
1047 errno = 0;
1049 if (h == INVALID_HANDLE_VALUE) {
1050 /* This is really a C library error (invalid file handle).
1051 We set the Win32 error to the closes one matching. */
1052 SetLastError(ERROR_INVALID_HANDLE);
1053 return -1;
1055 memset(result, 0, sizeof(*result));
1057 type = GetFileType(h);
1058 if (type == FILE_TYPE_UNKNOWN) {
1059 DWORD error = GetLastError();
1060 if (error != 0) {
1061 return -1;
1063 /* else: valid but unknown file */
1066 if (type != FILE_TYPE_DISK) {
1067 if (type == FILE_TYPE_CHAR)
1068 result->st_mode = _S_IFCHR;
1069 else if (type == FILE_TYPE_PIPE)
1070 result->st_mode = _S_IFIFO;
1071 return 0;
1074 if (!GetFileInformationByHandle(h, &info)) {
1075 return -1;
1078 /* similar to stat() */
1079 result->st_mode = attributes_to_mode(info.dwFileAttributes);
1080 result->st_size = (((__int64)info.nFileSizeHigh)<<32) + info.nFileSizeLow;
1081 FILE_TIME_to_time_t_nsec(&info.ftCreationTime, &result->st_ctime, &result->st_ctime_nsec);
1082 FILE_TIME_to_time_t_nsec(&info.ftLastWriteTime, &result->st_mtime, &result->st_mtime_nsec);
1083 FILE_TIME_to_time_t_nsec(&info.ftLastAccessTime, &result->st_atime, &result->st_atime_nsec);
1084 /* specific to fstat() */
1085 result->st_nlink = info.nNumberOfLinks;
1086 result->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow;
1087 return 0;
1090 #endif /* MS_WINDOWS */
1092 PyDoc_STRVAR(stat_result__doc__,
1093 "stat_result: Result from stat or lstat.\n\n\
1094 This object may be accessed either as a tuple of\n\
1095 (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
1096 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
1098 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
1099 or st_flags, they are available as attributes only.\n\
1101 See os.stat for more information.");
1103 static PyStructSequence_Field stat_result_fields[] = {
1104 {"st_mode", "protection bits"},
1105 {"st_ino", "inode"},
1106 {"st_dev", "device"},
1107 {"st_nlink", "number of hard links"},
1108 {"st_uid", "user ID of owner"},
1109 {"st_gid", "group ID of owner"},
1110 {"st_size", "total size, in bytes"},
1111 /* The NULL is replaced with PyStructSequence_UnnamedField later. */
1112 {NULL, "integer time of last access"},
1113 {NULL, "integer time of last modification"},
1114 {NULL, "integer time of last change"},
1115 {"st_atime", "time of last access"},
1116 {"st_mtime", "time of last modification"},
1117 {"st_ctime", "time of last change"},
1118 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1119 {"st_blksize", "blocksize for filesystem I/O"},
1120 #endif
1121 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1122 {"st_blocks", "number of blocks allocated"},
1123 #endif
1124 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1125 {"st_rdev", "device type (if inode device)"},
1126 #endif
1127 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
1128 {"st_flags", "user defined flags for file"},
1129 #endif
1130 #ifdef HAVE_STRUCT_STAT_ST_GEN
1131 {"st_gen", "generation number"},
1132 #endif
1133 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1134 {"st_birthtime", "time of creation"},
1135 #endif
1139 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1140 #define ST_BLKSIZE_IDX 13
1141 #else
1142 #define ST_BLKSIZE_IDX 12
1143 #endif
1145 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1146 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
1147 #else
1148 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
1149 #endif
1151 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1152 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
1153 #else
1154 #define ST_RDEV_IDX ST_BLOCKS_IDX
1155 #endif
1157 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
1158 #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
1159 #else
1160 #define ST_FLAGS_IDX ST_RDEV_IDX
1161 #endif
1163 #ifdef HAVE_STRUCT_STAT_ST_GEN
1164 #define ST_GEN_IDX (ST_FLAGS_IDX+1)
1165 #else
1166 #define ST_GEN_IDX ST_FLAGS_IDX
1167 #endif
1169 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1170 #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
1171 #else
1172 #define ST_BIRTHTIME_IDX ST_GEN_IDX
1173 #endif
1175 static PyStructSequence_Desc stat_result_desc = {
1176 "stat_result", /* name */
1177 stat_result__doc__, /* doc */
1178 stat_result_fields,
1182 PyDoc_STRVAR(statvfs_result__doc__,
1183 "statvfs_result: Result from statvfs or fstatvfs.\n\n\
1184 This object may be accessed either as a tuple of\n\
1185 (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
1186 or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
1188 See os.statvfs for more information.");
1190 static PyStructSequence_Field statvfs_result_fields[] = {
1191 {"f_bsize", },
1192 {"f_frsize", },
1193 {"f_blocks", },
1194 {"f_bfree", },
1195 {"f_bavail", },
1196 {"f_files", },
1197 {"f_ffree", },
1198 {"f_favail", },
1199 {"f_flag", },
1200 {"f_namemax",},
1204 static PyStructSequence_Desc statvfs_result_desc = {
1205 "statvfs_result", /* name */
1206 statvfs_result__doc__, /* doc */
1207 statvfs_result_fields,
1211 static int initialized;
1212 static PyTypeObject StatResultType;
1213 static PyTypeObject StatVFSResultType;
1214 static newfunc structseq_new;
1216 static PyObject *
1217 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1219 PyStructSequence *result;
1220 int i;
1222 result = (PyStructSequence*)structseq_new(type, args, kwds);
1223 if (!result)
1224 return NULL;
1225 /* If we have been initialized from a tuple,
1226 st_?time might be set to None. Initialize it
1227 from the int slots. */
1228 for (i = 7; i <= 9; i++) {
1229 if (result->ob_item[i+3] == Py_None) {
1230 Py_DECREF(Py_None);
1231 Py_INCREF(result->ob_item[i]);
1232 result->ob_item[i+3] = result->ob_item[i];
1235 return (PyObject*)result;
1240 /* If true, st_?time is float. */
1241 static int _stat_float_times = 1;
1243 PyDoc_STRVAR(stat_float_times__doc__,
1244 "stat_float_times([newval]) -> oldval\n\n\
1245 Determine whether os.[lf]stat represents time stamps as float objects.\n\
1246 If newval is True, future calls to stat() return floats, if it is False,\n\
1247 future calls return ints. \n\
1248 If newval is omitted, return the current setting.\n");
1250 static PyObject*
1251 stat_float_times(PyObject* self, PyObject *args)
1253 int newval = -1;
1254 if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval))
1255 return NULL;
1256 if (newval == -1)
1257 /* Return old value */
1258 return PyBool_FromLong(_stat_float_times);
1259 _stat_float_times = newval;
1260 Py_INCREF(Py_None);
1261 return Py_None;
1264 static void
1265 fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
1267 PyObject *fval,*ival;
1268 #if SIZEOF_TIME_T > SIZEOF_LONG
1269 ival = PyLong_FromLongLong((PY_LONG_LONG)sec);
1270 #else
1271 ival = PyInt_FromLong((long)sec);
1272 #endif
1273 if (!ival)
1274 return;
1275 if (_stat_float_times) {
1276 fval = PyFloat_FromDouble(sec + 1e-9*nsec);
1277 } else {
1278 fval = ival;
1279 Py_INCREF(fval);
1281 PyStructSequence_SET_ITEM(v, index, ival);
1282 PyStructSequence_SET_ITEM(v, index+3, fval);
1285 /* pack a system stat C structure into the Python stat tuple
1286 (used by posix_stat() and posix_fstat()) */
1287 static PyObject*
1288 _pystat_fromstructstat(STRUCT_STAT *st)
1290 unsigned long ansec, mnsec, cnsec;
1291 PyObject *v = PyStructSequence_New(&StatResultType);
1292 if (v == NULL)
1293 return NULL;
1295 PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long)st->st_mode));
1296 #ifdef HAVE_LARGEFILE_SUPPORT
1297 PyStructSequence_SET_ITEM(v, 1,
1298 PyLong_FromLongLong((PY_LONG_LONG)st->st_ino));
1299 #else
1300 PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long)st->st_ino));
1301 #endif
1302 #if defined(HAVE_LONG_LONG) && !defined(MS_WINDOWS)
1303 PyStructSequence_SET_ITEM(v, 2,
1304 PyLong_FromLongLong((PY_LONG_LONG)st->st_dev));
1305 #else
1306 PyStructSequence_SET_ITEM(v, 2, PyInt_FromLong((long)st->st_dev));
1307 #endif
1308 PyStructSequence_SET_ITEM(v, 3, PyInt_FromLong((long)st->st_nlink));
1309 PyStructSequence_SET_ITEM(v, 4, PyInt_FromLong((long)st->st_uid));
1310 PyStructSequence_SET_ITEM(v, 5, PyInt_FromLong((long)st->st_gid));
1311 #ifdef HAVE_LARGEFILE_SUPPORT
1312 PyStructSequence_SET_ITEM(v, 6,
1313 PyLong_FromLongLong((PY_LONG_LONG)st->st_size));
1314 #else
1315 PyStructSequence_SET_ITEM(v, 6, PyInt_FromLong(st->st_size));
1316 #endif
1318 #if defined(HAVE_STAT_TV_NSEC)
1319 ansec = st->st_atim.tv_nsec;
1320 mnsec = st->st_mtim.tv_nsec;
1321 cnsec = st->st_ctim.tv_nsec;
1322 #elif defined(HAVE_STAT_TV_NSEC2)
1323 ansec = st->st_atimespec.tv_nsec;
1324 mnsec = st->st_mtimespec.tv_nsec;
1325 cnsec = st->st_ctimespec.tv_nsec;
1326 #elif defined(HAVE_STAT_NSEC)
1327 ansec = st->st_atime_nsec;
1328 mnsec = st->st_mtime_nsec;
1329 cnsec = st->st_ctime_nsec;
1330 #else
1331 ansec = mnsec = cnsec = 0;
1332 #endif
1333 fill_time(v, 7, st->st_atime, ansec);
1334 fill_time(v, 8, st->st_mtime, mnsec);
1335 fill_time(v, 9, st->st_ctime, cnsec);
1337 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1338 PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
1339 PyInt_FromLong((long)st->st_blksize));
1340 #endif
1341 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1342 PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
1343 PyInt_FromLong((long)st->st_blocks));
1344 #endif
1345 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1346 PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
1347 PyInt_FromLong((long)st->st_rdev));
1348 #endif
1349 #ifdef HAVE_STRUCT_STAT_ST_GEN
1350 PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
1351 PyInt_FromLong((long)st->st_gen));
1352 #endif
1353 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1355 PyObject *val;
1356 unsigned long bsec,bnsec;
1357 bsec = (long)st->st_birthtime;
1358 #ifdef HAVE_STAT_TV_NSEC2
1359 bnsec = st->st_birthtimespec.tv_nsec;
1360 #else
1361 bnsec = 0;
1362 #endif
1363 if (_stat_float_times) {
1364 val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
1365 } else {
1366 val = PyInt_FromLong((long)bsec);
1368 PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
1369 val);
1371 #endif
1372 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
1373 PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
1374 PyInt_FromLong((long)st->st_flags));
1375 #endif
1377 if (PyErr_Occurred()) {
1378 Py_DECREF(v);
1379 return NULL;
1382 return v;
1385 #ifdef MS_WINDOWS
1387 /* IsUNCRoot -- test whether the supplied path is of the form \\SERVER\SHARE\,
1388 where / can be used in place of \ and the trailing slash is optional.
1389 Both SERVER and SHARE must have at least one character.
1392 #define ISSLASHA(c) ((c) == '\\' || (c) == '/')
1393 #define ISSLASHW(c) ((c) == L'\\' || (c) == L'/')
1394 #ifndef ARRAYSIZE
1395 #define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0]))
1396 #endif
1398 static BOOL
1399 IsUNCRootA(char *path, int pathlen)
1401 #define ISSLASH ISSLASHA
1403 int i, share;
1405 if (pathlen < 5 || !ISSLASH(path[0]) || !ISSLASH(path[1]))
1406 /* minimum UNCRoot is \\x\y */
1407 return FALSE;
1408 for (i = 2; i < pathlen ; i++)
1409 if (ISSLASH(path[i])) break;
1410 if (i == 2 || i == pathlen)
1411 /* do not allow \\\SHARE or \\SERVER */
1412 return FALSE;
1413 share = i+1;
1414 for (i = share; i < pathlen; i++)
1415 if (ISSLASH(path[i])) break;
1416 return (i != share && (i == pathlen || i == pathlen-1));
1418 #undef ISSLASH
1421 static BOOL
1422 IsUNCRootW(Py_UNICODE *path, int pathlen)
1424 #define ISSLASH ISSLASHW
1426 int i, share;
1428 if (pathlen < 5 || !ISSLASH(path[0]) || !ISSLASH(path[1]))
1429 /* minimum UNCRoot is \\x\y */
1430 return FALSE;
1431 for (i = 2; i < pathlen ; i++)
1432 if (ISSLASH(path[i])) break;
1433 if (i == 2 || i == pathlen)
1434 /* do not allow \\\SHARE or \\SERVER */
1435 return FALSE;
1436 share = i+1;
1437 for (i = share; i < pathlen; i++)
1438 if (ISSLASH(path[i])) break;
1439 return (i != share && (i == pathlen || i == pathlen-1));
1441 #undef ISSLASH
1443 #endif /* MS_WINDOWS */
1445 static PyObject *
1446 posix_do_stat(PyObject *self, PyObject *args,
1447 char *format,
1448 #ifdef __VMS
1449 int (*statfunc)(const char *, STRUCT_STAT *, ...),
1450 #else
1451 int (*statfunc)(const char *, STRUCT_STAT *),
1452 #endif
1453 char *wformat,
1454 int (*wstatfunc)(const Py_UNICODE *, STRUCT_STAT *))
1456 STRUCT_STAT st;
1457 char *path = NULL; /* pass this to stat; do not free() it */
1458 char *pathfree = NULL; /* this memory must be free'd */
1459 int res;
1460 PyObject *result;
1462 #ifdef MS_WINDOWS
1463 PyUnicodeObject *po;
1464 if (PyArg_ParseTuple(args, wformat, &po)) {
1465 Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po);
1467 Py_BEGIN_ALLOW_THREADS
1468 /* PyUnicode_AS_UNICODE result OK without
1469 thread lock as it is a simple dereference. */
1470 res = wstatfunc(wpath, &st);
1471 Py_END_ALLOW_THREADS
1473 if (res != 0)
1474 return win32_error_unicode("stat", wpath);
1475 return _pystat_fromstructstat(&st);
1477 /* Drop the argument parsing error as narrow strings
1478 are also valid. */
1479 PyErr_Clear();
1480 #endif
1482 if (!PyArg_ParseTuple(args, format,
1483 Py_FileSystemDefaultEncoding, &path))
1484 return NULL;
1485 pathfree = path;
1487 Py_BEGIN_ALLOW_THREADS
1488 res = (*statfunc)(path, &st);
1489 Py_END_ALLOW_THREADS
1491 if (res != 0) {
1492 #ifdef MS_WINDOWS
1493 result = win32_error("stat", pathfree);
1494 #else
1495 result = posix_error_with_filename(pathfree);
1496 #endif
1498 else
1499 result = _pystat_fromstructstat(&st);
1501 PyMem_Free(pathfree);
1502 return result;
1505 /* POSIX methods */
1507 PyDoc_STRVAR(posix_access__doc__,
1508 "access(path, mode) -> True if granted, False otherwise\n\n\
1509 Use the real uid/gid to test for access to a path. Note that most\n\
1510 operations will use the effective uid/gid, therefore this routine can\n\
1511 be used in a suid/sgid environment to test if the invoking user has the\n\
1512 specified access to the path. The mode argument can be F_OK to test\n\
1513 existence, or the inclusive-OR of R_OK, W_OK, and X_OK.");
1515 static PyObject *
1516 posix_access(PyObject *self, PyObject *args)
1518 char *path;
1519 int mode;
1521 #ifdef MS_WINDOWS
1522 DWORD attr;
1523 PyUnicodeObject *po;
1524 if (PyArg_ParseTuple(args, "Ui:access", &po, &mode)) {
1525 Py_BEGIN_ALLOW_THREADS
1526 /* PyUnicode_AS_UNICODE OK without thread lock as
1527 it is a simple dereference. */
1528 attr = GetFileAttributesW(PyUnicode_AS_UNICODE(po));
1529 Py_END_ALLOW_THREADS
1530 goto finish;
1532 /* Drop the argument parsing error as narrow strings
1533 are also valid. */
1534 PyErr_Clear();
1535 if (!PyArg_ParseTuple(args, "eti:access",
1536 Py_FileSystemDefaultEncoding, &path, &mode))
1537 return NULL;
1538 Py_BEGIN_ALLOW_THREADS
1539 attr = GetFileAttributesA(path);
1540 Py_END_ALLOW_THREADS
1541 PyMem_Free(path);
1542 finish:
1543 if (attr == 0xFFFFFFFF)
1544 /* File does not exist, or cannot read attributes */
1545 return PyBool_FromLong(0);
1546 /* Access is possible if either write access wasn't requested, or
1547 the file isn't read-only, or if it's a directory, as there are
1548 no read-only directories on Windows. */
1549 return PyBool_FromLong(!(mode & 2)
1550 || !(attr & FILE_ATTRIBUTE_READONLY)
1551 || (attr & FILE_ATTRIBUTE_DIRECTORY));
1552 #else /* MS_WINDOWS */
1553 int res;
1554 if (!PyArg_ParseTuple(args, "eti:access",
1555 Py_FileSystemDefaultEncoding, &path, &mode))
1556 return NULL;
1557 Py_BEGIN_ALLOW_THREADS
1558 res = access(path, mode);
1559 Py_END_ALLOW_THREADS
1560 PyMem_Free(path);
1561 return PyBool_FromLong(res == 0);
1562 #endif /* MS_WINDOWS */
1565 #ifndef F_OK
1566 #define F_OK 0
1567 #endif
1568 #ifndef R_OK
1569 #define R_OK 4
1570 #endif
1571 #ifndef W_OK
1572 #define W_OK 2
1573 #endif
1574 #ifndef X_OK
1575 #define X_OK 1
1576 #endif
1578 #ifdef HAVE_TTYNAME
1579 PyDoc_STRVAR(posix_ttyname__doc__,
1580 "ttyname(fd) -> string\n\n\
1581 Return the name of the terminal device connected to 'fd'.");
1583 static PyObject *
1584 posix_ttyname(PyObject *self, PyObject *args)
1586 int id;
1587 char *ret;
1589 if (!PyArg_ParseTuple(args, "i:ttyname", &id))
1590 return NULL;
1592 #if defined(__VMS)
1593 /* file descriptor 0 only, the default input device (stdin) */
1594 if (id == 0) {
1595 ret = ttyname();
1597 else {
1598 ret = NULL;
1600 #else
1601 ret = ttyname(id);
1602 #endif
1603 if (ret == NULL)
1604 return posix_error();
1605 return PyString_FromString(ret);
1607 #endif
1609 #ifdef HAVE_CTERMID
1610 PyDoc_STRVAR(posix_ctermid__doc__,
1611 "ctermid() -> string\n\n\
1612 Return the name of the controlling terminal for this process.");
1614 static PyObject *
1615 posix_ctermid(PyObject *self, PyObject *noargs)
1617 char *ret;
1618 char buffer[L_ctermid];
1620 #ifdef USE_CTERMID_R
1621 ret = ctermid_r(buffer);
1622 #else
1623 ret = ctermid(buffer);
1624 #endif
1625 if (ret == NULL)
1626 return posix_error();
1627 return PyString_FromString(buffer);
1629 #endif
1631 PyDoc_STRVAR(posix_chdir__doc__,
1632 "chdir(path)\n\n\
1633 Change the current working directory to the specified path.");
1635 static PyObject *
1636 posix_chdir(PyObject *self, PyObject *args)
1638 #ifdef MS_WINDOWS
1639 return win32_1str(args, "chdir", "s:chdir", win32_chdir, "U:chdir", win32_wchdir);
1640 #elif defined(PYOS_OS2) && defined(PYCC_GCC)
1641 return posix_1str(args, "et:chdir", _chdir2);
1642 #elif defined(__VMS)
1643 return posix_1str(args, "et:chdir", (int (*)(const char *))chdir);
1644 #else
1645 return posix_1str(args, "et:chdir", chdir);
1646 #endif
1649 #ifdef HAVE_FCHDIR
1650 PyDoc_STRVAR(posix_fchdir__doc__,
1651 "fchdir(fildes)\n\n\
1652 Change to the directory of the given file descriptor. fildes must be\n\
1653 opened on a directory, not a file.");
1655 static PyObject *
1656 posix_fchdir(PyObject *self, PyObject *fdobj)
1658 return posix_fildes(fdobj, fchdir);
1660 #endif /* HAVE_FCHDIR */
1663 PyDoc_STRVAR(posix_chmod__doc__,
1664 "chmod(path, mode)\n\n\
1665 Change the access permissions of a file.");
1667 static PyObject *
1668 posix_chmod(PyObject *self, PyObject *args)
1670 char *path = NULL;
1671 int i;
1672 int res;
1673 #ifdef MS_WINDOWS
1674 DWORD attr;
1675 PyUnicodeObject *po;
1676 if (PyArg_ParseTuple(args, "Ui|:chmod", &po, &i)) {
1677 Py_BEGIN_ALLOW_THREADS
1678 attr = GetFileAttributesW(PyUnicode_AS_UNICODE(po));
1679 if (attr != 0xFFFFFFFF) {
1680 if (i & _S_IWRITE)
1681 attr &= ~FILE_ATTRIBUTE_READONLY;
1682 else
1683 attr |= FILE_ATTRIBUTE_READONLY;
1684 res = SetFileAttributesW(PyUnicode_AS_UNICODE(po), attr);
1686 else
1687 res = 0;
1688 Py_END_ALLOW_THREADS
1689 if (!res)
1690 return win32_error_unicode("chmod",
1691 PyUnicode_AS_UNICODE(po));
1692 Py_INCREF(Py_None);
1693 return Py_None;
1695 /* Drop the argument parsing error as narrow strings
1696 are also valid. */
1697 PyErr_Clear();
1699 if (!PyArg_ParseTuple(args, "eti:chmod", Py_FileSystemDefaultEncoding,
1700 &path, &i))
1701 return NULL;
1702 Py_BEGIN_ALLOW_THREADS
1703 attr = GetFileAttributesA(path);
1704 if (attr != 0xFFFFFFFF) {
1705 if (i & _S_IWRITE)
1706 attr &= ~FILE_ATTRIBUTE_READONLY;
1707 else
1708 attr |= FILE_ATTRIBUTE_READONLY;
1709 res = SetFileAttributesA(path, attr);
1711 else
1712 res = 0;
1713 Py_END_ALLOW_THREADS
1714 if (!res) {
1715 win32_error("chmod", path);
1716 PyMem_Free(path);
1717 return NULL;
1719 PyMem_Free(path);
1720 Py_INCREF(Py_None);
1721 return Py_None;
1722 #else /* MS_WINDOWS */
1723 if (!PyArg_ParseTuple(args, "eti:chmod", Py_FileSystemDefaultEncoding,
1724 &path, &i))
1725 return NULL;
1726 Py_BEGIN_ALLOW_THREADS
1727 res = chmod(path, i);
1728 Py_END_ALLOW_THREADS
1729 if (res < 0)
1730 return posix_error_with_allocated_filename(path);
1731 PyMem_Free(path);
1732 Py_INCREF(Py_None);
1733 return Py_None;
1734 #endif
1737 #ifdef HAVE_FCHMOD
1738 PyDoc_STRVAR(posix_fchmod__doc__,
1739 "fchmod(fd, mode)\n\n\
1740 Change the access permissions of the file given by file\n\
1741 descriptor fd.");
1743 static PyObject *
1744 posix_fchmod(PyObject *self, PyObject *args)
1746 int fd, mode, res;
1747 if (!PyArg_ParseTuple(args, "ii:fchmod", &fd, &mode))
1748 return NULL;
1749 Py_BEGIN_ALLOW_THREADS
1750 res = fchmod(fd, mode);
1751 Py_END_ALLOW_THREADS
1752 if (res < 0)
1753 return posix_error();
1754 Py_RETURN_NONE;
1756 #endif /* HAVE_FCHMOD */
1758 #ifdef HAVE_LCHMOD
1759 PyDoc_STRVAR(posix_lchmod__doc__,
1760 "lchmod(path, mode)\n\n\
1761 Change the access permissions of a file. If path is a symlink, this\n\
1762 affects the link itself rather than the target.");
1764 static PyObject *
1765 posix_lchmod(PyObject *self, PyObject *args)
1767 char *path = NULL;
1768 int i;
1769 int res;
1770 if (!PyArg_ParseTuple(args, "eti:lchmod", Py_FileSystemDefaultEncoding,
1771 &path, &i))
1772 return NULL;
1773 Py_BEGIN_ALLOW_THREADS
1774 res = lchmod(path, i);
1775 Py_END_ALLOW_THREADS
1776 if (res < 0)
1777 return posix_error_with_allocated_filename(path);
1778 PyMem_Free(path);
1779 Py_RETURN_NONE;
1781 #endif /* HAVE_LCHMOD */
1784 #ifdef HAVE_CHFLAGS
1785 PyDoc_STRVAR(posix_chflags__doc__,
1786 "chflags(path, flags)\n\n\
1787 Set file flags.");
1789 static PyObject *
1790 posix_chflags(PyObject *self, PyObject *args)
1792 char *path;
1793 unsigned long flags;
1794 int res;
1795 if (!PyArg_ParseTuple(args, "etk:chflags",
1796 Py_FileSystemDefaultEncoding, &path, &flags))
1797 return NULL;
1798 Py_BEGIN_ALLOW_THREADS
1799 res = chflags(path, flags);
1800 Py_END_ALLOW_THREADS
1801 if (res < 0)
1802 return posix_error_with_allocated_filename(path);
1803 PyMem_Free(path);
1804 Py_INCREF(Py_None);
1805 return Py_None;
1807 #endif /* HAVE_CHFLAGS */
1809 #ifdef HAVE_LCHFLAGS
1810 PyDoc_STRVAR(posix_lchflags__doc__,
1811 "lchflags(path, flags)\n\n\
1812 Set file flags.\n\
1813 This function will not follow symbolic links.");
1815 static PyObject *
1816 posix_lchflags(PyObject *self, PyObject *args)
1818 char *path;
1819 unsigned long flags;
1820 int res;
1821 if (!PyArg_ParseTuple(args, "etk:lchflags",
1822 Py_FileSystemDefaultEncoding, &path, &flags))
1823 return NULL;
1824 Py_BEGIN_ALLOW_THREADS
1825 res = lchflags(path, flags);
1826 Py_END_ALLOW_THREADS
1827 if (res < 0)
1828 return posix_error_with_allocated_filename(path);
1829 PyMem_Free(path);
1830 Py_INCREF(Py_None);
1831 return Py_None;
1833 #endif /* HAVE_LCHFLAGS */
1835 #ifdef HAVE_CHROOT
1836 PyDoc_STRVAR(posix_chroot__doc__,
1837 "chroot(path)\n\n\
1838 Change root directory to path.");
1840 static PyObject *
1841 posix_chroot(PyObject *self, PyObject *args)
1843 return posix_1str(args, "et:chroot", chroot);
1845 #endif
1847 #ifdef HAVE_FSYNC
1848 PyDoc_STRVAR(posix_fsync__doc__,
1849 "fsync(fildes)\n\n\
1850 force write of file with filedescriptor to disk.");
1852 static PyObject *
1853 posix_fsync(PyObject *self, PyObject *fdobj)
1855 return posix_fildes(fdobj, fsync);
1857 #endif /* HAVE_FSYNC */
1859 #ifdef HAVE_FDATASYNC
1861 #ifdef __hpux
1862 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
1863 #endif
1865 PyDoc_STRVAR(posix_fdatasync__doc__,
1866 "fdatasync(fildes)\n\n\
1867 force write of file with filedescriptor to disk.\n\
1868 does not force update of metadata.");
1870 static PyObject *
1871 posix_fdatasync(PyObject *self, PyObject *fdobj)
1873 return posix_fildes(fdobj, fdatasync);
1875 #endif /* HAVE_FDATASYNC */
1878 #ifdef HAVE_CHOWN
1879 PyDoc_STRVAR(posix_chown__doc__,
1880 "chown(path, uid, gid)\n\n\
1881 Change the owner and group id of path to the numeric uid and gid.");
1883 static PyObject *
1884 posix_chown(PyObject *self, PyObject *args)
1886 char *path = NULL;
1887 long uid, gid;
1888 int res;
1889 if (!PyArg_ParseTuple(args, "etll:chown",
1890 Py_FileSystemDefaultEncoding, &path,
1891 &uid, &gid))
1892 return NULL;
1893 Py_BEGIN_ALLOW_THREADS
1894 res = chown(path, (uid_t) uid, (gid_t) gid);
1895 Py_END_ALLOW_THREADS
1896 if (res < 0)
1897 return posix_error_with_allocated_filename(path);
1898 PyMem_Free(path);
1899 Py_INCREF(Py_None);
1900 return Py_None;
1902 #endif /* HAVE_CHOWN */
1904 #ifdef HAVE_FCHOWN
1905 PyDoc_STRVAR(posix_fchown__doc__,
1906 "fchown(fd, uid, gid)\n\n\
1907 Change the owner and group id of the file given by file descriptor\n\
1908 fd to the numeric uid and gid.");
1910 static PyObject *
1911 posix_fchown(PyObject *self, PyObject *args)
1913 int fd, uid, gid;
1914 int res;
1915 if (!PyArg_ParseTuple(args, "iii:chown", &fd, &uid, &gid))
1916 return NULL;
1917 Py_BEGIN_ALLOW_THREADS
1918 res = fchown(fd, (uid_t) uid, (gid_t) gid);
1919 Py_END_ALLOW_THREADS
1920 if (res < 0)
1921 return posix_error();
1922 Py_RETURN_NONE;
1924 #endif /* HAVE_FCHOWN */
1926 #ifdef HAVE_LCHOWN
1927 PyDoc_STRVAR(posix_lchown__doc__,
1928 "lchown(path, uid, gid)\n\n\
1929 Change the owner and group id of path to the numeric uid and gid.\n\
1930 This function will not follow symbolic links.");
1932 static PyObject *
1933 posix_lchown(PyObject *self, PyObject *args)
1935 char *path = NULL;
1936 int uid, gid;
1937 int res;
1938 if (!PyArg_ParseTuple(args, "etii:lchown",
1939 Py_FileSystemDefaultEncoding, &path,
1940 &uid, &gid))
1941 return NULL;
1942 Py_BEGIN_ALLOW_THREADS
1943 res = lchown(path, (uid_t) uid, (gid_t) gid);
1944 Py_END_ALLOW_THREADS
1945 if (res < 0)
1946 return posix_error_with_allocated_filename(path);
1947 PyMem_Free(path);
1948 Py_INCREF(Py_None);
1949 return Py_None;
1951 #endif /* HAVE_LCHOWN */
1954 #ifdef HAVE_GETCWD
1955 PyDoc_STRVAR(posix_getcwd__doc__,
1956 "getcwd() -> path\n\n\
1957 Return a string representing the current working directory.");
1959 static PyObject *
1960 posix_getcwd(PyObject *self, PyObject *noargs)
1962 int bufsize_incr = 1024;
1963 int bufsize = 0;
1964 char *tmpbuf = NULL;
1965 char *res = NULL;
1966 PyObject *dynamic_return;
1968 Py_BEGIN_ALLOW_THREADS
1969 do {
1970 bufsize = bufsize + bufsize_incr;
1971 tmpbuf = malloc(bufsize);
1972 if (tmpbuf == NULL) {
1973 break;
1975 #if defined(PYOS_OS2) && defined(PYCC_GCC)
1976 res = _getcwd2(tmpbuf, bufsize);
1977 #else
1978 res = getcwd(tmpbuf, bufsize);
1979 #endif
1981 if (res == NULL) {
1982 free(tmpbuf);
1984 } while ((res == NULL) && (errno == ERANGE));
1985 Py_END_ALLOW_THREADS
1987 if (res == NULL)
1988 return posix_error();
1990 dynamic_return = PyString_FromString(tmpbuf);
1991 free(tmpbuf);
1993 return dynamic_return;
1996 #ifdef Py_USING_UNICODE
1997 PyDoc_STRVAR(posix_getcwdu__doc__,
1998 "getcwdu() -> path\n\n\
1999 Return a unicode string representing the current working directory.");
2001 static PyObject *
2002 posix_getcwdu(PyObject *self, PyObject *noargs)
2004 char buf[1026];
2005 char *res;
2007 #ifdef MS_WINDOWS
2008 DWORD len;
2009 wchar_t wbuf[1026];
2010 wchar_t *wbuf2 = wbuf;
2011 PyObject *resobj;
2012 Py_BEGIN_ALLOW_THREADS
2013 len = GetCurrentDirectoryW(sizeof wbuf/ sizeof wbuf[0], wbuf);
2014 /* If the buffer is large enough, len does not include the
2015 terminating \0. If the buffer is too small, len includes
2016 the space needed for the terminator. */
2017 if (len >= sizeof wbuf/ sizeof wbuf[0]) {
2018 wbuf2 = malloc(len * sizeof(wchar_t));
2019 if (wbuf2)
2020 len = GetCurrentDirectoryW(len, wbuf2);
2022 Py_END_ALLOW_THREADS
2023 if (!wbuf2) {
2024 PyErr_NoMemory();
2025 return NULL;
2027 if (!len) {
2028 if (wbuf2 != wbuf) free(wbuf2);
2029 return win32_error("getcwdu", NULL);
2031 resobj = PyUnicode_FromWideChar(wbuf2, len);
2032 if (wbuf2 != wbuf) free(wbuf2);
2033 return resobj;
2034 #endif /* MS_WINDOWS */
2036 Py_BEGIN_ALLOW_THREADS
2037 #if defined(PYOS_OS2) && defined(PYCC_GCC)
2038 res = _getcwd2(buf, sizeof buf);
2039 #else
2040 res = getcwd(buf, sizeof buf);
2041 #endif
2042 Py_END_ALLOW_THREADS
2043 if (res == NULL)
2044 return posix_error();
2045 return PyUnicode_Decode(buf, strlen(buf), Py_FileSystemDefaultEncoding,"strict");
2047 #endif /* Py_USING_UNICODE */
2048 #endif /* HAVE_GETCWD */
2051 #ifdef HAVE_LINK
2052 PyDoc_STRVAR(posix_link__doc__,
2053 "link(src, dst)\n\n\
2054 Create a hard link to a file.");
2056 static PyObject *
2057 posix_link(PyObject *self, PyObject *args)
2059 return posix_2str(args, "etet:link", link);
2061 #endif /* HAVE_LINK */
2064 PyDoc_STRVAR(posix_listdir__doc__,
2065 "listdir(path) -> list_of_strings\n\n\
2066 Return a list containing the names of the entries in the directory.\n\
2068 path: path of directory to list\n\
2070 The list is in arbitrary order. It does not include the special\n\
2071 entries '.' and '..' even if they are present in the directory.");
2073 static PyObject *
2074 posix_listdir(PyObject *self, PyObject *args)
2076 /* XXX Should redo this putting the (now four) versions of opendir
2077 in separate files instead of having them all here... */
2078 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
2080 PyObject *d, *v;
2081 HANDLE hFindFile;
2082 BOOL result;
2083 WIN32_FIND_DATA FileData;
2084 char namebuf[MAX_PATH+5]; /* Overallocate for \\*.*\0 */
2085 char *bufptr = namebuf;
2086 Py_ssize_t len = sizeof(namebuf)-5; /* only claim to have space for MAX_PATH */
2088 PyObject *po;
2089 if (PyArg_ParseTuple(args, "U:listdir", &po)) {
2090 WIN32_FIND_DATAW wFileData;
2091 Py_UNICODE *wnamebuf;
2092 /* Overallocate for \\*.*\0 */
2093 len = PyUnicode_GET_SIZE(po);
2094 wnamebuf = malloc((len + 5) * sizeof(wchar_t));
2095 if (!wnamebuf) {
2096 PyErr_NoMemory();
2097 return NULL;
2099 wcscpy(wnamebuf, PyUnicode_AS_UNICODE(po));
2100 if (len > 0) {
2101 Py_UNICODE wch = wnamebuf[len-1];
2102 if (wch != L'/' && wch != L'\\' && wch != L':')
2103 wnamebuf[len++] = L'\\';
2104 wcscpy(wnamebuf + len, L"*.*");
2106 if ((d = PyList_New(0)) == NULL) {
2107 free(wnamebuf);
2108 return NULL;
2110 hFindFile = FindFirstFileW(wnamebuf, &wFileData);
2111 if (hFindFile == INVALID_HANDLE_VALUE) {
2112 int error = GetLastError();
2113 if (error == ERROR_FILE_NOT_FOUND) {
2114 free(wnamebuf);
2115 return d;
2117 Py_DECREF(d);
2118 win32_error_unicode("FindFirstFileW", wnamebuf);
2119 free(wnamebuf);
2120 return NULL;
2122 do {
2123 /* Skip over . and .. */
2124 if (wcscmp(wFileData.cFileName, L".") != 0 &&
2125 wcscmp(wFileData.cFileName, L"..") != 0) {
2126 v = PyUnicode_FromUnicode(wFileData.cFileName, wcslen(wFileData.cFileName));
2127 if (v == NULL) {
2128 Py_DECREF(d);
2129 d = NULL;
2130 break;
2132 if (PyList_Append(d, v) != 0) {
2133 Py_DECREF(v);
2134 Py_DECREF(d);
2135 d = NULL;
2136 break;
2138 Py_DECREF(v);
2140 Py_BEGIN_ALLOW_THREADS
2141 result = FindNextFileW(hFindFile, &wFileData);
2142 Py_END_ALLOW_THREADS
2143 /* FindNextFile sets error to ERROR_NO_MORE_FILES if
2144 it got to the end of the directory. */
2145 if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
2146 Py_DECREF(d);
2147 win32_error_unicode("FindNextFileW", wnamebuf);
2148 FindClose(hFindFile);
2149 free(wnamebuf);
2150 return NULL;
2152 } while (result == TRUE);
2154 if (FindClose(hFindFile) == FALSE) {
2155 Py_DECREF(d);
2156 win32_error_unicode("FindClose", wnamebuf);
2157 free(wnamebuf);
2158 return NULL;
2160 free(wnamebuf);
2161 return d;
2163 /* Drop the argument parsing error as narrow strings
2164 are also valid. */
2165 PyErr_Clear();
2167 if (!PyArg_ParseTuple(args, "et#:listdir",
2168 Py_FileSystemDefaultEncoding, &bufptr, &len))
2169 return NULL;
2170 if (len > 0) {
2171 char ch = namebuf[len-1];
2172 if (ch != SEP && ch != ALTSEP && ch != ':')
2173 namebuf[len++] = '/';
2174 strcpy(namebuf + len, "*.*");
2177 if ((d = PyList_New(0)) == NULL)
2178 return NULL;
2180 hFindFile = FindFirstFile(namebuf, &FileData);
2181 if (hFindFile == INVALID_HANDLE_VALUE) {
2182 int error = GetLastError();
2183 if (error == ERROR_FILE_NOT_FOUND)
2184 return d;
2185 Py_DECREF(d);
2186 return win32_error("FindFirstFile", namebuf);
2188 do {
2189 /* Skip over . and .. */
2190 if (strcmp(FileData.cFileName, ".") != 0 &&
2191 strcmp(FileData.cFileName, "..") != 0) {
2192 v = PyString_FromString(FileData.cFileName);
2193 if (v == NULL) {
2194 Py_DECREF(d);
2195 d = NULL;
2196 break;
2198 if (PyList_Append(d, v) != 0) {
2199 Py_DECREF(v);
2200 Py_DECREF(d);
2201 d = NULL;
2202 break;
2204 Py_DECREF(v);
2206 Py_BEGIN_ALLOW_THREADS
2207 result = FindNextFile(hFindFile, &FileData);
2208 Py_END_ALLOW_THREADS
2209 /* FindNextFile sets error to ERROR_NO_MORE_FILES if
2210 it got to the end of the directory. */
2211 if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
2212 Py_DECREF(d);
2213 win32_error("FindNextFile", namebuf);
2214 FindClose(hFindFile);
2215 return NULL;
2217 } while (result == TRUE);
2219 if (FindClose(hFindFile) == FALSE) {
2220 Py_DECREF(d);
2221 return win32_error("FindClose", namebuf);
2224 return d;
2226 #elif defined(PYOS_OS2)
2228 #ifndef MAX_PATH
2229 #define MAX_PATH CCHMAXPATH
2230 #endif
2231 char *name, *pt;
2232 Py_ssize_t len;
2233 PyObject *d, *v;
2234 char namebuf[MAX_PATH+5];
2235 HDIR hdir = 1;
2236 ULONG srchcnt = 1;
2237 FILEFINDBUF3 ep;
2238 APIRET rc;
2240 if (!PyArg_ParseTuple(args, "t#:listdir", &name, &len))
2241 return NULL;
2242 if (len >= MAX_PATH) {
2243 PyErr_SetString(PyExc_ValueError, "path too long");
2244 return NULL;
2246 strcpy(namebuf, name);
2247 for (pt = namebuf; *pt; pt++)
2248 if (*pt == ALTSEP)
2249 *pt = SEP;
2250 if (namebuf[len-1] != SEP)
2251 namebuf[len++] = SEP;
2252 strcpy(namebuf + len, "*.*");
2254 if ((d = PyList_New(0)) == NULL)
2255 return NULL;
2257 rc = DosFindFirst(namebuf, /* Wildcard Pattern to Match */
2258 &hdir, /* Handle to Use While Search Directory */
2259 FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY,
2260 &ep, sizeof(ep), /* Structure to Receive Directory Entry */
2261 &srchcnt, /* Max and Actual Count of Entries Per Iteration */
2262 FIL_STANDARD); /* Format of Entry (EAs or Not) */
2264 if (rc != NO_ERROR) {
2265 errno = ENOENT;
2266 return posix_error_with_filename(name);
2269 if (srchcnt > 0) { /* If Directory is NOT Totally Empty, */
2270 do {
2271 if (ep.achName[0] == '.'
2272 && (ep.achName[1] == '\0' || (ep.achName[1] == '.' && ep.achName[2] == '\0')))
2273 continue; /* Skip Over "." and ".." Names */
2275 strcpy(namebuf, ep.achName);
2277 /* Leave Case of Name Alone -- In Native Form */
2278 /* (Removed Forced Lowercasing Code) */
2280 v = PyString_FromString(namebuf);
2281 if (v == NULL) {
2282 Py_DECREF(d);
2283 d = NULL;
2284 break;
2286 if (PyList_Append(d, v) != 0) {
2287 Py_DECREF(v);
2288 Py_DECREF(d);
2289 d = NULL;
2290 break;
2292 Py_DECREF(v);
2293 } while (DosFindNext(hdir, &ep, sizeof(ep), &srchcnt) == NO_ERROR && srchcnt > 0);
2296 return d;
2297 #else
2299 char *name = NULL;
2300 PyObject *d, *v;
2301 DIR *dirp;
2302 struct dirent *ep;
2303 int arg_is_unicode = 1;
2305 errno = 0;
2306 if (!PyArg_ParseTuple(args, "U:listdir", &v)) {
2307 arg_is_unicode = 0;
2308 PyErr_Clear();
2310 if (!PyArg_ParseTuple(args, "et:listdir", Py_FileSystemDefaultEncoding, &name))
2311 return NULL;
2312 if ((dirp = opendir(name)) == NULL) {
2313 return posix_error_with_allocated_filename(name);
2315 if ((d = PyList_New(0)) == NULL) {
2316 closedir(dirp);
2317 PyMem_Free(name);
2318 return NULL;
2320 for (;;) {
2321 errno = 0;
2322 Py_BEGIN_ALLOW_THREADS
2323 ep = readdir(dirp);
2324 Py_END_ALLOW_THREADS
2325 if (ep == NULL) {
2326 if (errno == 0) {
2327 break;
2328 } else {
2329 closedir(dirp);
2330 Py_DECREF(d);
2331 return posix_error_with_allocated_filename(name);
2334 if (ep->d_name[0] == '.' &&
2335 (NAMLEN(ep) == 1 ||
2336 (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
2337 continue;
2338 v = PyString_FromStringAndSize(ep->d_name, NAMLEN(ep));
2339 if (v == NULL) {
2340 Py_DECREF(d);
2341 d = NULL;
2342 break;
2344 #ifdef Py_USING_UNICODE
2345 if (arg_is_unicode) {
2346 PyObject *w;
2348 w = PyUnicode_FromEncodedObject(v,
2349 Py_FileSystemDefaultEncoding,
2350 "strict");
2351 if (w != NULL) {
2352 Py_DECREF(v);
2353 v = w;
2355 else {
2356 /* fall back to the original byte string, as
2357 discussed in patch #683592 */
2358 PyErr_Clear();
2361 #endif
2362 if (PyList_Append(d, v) != 0) {
2363 Py_DECREF(v);
2364 Py_DECREF(d);
2365 d = NULL;
2366 break;
2368 Py_DECREF(v);
2370 closedir(dirp);
2371 PyMem_Free(name);
2373 return d;
2375 #endif /* which OS */
2376 } /* end of posix_listdir */
2378 #ifdef MS_WINDOWS
2379 /* A helper function for abspath on win32 */
2380 static PyObject *
2381 posix__getfullpathname(PyObject *self, PyObject *args)
2383 /* assume encoded strings won't more than double no of chars */
2384 char inbuf[MAX_PATH*2];
2385 char *inbufp = inbuf;
2386 Py_ssize_t insize = sizeof(inbuf);
2387 char outbuf[MAX_PATH*2];
2388 char *temp;
2390 PyUnicodeObject *po;
2391 if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po)) {
2392 Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po);
2393 Py_UNICODE woutbuf[MAX_PATH*2], *woutbufp = woutbuf;
2394 Py_UNICODE *wtemp;
2395 DWORD result;
2396 PyObject *v;
2397 result = GetFullPathNameW(wpath,
2398 sizeof(woutbuf)/sizeof(woutbuf[0]),
2399 woutbuf, &wtemp);
2400 if (result > sizeof(woutbuf)/sizeof(woutbuf[0])) {
2401 woutbufp = malloc(result * sizeof(Py_UNICODE));
2402 if (!woutbufp)
2403 return PyErr_NoMemory();
2404 result = GetFullPathNameW(wpath, result, woutbufp, &wtemp);
2406 if (result)
2407 v = PyUnicode_FromUnicode(woutbufp, wcslen(woutbufp));
2408 else
2409 v = win32_error_unicode("GetFullPathNameW", wpath);
2410 if (woutbufp != woutbuf)
2411 free(woutbufp);
2412 return v;
2414 /* Drop the argument parsing error as narrow strings
2415 are also valid. */
2416 PyErr_Clear();
2418 if (!PyArg_ParseTuple (args, "et#:_getfullpathname",
2419 Py_FileSystemDefaultEncoding, &inbufp,
2420 &insize))
2421 return NULL;
2422 if (!GetFullPathName(inbuf, sizeof(outbuf)/sizeof(outbuf[0]),
2423 outbuf, &temp))
2424 return win32_error("GetFullPathName", inbuf);
2425 if (PyUnicode_Check(PyTuple_GetItem(args, 0))) {
2426 return PyUnicode_Decode(outbuf, strlen(outbuf),
2427 Py_FileSystemDefaultEncoding, NULL);
2429 return PyString_FromString(outbuf);
2430 } /* end of posix__getfullpathname */
2431 #endif /* MS_WINDOWS */
2433 PyDoc_STRVAR(posix_mkdir__doc__,
2434 "mkdir(path [, mode=0777])\n\n\
2435 Create a directory.");
2437 static PyObject *
2438 posix_mkdir(PyObject *self, PyObject *args)
2440 int res;
2441 char *path = NULL;
2442 int mode = 0777;
2444 #ifdef MS_WINDOWS
2445 PyUnicodeObject *po;
2446 if (PyArg_ParseTuple(args, "U|i:mkdir", &po, &mode)) {
2447 Py_BEGIN_ALLOW_THREADS
2448 /* PyUnicode_AS_UNICODE OK without thread lock as
2449 it is a simple dereference. */
2450 res = CreateDirectoryW(PyUnicode_AS_UNICODE(po), NULL);
2451 Py_END_ALLOW_THREADS
2452 if (!res)
2453 return win32_error_unicode("mkdir", PyUnicode_AS_UNICODE(po));
2454 Py_INCREF(Py_None);
2455 return Py_None;
2457 /* Drop the argument parsing error as narrow strings
2458 are also valid. */
2459 PyErr_Clear();
2460 if (!PyArg_ParseTuple(args, "et|i:mkdir",
2461 Py_FileSystemDefaultEncoding, &path, &mode))
2462 return NULL;
2463 Py_BEGIN_ALLOW_THREADS
2464 /* PyUnicode_AS_UNICODE OK without thread lock as
2465 it is a simple dereference. */
2466 res = CreateDirectoryA(path, NULL);
2467 Py_END_ALLOW_THREADS
2468 if (!res) {
2469 win32_error("mkdir", path);
2470 PyMem_Free(path);
2471 return NULL;
2473 PyMem_Free(path);
2474 Py_INCREF(Py_None);
2475 return Py_None;
2476 #else /* MS_WINDOWS */
2478 if (!PyArg_ParseTuple(args, "et|i:mkdir",
2479 Py_FileSystemDefaultEncoding, &path, &mode))
2480 return NULL;
2481 Py_BEGIN_ALLOW_THREADS
2482 #if ( defined(__WATCOMC__) || defined(PYCC_VACPP) ) && !defined(__QNX__)
2483 res = mkdir(path);
2484 #else
2485 res = mkdir(path, mode);
2486 #endif
2487 Py_END_ALLOW_THREADS
2488 if (res < 0)
2489 return posix_error_with_allocated_filename(path);
2490 PyMem_Free(path);
2491 Py_INCREF(Py_None);
2492 return Py_None;
2493 #endif /* MS_WINDOWS */
2497 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
2498 #if defined(HAVE_SYS_RESOURCE_H)
2499 #include <sys/resource.h>
2500 #endif
2503 #ifdef HAVE_NICE
2504 PyDoc_STRVAR(posix_nice__doc__,
2505 "nice(inc) -> new_priority\n\n\
2506 Decrease the priority of process by inc and return the new priority.");
2508 static PyObject *
2509 posix_nice(PyObject *self, PyObject *args)
2511 int increment, value;
2513 if (!PyArg_ParseTuple(args, "i:nice", &increment))
2514 return NULL;
2516 /* There are two flavours of 'nice': one that returns the new
2517 priority (as required by almost all standards out there) and the
2518 Linux/FreeBSD/BSDI one, which returns '0' on success and advices
2519 the use of getpriority() to get the new priority.
2521 If we are of the nice family that returns the new priority, we
2522 need to clear errno before the call, and check if errno is filled
2523 before calling posix_error() on a returnvalue of -1, because the
2524 -1 may be the actual new priority! */
2526 errno = 0;
2527 value = nice(increment);
2528 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
2529 if (value == 0)
2530 value = getpriority(PRIO_PROCESS, 0);
2531 #endif
2532 if (value == -1 && errno != 0)
2533 /* either nice() or getpriority() returned an error */
2534 return posix_error();
2535 return PyInt_FromLong((long) value);
2537 #endif /* HAVE_NICE */
2539 PyDoc_STRVAR(posix_rename__doc__,
2540 "rename(old, new)\n\n\
2541 Rename a file or directory.");
2543 static PyObject *
2544 posix_rename(PyObject *self, PyObject *args)
2546 #ifdef MS_WINDOWS
2547 PyObject *o1, *o2;
2548 char *p1, *p2;
2549 BOOL result;
2550 if (!PyArg_ParseTuple(args, "OO:rename", &o1, &o2))
2551 goto error;
2552 if (!convert_to_unicode(&o1))
2553 goto error;
2554 if (!convert_to_unicode(&o2)) {
2555 Py_DECREF(o1);
2556 goto error;
2558 Py_BEGIN_ALLOW_THREADS
2559 result = MoveFileW(PyUnicode_AsUnicode(o1),
2560 PyUnicode_AsUnicode(o2));
2561 Py_END_ALLOW_THREADS
2562 Py_DECREF(o1);
2563 Py_DECREF(o2);
2564 if (!result)
2565 return win32_error("rename", NULL);
2566 Py_INCREF(Py_None);
2567 return Py_None;
2568 error:
2569 PyErr_Clear();
2570 if (!PyArg_ParseTuple(args, "ss:rename", &p1, &p2))
2571 return NULL;
2572 Py_BEGIN_ALLOW_THREADS
2573 result = MoveFileA(p1, p2);
2574 Py_END_ALLOW_THREADS
2575 if (!result)
2576 return win32_error("rename", NULL);
2577 Py_INCREF(Py_None);
2578 return Py_None;
2579 #else
2580 return posix_2str(args, "etet:rename", rename);
2581 #endif
2585 PyDoc_STRVAR(posix_rmdir__doc__,
2586 "rmdir(path)\n\n\
2587 Remove a directory.");
2589 static PyObject *
2590 posix_rmdir(PyObject *self, PyObject *args)
2592 #ifdef MS_WINDOWS
2593 return win32_1str(args, "rmdir", "s:rmdir", RemoveDirectoryA, "U:rmdir", RemoveDirectoryW);
2594 #else
2595 return posix_1str(args, "et:rmdir", rmdir);
2596 #endif
2600 PyDoc_STRVAR(posix_stat__doc__,
2601 "stat(path) -> stat result\n\n\
2602 Perform a stat system call on the given path.");
2604 static PyObject *
2605 posix_stat(PyObject *self, PyObject *args)
2607 #ifdef MS_WINDOWS
2608 return posix_do_stat(self, args, "et:stat", STAT, "U:stat", win32_wstat);
2609 #else
2610 return posix_do_stat(self, args, "et:stat", STAT, NULL, NULL);
2611 #endif
2615 #ifdef HAVE_SYSTEM
2616 PyDoc_STRVAR(posix_system__doc__,
2617 "system(command) -> exit_status\n\n\
2618 Execute the command (a string) in a subshell.");
2620 static PyObject *
2621 posix_system(PyObject *self, PyObject *args)
2623 char *command;
2624 long sts;
2625 if (!PyArg_ParseTuple(args, "s:system", &command))
2626 return NULL;
2627 Py_BEGIN_ALLOW_THREADS
2628 sts = system(command);
2629 Py_END_ALLOW_THREADS
2630 return PyInt_FromLong(sts);
2632 #endif
2635 PyDoc_STRVAR(posix_umask__doc__,
2636 "umask(new_mask) -> old_mask\n\n\
2637 Set the current numeric umask and return the previous umask.");
2639 static PyObject *
2640 posix_umask(PyObject *self, PyObject *args)
2642 int i;
2643 if (!PyArg_ParseTuple(args, "i:umask", &i))
2644 return NULL;
2645 i = (int)umask(i);
2646 if (i < 0)
2647 return posix_error();
2648 return PyInt_FromLong((long)i);
2652 PyDoc_STRVAR(posix_unlink__doc__,
2653 "unlink(path)\n\n\
2654 Remove a file (same as remove(path)).");
2656 PyDoc_STRVAR(posix_remove__doc__,
2657 "remove(path)\n\n\
2658 Remove a file (same as unlink(path)).");
2660 static PyObject *
2661 posix_unlink(PyObject *self, PyObject *args)
2663 #ifdef MS_WINDOWS
2664 return win32_1str(args, "remove", "s:remove", DeleteFileA, "U:remove", DeleteFileW);
2665 #else
2666 return posix_1str(args, "et:remove", unlink);
2667 #endif
2671 #ifdef HAVE_UNAME
2672 PyDoc_STRVAR(posix_uname__doc__,
2673 "uname() -> (sysname, nodename, release, version, machine)\n\n\
2674 Return a tuple identifying the current operating system.");
2676 static PyObject *
2677 posix_uname(PyObject *self, PyObject *noargs)
2679 struct utsname u;
2680 int res;
2682 Py_BEGIN_ALLOW_THREADS
2683 res = uname(&u);
2684 Py_END_ALLOW_THREADS
2685 if (res < 0)
2686 return posix_error();
2687 return Py_BuildValue("(sssss)",
2688 u.sysname,
2689 u.nodename,
2690 u.release,
2691 u.version,
2692 u.machine);
2694 #endif /* HAVE_UNAME */
2696 static int
2697 extract_time(PyObject *t, long* sec, long* usec)
2699 long intval;
2700 if (PyFloat_Check(t)) {
2701 double tval = PyFloat_AsDouble(t);
2702 PyObject *intobj = Py_TYPE(t)->tp_as_number->nb_int(t);
2703 if (!intobj)
2704 return -1;
2705 intval = PyInt_AsLong(intobj);
2706 Py_DECREF(intobj);
2707 if (intval == -1 && PyErr_Occurred())
2708 return -1;
2709 *sec = intval;
2710 *usec = (long)((tval - intval) * 1e6); /* can't exceed 1000000 */
2711 if (*usec < 0)
2712 /* If rounding gave us a negative number,
2713 truncate. */
2714 *usec = 0;
2715 return 0;
2717 intval = PyInt_AsLong(t);
2718 if (intval == -1 && PyErr_Occurred())
2719 return -1;
2720 *sec = intval;
2721 *usec = 0;
2722 return 0;
2725 PyDoc_STRVAR(posix_utime__doc__,
2726 "utime(path, (atime, mtime))\n\
2727 utime(path, None)\n\n\
2728 Set the access and modified time of the file to the given values. If the\n\
2729 second form is used, set the access and modified times to the current time.");
2731 static PyObject *
2732 posix_utime(PyObject *self, PyObject *args)
2734 #ifdef MS_WINDOWS
2735 PyObject *arg;
2736 PyUnicodeObject *obwpath;
2737 wchar_t *wpath = NULL;
2738 char *apath = NULL;
2739 HANDLE hFile;
2740 long atimesec, mtimesec, ausec, musec;
2741 FILETIME atime, mtime;
2742 PyObject *result = NULL;
2744 if (PyArg_ParseTuple(args, "UO|:utime", &obwpath, &arg)) {
2745 wpath = PyUnicode_AS_UNICODE(obwpath);
2746 Py_BEGIN_ALLOW_THREADS
2747 hFile = CreateFileW(wpath, FILE_WRITE_ATTRIBUTES, 0,
2748 NULL, OPEN_EXISTING,
2749 FILE_FLAG_BACKUP_SEMANTICS, NULL);
2750 Py_END_ALLOW_THREADS
2751 if (hFile == INVALID_HANDLE_VALUE)
2752 return win32_error_unicode("utime", wpath);
2753 } else
2754 /* Drop the argument parsing error as narrow strings
2755 are also valid. */
2756 PyErr_Clear();
2758 if (!wpath) {
2759 if (!PyArg_ParseTuple(args, "etO:utime",
2760 Py_FileSystemDefaultEncoding, &apath, &arg))
2761 return NULL;
2762 Py_BEGIN_ALLOW_THREADS
2763 hFile = CreateFileA(apath, FILE_WRITE_ATTRIBUTES, 0,
2764 NULL, OPEN_EXISTING,
2765 FILE_FLAG_BACKUP_SEMANTICS, NULL);
2766 Py_END_ALLOW_THREADS
2767 if (hFile == INVALID_HANDLE_VALUE) {
2768 win32_error("utime", apath);
2769 PyMem_Free(apath);
2770 return NULL;
2772 PyMem_Free(apath);
2775 if (arg == Py_None) {
2776 SYSTEMTIME now;
2777 GetSystemTime(&now);
2778 if (!SystemTimeToFileTime(&now, &mtime) ||
2779 !SystemTimeToFileTime(&now, &atime)) {
2780 win32_error("utime", NULL);
2781 goto done;
2784 else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) {
2785 PyErr_SetString(PyExc_TypeError,
2786 "utime() arg 2 must be a tuple (atime, mtime)");
2787 goto done;
2789 else {
2790 if (extract_time(PyTuple_GET_ITEM(arg, 0),
2791 &atimesec, &ausec) == -1)
2792 goto done;
2793 time_t_to_FILE_TIME(atimesec, 1000*ausec, &atime);
2794 if (extract_time(PyTuple_GET_ITEM(arg, 1),
2795 &mtimesec, &musec) == -1)
2796 goto done;
2797 time_t_to_FILE_TIME(mtimesec, 1000*musec, &mtime);
2799 if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
2800 /* Avoid putting the file name into the error here,
2801 as that may confuse the user into believing that
2802 something is wrong with the file, when it also
2803 could be the time stamp that gives a problem. */
2804 win32_error("utime", NULL);
2806 Py_INCREF(Py_None);
2807 result = Py_None;
2808 done:
2809 CloseHandle(hFile);
2810 return result;
2811 #else /* MS_WINDOWS */
2813 char *path = NULL;
2814 long atime, mtime, ausec, musec;
2815 int res;
2816 PyObject* arg;
2818 #if defined(HAVE_UTIMES)
2819 struct timeval buf[2];
2820 #define ATIME buf[0].tv_sec
2821 #define MTIME buf[1].tv_sec
2822 #elif defined(HAVE_UTIME_H)
2823 /* XXX should define struct utimbuf instead, above */
2824 struct utimbuf buf;
2825 #define ATIME buf.actime
2826 #define MTIME buf.modtime
2827 #define UTIME_ARG &buf
2828 #else /* HAVE_UTIMES */
2829 time_t buf[2];
2830 #define ATIME buf[0]
2831 #define MTIME buf[1]
2832 #define UTIME_ARG buf
2833 #endif /* HAVE_UTIMES */
2836 if (!PyArg_ParseTuple(args, "etO:utime",
2837 Py_FileSystemDefaultEncoding, &path, &arg))
2838 return NULL;
2839 if (arg == Py_None) {
2840 /* optional time values not given */
2841 Py_BEGIN_ALLOW_THREADS
2842 res = utime(path, NULL);
2843 Py_END_ALLOW_THREADS
2845 else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) {
2846 PyErr_SetString(PyExc_TypeError,
2847 "utime() arg 2 must be a tuple (atime, mtime)");
2848 PyMem_Free(path);
2849 return NULL;
2851 else {
2852 if (extract_time(PyTuple_GET_ITEM(arg, 0),
2853 &atime, &ausec) == -1) {
2854 PyMem_Free(path);
2855 return NULL;
2857 if (extract_time(PyTuple_GET_ITEM(arg, 1),
2858 &mtime, &musec) == -1) {
2859 PyMem_Free(path);
2860 return NULL;
2862 ATIME = atime;
2863 MTIME = mtime;
2864 #ifdef HAVE_UTIMES
2865 buf[0].tv_usec = ausec;
2866 buf[1].tv_usec = musec;
2867 Py_BEGIN_ALLOW_THREADS
2868 res = utimes(path, buf);
2869 Py_END_ALLOW_THREADS
2870 #else
2871 Py_BEGIN_ALLOW_THREADS
2872 res = utime(path, UTIME_ARG);
2873 Py_END_ALLOW_THREADS
2874 #endif /* HAVE_UTIMES */
2876 if (res < 0) {
2877 return posix_error_with_allocated_filename(path);
2879 PyMem_Free(path);
2880 Py_INCREF(Py_None);
2881 return Py_None;
2882 #undef UTIME_ARG
2883 #undef ATIME
2884 #undef MTIME
2885 #endif /* MS_WINDOWS */
2889 /* Process operations */
2891 PyDoc_STRVAR(posix__exit__doc__,
2892 "_exit(status)\n\n\
2893 Exit to the system with specified status, without normal exit processing.");
2895 static PyObject *
2896 posix__exit(PyObject *self, PyObject *args)
2898 int sts;
2899 if (!PyArg_ParseTuple(args, "i:_exit", &sts))
2900 return NULL;
2901 _exit(sts);
2902 return NULL; /* Make gcc -Wall happy */
2905 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV)
2906 static void
2907 free_string_array(char **array, Py_ssize_t count)
2909 Py_ssize_t i;
2910 for (i = 0; i < count; i++)
2911 PyMem_Free(array[i]);
2912 PyMem_DEL(array);
2914 #endif
2917 #ifdef HAVE_EXECV
2918 PyDoc_STRVAR(posix_execv__doc__,
2919 "execv(path, args)\n\n\
2920 Execute an executable path with arguments, replacing current process.\n\
2922 path: path of executable file\n\
2923 args: tuple or list of strings");
2925 static PyObject *
2926 posix_execv(PyObject *self, PyObject *args)
2928 char *path;
2929 PyObject *argv;
2930 char **argvlist;
2931 Py_ssize_t i, argc;
2932 PyObject *(*getitem)(PyObject *, Py_ssize_t);
2934 /* execv has two arguments: (path, argv), where
2935 argv is a list or tuple of strings. */
2937 if (!PyArg_ParseTuple(args, "etO:execv",
2938 Py_FileSystemDefaultEncoding,
2939 &path, &argv))
2940 return NULL;
2941 if (PyList_Check(argv)) {
2942 argc = PyList_Size(argv);
2943 getitem = PyList_GetItem;
2945 else if (PyTuple_Check(argv)) {
2946 argc = PyTuple_Size(argv);
2947 getitem = PyTuple_GetItem;
2949 else {
2950 PyErr_SetString(PyExc_TypeError, "execv() arg 2 must be a tuple or list");
2951 PyMem_Free(path);
2952 return NULL;
2955 argvlist = PyMem_NEW(char *, argc+1);
2956 if (argvlist == NULL) {
2957 PyMem_Free(path);
2958 return PyErr_NoMemory();
2960 for (i = 0; i < argc; i++) {
2961 if (!PyArg_Parse((*getitem)(argv, i), "et",
2962 Py_FileSystemDefaultEncoding,
2963 &argvlist[i])) {
2964 free_string_array(argvlist, i);
2965 PyErr_SetString(PyExc_TypeError,
2966 "execv() arg 2 must contain only strings");
2967 PyMem_Free(path);
2968 return NULL;
2972 argvlist[argc] = NULL;
2974 execv(path, argvlist);
2976 /* If we get here it's definitely an error */
2978 free_string_array(argvlist, argc);
2979 PyMem_Free(path);
2980 return posix_error();
2984 PyDoc_STRVAR(posix_execve__doc__,
2985 "execve(path, args, env)\n\n\
2986 Execute a path with arguments and environment, replacing current process.\n\
2988 path: path of executable file\n\
2989 args: tuple or list of arguments\n\
2990 env: dictionary of strings mapping to strings");
2992 static PyObject *
2993 posix_execve(PyObject *self, PyObject *args)
2995 char *path;
2996 PyObject *argv, *env;
2997 char **argvlist;
2998 char **envlist;
2999 PyObject *key, *val, *keys=NULL, *vals=NULL;
3000 Py_ssize_t i, pos, argc, envc;
3001 PyObject *(*getitem)(PyObject *, Py_ssize_t);
3002 Py_ssize_t lastarg = 0;
3004 /* execve has three arguments: (path, argv, env), where
3005 argv is a list or tuple of strings and env is a dictionary
3006 like posix.environ. */
3008 if (!PyArg_ParseTuple(args, "etOO:execve",
3009 Py_FileSystemDefaultEncoding,
3010 &path, &argv, &env))
3011 return NULL;
3012 if (PyList_Check(argv)) {
3013 argc = PyList_Size(argv);
3014 getitem = PyList_GetItem;
3016 else if (PyTuple_Check(argv)) {
3017 argc = PyTuple_Size(argv);
3018 getitem = PyTuple_GetItem;
3020 else {
3021 PyErr_SetString(PyExc_TypeError,
3022 "execve() arg 2 must be a tuple or list");
3023 goto fail_0;
3025 if (!PyMapping_Check(env)) {
3026 PyErr_SetString(PyExc_TypeError,
3027 "execve() arg 3 must be a mapping object");
3028 goto fail_0;
3031 argvlist = PyMem_NEW(char *, argc+1);
3032 if (argvlist == NULL) {
3033 PyErr_NoMemory();
3034 goto fail_0;
3036 for (i = 0; i < argc; i++) {
3037 if (!PyArg_Parse((*getitem)(argv, i),
3038 "et;execve() arg 2 must contain only strings",
3039 Py_FileSystemDefaultEncoding,
3040 &argvlist[i]))
3042 lastarg = i;
3043 goto fail_1;
3046 lastarg = argc;
3047 argvlist[argc] = NULL;
3049 i = PyMapping_Size(env);
3050 if (i < 0)
3051 goto fail_1;
3052 envlist = PyMem_NEW(char *, i + 1);
3053 if (envlist == NULL) {
3054 PyErr_NoMemory();
3055 goto fail_1;
3057 envc = 0;
3058 keys = PyMapping_Keys(env);
3059 vals = PyMapping_Values(env);
3060 if (!keys || !vals)
3061 goto fail_2;
3062 if (!PyList_Check(keys) || !PyList_Check(vals)) {
3063 PyErr_SetString(PyExc_TypeError,
3064 "execve(): env.keys() or env.values() is not a list");
3065 goto fail_2;
3068 for (pos = 0; pos < i; pos++) {
3069 char *p, *k, *v;
3070 size_t len;
3072 key = PyList_GetItem(keys, pos);
3073 val = PyList_GetItem(vals, pos);
3074 if (!key || !val)
3075 goto fail_2;
3077 if (!PyArg_Parse(
3078 key,
3079 "s;execve() arg 3 contains a non-string key",
3080 &k) ||
3081 !PyArg_Parse(
3082 val,
3083 "s;execve() arg 3 contains a non-string value",
3084 &v))
3086 goto fail_2;
3089 #if defined(PYOS_OS2)
3090 /* Omit Pseudo-Env Vars that Would Confuse Programs if Passed On */
3091 if (stricmp(k, "BEGINLIBPATH") != 0 && stricmp(k, "ENDLIBPATH") != 0) {
3092 #endif
3093 len = PyString_Size(key) + PyString_Size(val) + 2;
3094 p = PyMem_NEW(char, len);
3095 if (p == NULL) {
3096 PyErr_NoMemory();
3097 goto fail_2;
3099 PyOS_snprintf(p, len, "%s=%s", k, v);
3100 envlist[envc++] = p;
3101 #if defined(PYOS_OS2)
3103 #endif
3105 envlist[envc] = 0;
3107 execve(path, argvlist, envlist);
3109 /* If we get here it's definitely an error */
3111 (void) posix_error();
3113 fail_2:
3114 while (--envc >= 0)
3115 PyMem_DEL(envlist[envc]);
3116 PyMem_DEL(envlist);
3117 fail_1:
3118 free_string_array(argvlist, lastarg);
3119 Py_XDECREF(vals);
3120 Py_XDECREF(keys);
3121 fail_0:
3122 PyMem_Free(path);
3123 return NULL;
3125 #endif /* HAVE_EXECV */
3128 #ifdef HAVE_SPAWNV
3129 PyDoc_STRVAR(posix_spawnv__doc__,
3130 "spawnv(mode, path, args)\n\n\
3131 Execute the program 'path' in a new process.\n\
3133 mode: mode of process creation\n\
3134 path: path of executable file\n\
3135 args: tuple or list of strings");
3137 static PyObject *
3138 posix_spawnv(PyObject *self, PyObject *args)
3140 char *path;
3141 PyObject *argv;
3142 char **argvlist;
3143 int mode, i;
3144 Py_ssize_t argc;
3145 Py_intptr_t spawnval;
3146 PyObject *(*getitem)(PyObject *, Py_ssize_t);
3148 /* spawnv has three arguments: (mode, path, argv), where
3149 argv is a list or tuple of strings. */
3151 if (!PyArg_ParseTuple(args, "ietO:spawnv", &mode,
3152 Py_FileSystemDefaultEncoding,
3153 &path, &argv))
3154 return NULL;
3155 if (PyList_Check(argv)) {
3156 argc = PyList_Size(argv);
3157 getitem = PyList_GetItem;
3159 else if (PyTuple_Check(argv)) {
3160 argc = PyTuple_Size(argv);
3161 getitem = PyTuple_GetItem;
3163 else {
3164 PyErr_SetString(PyExc_TypeError,
3165 "spawnv() arg 2 must be a tuple or list");
3166 PyMem_Free(path);
3167 return NULL;
3170 argvlist = PyMem_NEW(char *, argc+1);
3171 if (argvlist == NULL) {
3172 PyMem_Free(path);
3173 return PyErr_NoMemory();
3175 for (i = 0; i < argc; i++) {
3176 if (!PyArg_Parse((*getitem)(argv, i), "et",
3177 Py_FileSystemDefaultEncoding,
3178 &argvlist[i])) {
3179 free_string_array(argvlist, i);
3180 PyErr_SetString(
3181 PyExc_TypeError,
3182 "spawnv() arg 2 must contain only strings");
3183 PyMem_Free(path);
3184 return NULL;
3187 argvlist[argc] = NULL;
3189 #if defined(PYOS_OS2) && defined(PYCC_GCC)
3190 Py_BEGIN_ALLOW_THREADS
3191 spawnval = spawnv(mode, path, argvlist);
3192 Py_END_ALLOW_THREADS
3193 #else
3194 if (mode == _OLD_P_OVERLAY)
3195 mode = _P_OVERLAY;
3197 Py_BEGIN_ALLOW_THREADS
3198 spawnval = _spawnv(mode, path, argvlist);
3199 Py_END_ALLOW_THREADS
3200 #endif
3202 free_string_array(argvlist, argc);
3203 PyMem_Free(path);
3205 if (spawnval == -1)
3206 return posix_error();
3207 else
3208 #if SIZEOF_LONG == SIZEOF_VOID_P
3209 return Py_BuildValue("l", (long) spawnval);
3210 #else
3211 return Py_BuildValue("L", (PY_LONG_LONG) spawnval);
3212 #endif
3216 PyDoc_STRVAR(posix_spawnve__doc__,
3217 "spawnve(mode, path, args, env)\n\n\
3218 Execute the program 'path' in a new process.\n\
3220 mode: mode of process creation\n\
3221 path: path of executable file\n\
3222 args: tuple or list of arguments\n\
3223 env: dictionary of strings mapping to strings");
3225 static PyObject *
3226 posix_spawnve(PyObject *self, PyObject *args)
3228 char *path;
3229 PyObject *argv, *env;
3230 char **argvlist;
3231 char **envlist;
3232 PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL;
3233 int mode, pos, envc;
3234 Py_ssize_t argc, i;
3235 Py_intptr_t spawnval;
3236 PyObject *(*getitem)(PyObject *, Py_ssize_t);
3237 Py_ssize_t lastarg = 0;
3239 /* spawnve has four arguments: (mode, path, argv, env), where
3240 argv is a list or tuple of strings and env is a dictionary
3241 like posix.environ. */
3243 if (!PyArg_ParseTuple(args, "ietOO:spawnve", &mode,
3244 Py_FileSystemDefaultEncoding,
3245 &path, &argv, &env))
3246 return NULL;
3247 if (PyList_Check(argv)) {
3248 argc = PyList_Size(argv);
3249 getitem = PyList_GetItem;
3251 else if (PyTuple_Check(argv)) {
3252 argc = PyTuple_Size(argv);
3253 getitem = PyTuple_GetItem;
3255 else {
3256 PyErr_SetString(PyExc_TypeError,
3257 "spawnve() arg 2 must be a tuple or list");
3258 goto fail_0;
3260 if (!PyMapping_Check(env)) {
3261 PyErr_SetString(PyExc_TypeError,
3262 "spawnve() arg 3 must be a mapping object");
3263 goto fail_0;
3266 argvlist = PyMem_NEW(char *, argc+1);
3267 if (argvlist == NULL) {
3268 PyErr_NoMemory();
3269 goto fail_0;
3271 for (i = 0; i < argc; i++) {
3272 if (!PyArg_Parse((*getitem)(argv, i),
3273 "et;spawnve() arg 2 must contain only strings",
3274 Py_FileSystemDefaultEncoding,
3275 &argvlist[i]))
3277 lastarg = i;
3278 goto fail_1;
3281 lastarg = argc;
3282 argvlist[argc] = NULL;
3284 i = PyMapping_Size(env);
3285 if (i < 0)
3286 goto fail_1;
3287 envlist = PyMem_NEW(char *, i + 1);
3288 if (envlist == NULL) {
3289 PyErr_NoMemory();
3290 goto fail_1;
3292 envc = 0;
3293 keys = PyMapping_Keys(env);
3294 vals = PyMapping_Values(env);
3295 if (!keys || !vals)
3296 goto fail_2;
3297 if (!PyList_Check(keys) || !PyList_Check(vals)) {
3298 PyErr_SetString(PyExc_TypeError,
3299 "spawnve(): env.keys() or env.values() is not a list");
3300 goto fail_2;
3303 for (pos = 0; pos < i; pos++) {
3304 char *p, *k, *v;
3305 size_t len;
3307 key = PyList_GetItem(keys, pos);
3308 val = PyList_GetItem(vals, pos);
3309 if (!key || !val)
3310 goto fail_2;
3312 if (!PyArg_Parse(
3313 key,
3314 "s;spawnve() arg 3 contains a non-string key",
3315 &k) ||
3316 !PyArg_Parse(
3317 val,
3318 "s;spawnve() arg 3 contains a non-string value",
3319 &v))
3321 goto fail_2;
3323 len = PyString_Size(key) + PyString_Size(val) + 2;
3324 p = PyMem_NEW(char, len);
3325 if (p == NULL) {
3326 PyErr_NoMemory();
3327 goto fail_2;
3329 PyOS_snprintf(p, len, "%s=%s", k, v);
3330 envlist[envc++] = p;
3332 envlist[envc] = 0;
3334 #if defined(PYOS_OS2) && defined(PYCC_GCC)
3335 Py_BEGIN_ALLOW_THREADS
3336 spawnval = spawnve(mode, path, argvlist, envlist);
3337 Py_END_ALLOW_THREADS
3338 #else
3339 if (mode == _OLD_P_OVERLAY)
3340 mode = _P_OVERLAY;
3342 Py_BEGIN_ALLOW_THREADS
3343 spawnval = _spawnve(mode, path, argvlist, envlist);
3344 Py_END_ALLOW_THREADS
3345 #endif
3347 if (spawnval == -1)
3348 (void) posix_error();
3349 else
3350 #if SIZEOF_LONG == SIZEOF_VOID_P
3351 res = Py_BuildValue("l", (long) spawnval);
3352 #else
3353 res = Py_BuildValue("L", (PY_LONG_LONG) spawnval);
3354 #endif
3356 fail_2:
3357 while (--envc >= 0)
3358 PyMem_DEL(envlist[envc]);
3359 PyMem_DEL(envlist);
3360 fail_1:
3361 free_string_array(argvlist, lastarg);
3362 Py_XDECREF(vals);
3363 Py_XDECREF(keys);
3364 fail_0:
3365 PyMem_Free(path);
3366 return res;
3369 /* OS/2 supports spawnvp & spawnvpe natively */
3370 #if defined(PYOS_OS2)
3371 PyDoc_STRVAR(posix_spawnvp__doc__,
3372 "spawnvp(mode, file, args)\n\n\
3373 Execute the program 'file' in a new process, using the environment\n\
3374 search path to find the file.\n\
3376 mode: mode of process creation\n\
3377 file: executable file name\n\
3378 args: tuple or list of strings");
3380 static PyObject *
3381 posix_spawnvp(PyObject *self, PyObject *args)
3383 char *path;
3384 PyObject *argv;
3385 char **argvlist;
3386 int mode, i, argc;
3387 Py_intptr_t spawnval;
3388 PyObject *(*getitem)(PyObject *, Py_ssize_t);
3390 /* spawnvp has three arguments: (mode, path, argv), where
3391 argv is a list or tuple of strings. */
3393 if (!PyArg_ParseTuple(args, "ietO:spawnvp", &mode,
3394 Py_FileSystemDefaultEncoding,
3395 &path, &argv))
3396 return NULL;
3397 if (PyList_Check(argv)) {
3398 argc = PyList_Size(argv);
3399 getitem = PyList_GetItem;
3401 else if (PyTuple_Check(argv)) {
3402 argc = PyTuple_Size(argv);
3403 getitem = PyTuple_GetItem;
3405 else {
3406 PyErr_SetString(PyExc_TypeError,
3407 "spawnvp() arg 2 must be a tuple or list");
3408 PyMem_Free(path);
3409 return NULL;
3412 argvlist = PyMem_NEW(char *, argc+1);
3413 if (argvlist == NULL) {
3414 PyMem_Free(path);
3415 return PyErr_NoMemory();
3417 for (i = 0; i < argc; i++) {
3418 if (!PyArg_Parse((*getitem)(argv, i), "et",
3419 Py_FileSystemDefaultEncoding,
3420 &argvlist[i])) {
3421 free_string_array(argvlist, i);
3422 PyErr_SetString(
3423 PyExc_TypeError,
3424 "spawnvp() arg 2 must contain only strings");
3425 PyMem_Free(path);
3426 return NULL;
3429 argvlist[argc] = NULL;
3431 Py_BEGIN_ALLOW_THREADS
3432 #if defined(PYCC_GCC)
3433 spawnval = spawnvp(mode, path, argvlist);
3434 #else
3435 spawnval = _spawnvp(mode, path, argvlist);
3436 #endif
3437 Py_END_ALLOW_THREADS
3439 free_string_array(argvlist, argc);
3440 PyMem_Free(path);
3442 if (spawnval == -1)
3443 return posix_error();
3444 else
3445 return Py_BuildValue("l", (long) spawnval);
3449 PyDoc_STRVAR(posix_spawnvpe__doc__,
3450 "spawnvpe(mode, file, args, env)\n\n\
3451 Execute the program 'file' in a new process, using the environment\n\
3452 search path to find the file.\n\
3454 mode: mode of process creation\n\
3455 file: executable file name\n\
3456 args: tuple or list of arguments\n\
3457 env: dictionary of strings mapping to strings");
3459 static PyObject *
3460 posix_spawnvpe(PyObject *self, PyObject *args)
3462 char *path;
3463 PyObject *argv, *env;
3464 char **argvlist;
3465 char **envlist;
3466 PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL;
3467 int mode, i, pos, argc, envc;
3468 Py_intptr_t spawnval;
3469 PyObject *(*getitem)(PyObject *, Py_ssize_t);
3470 int lastarg = 0;
3472 /* spawnvpe has four arguments: (mode, path, argv, env), where
3473 argv is a list or tuple of strings and env is a dictionary
3474 like posix.environ. */
3476 if (!PyArg_ParseTuple(args, "ietOO:spawnvpe", &mode,
3477 Py_FileSystemDefaultEncoding,
3478 &path, &argv, &env))
3479 return NULL;
3480 if (PyList_Check(argv)) {
3481 argc = PyList_Size(argv);
3482 getitem = PyList_GetItem;
3484 else if (PyTuple_Check(argv)) {
3485 argc = PyTuple_Size(argv);
3486 getitem = PyTuple_GetItem;
3488 else {
3489 PyErr_SetString(PyExc_TypeError,
3490 "spawnvpe() arg 2 must be a tuple or list");
3491 goto fail_0;
3493 if (!PyMapping_Check(env)) {
3494 PyErr_SetString(PyExc_TypeError,
3495 "spawnvpe() arg 3 must be a mapping object");
3496 goto fail_0;
3499 argvlist = PyMem_NEW(char *, argc+1);
3500 if (argvlist == NULL) {
3501 PyErr_NoMemory();
3502 goto fail_0;
3504 for (i = 0; i < argc; i++) {
3505 if (!PyArg_Parse((*getitem)(argv, i),
3506 "et;spawnvpe() arg 2 must contain only strings",
3507 Py_FileSystemDefaultEncoding,
3508 &argvlist[i]))
3510 lastarg = i;
3511 goto fail_1;
3514 lastarg = argc;
3515 argvlist[argc] = NULL;
3517 i = PyMapping_Size(env);
3518 if (i < 0)
3519 goto fail_1;
3520 envlist = PyMem_NEW(char *, i + 1);
3521 if (envlist == NULL) {
3522 PyErr_NoMemory();
3523 goto fail_1;
3525 envc = 0;
3526 keys = PyMapping_Keys(env);
3527 vals = PyMapping_Values(env);
3528 if (!keys || !vals)
3529 goto fail_2;
3530 if (!PyList_Check(keys) || !PyList_Check(vals)) {
3531 PyErr_SetString(PyExc_TypeError,
3532 "spawnvpe(): env.keys() or env.values() is not a list");
3533 goto fail_2;
3536 for (pos = 0; pos < i; pos++) {
3537 char *p, *k, *v;
3538 size_t len;
3540 key = PyList_GetItem(keys, pos);
3541 val = PyList_GetItem(vals, pos);
3542 if (!key || !val)
3543 goto fail_2;
3545 if (!PyArg_Parse(
3546 key,
3547 "s;spawnvpe() arg 3 contains a non-string key",
3548 &k) ||
3549 !PyArg_Parse(
3550 val,
3551 "s;spawnvpe() arg 3 contains a non-string value",
3552 &v))
3554 goto fail_2;
3556 len = PyString_Size(key) + PyString_Size(val) + 2;
3557 p = PyMem_NEW(char, len);
3558 if (p == NULL) {
3559 PyErr_NoMemory();
3560 goto fail_2;
3562 PyOS_snprintf(p, len, "%s=%s", k, v);
3563 envlist[envc++] = p;
3565 envlist[envc] = 0;
3567 Py_BEGIN_ALLOW_THREADS
3568 #if defined(PYCC_GCC)
3569 spawnval = spawnvpe(mode, path, argvlist, envlist);
3570 #else
3571 spawnval = _spawnvpe(mode, path, argvlist, envlist);
3572 #endif
3573 Py_END_ALLOW_THREADS
3575 if (spawnval == -1)
3576 (void) posix_error();
3577 else
3578 res = Py_BuildValue("l", (long) spawnval);
3580 fail_2:
3581 while (--envc >= 0)
3582 PyMem_DEL(envlist[envc]);
3583 PyMem_DEL(envlist);
3584 fail_1:
3585 free_string_array(argvlist, lastarg);
3586 Py_XDECREF(vals);
3587 Py_XDECREF(keys);
3588 fail_0:
3589 PyMem_Free(path);
3590 return res;
3592 #endif /* PYOS_OS2 */
3593 #endif /* HAVE_SPAWNV */
3596 #ifdef HAVE_FORK1
3597 PyDoc_STRVAR(posix_fork1__doc__,
3598 "fork1() -> pid\n\n\
3599 Fork a child process with a single multiplexed (i.e., not bound) thread.\n\
3601 Return 0 to child process and PID of child to parent process.");
3603 static PyObject *
3604 posix_fork1(PyObject *self, PyObject *noargs)
3606 pid_t pid;
3607 int result;
3608 _PyImport_AcquireLock();
3609 pid = fork1();
3610 result = _PyImport_ReleaseLock();
3611 if (pid == -1)
3612 return posix_error();
3613 if (pid == 0)
3614 PyOS_AfterFork();
3615 if (result < 0) {
3616 /* Don't clobber the OSError if the fork failed. */
3617 PyErr_SetString(PyExc_RuntimeError,
3618 "not holding the import lock");
3619 return NULL;
3621 return PyLong_FromPid(pid);
3623 #endif
3626 #ifdef HAVE_FORK
3627 PyDoc_STRVAR(posix_fork__doc__,
3628 "fork() -> pid\n\n\
3629 Fork a child process.\n\
3630 Return 0 to child process and PID of child to parent process.");
3632 static PyObject *
3633 posix_fork(PyObject *self, PyObject *noargs)
3635 pid_t pid;
3636 int result;
3637 _PyImport_AcquireLock();
3638 pid = fork();
3639 result = _PyImport_ReleaseLock();
3640 if (pid == -1)
3641 return posix_error();
3642 if (pid == 0)
3643 PyOS_AfterFork();
3644 if (result < 0) {
3645 /* Don't clobber the OSError if the fork failed. */
3646 PyErr_SetString(PyExc_RuntimeError,
3647 "not holding the import lock");
3648 return NULL;
3650 return PyLong_FromPid(pid);
3652 #endif
3654 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
3655 /* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
3656 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
3657 #define DEV_PTY_FILE "/dev/ptc"
3658 #define HAVE_DEV_PTMX
3659 #else
3660 #define DEV_PTY_FILE "/dev/ptmx"
3661 #endif
3663 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
3664 #ifdef HAVE_PTY_H
3665 #include <pty.h>
3666 #else
3667 #ifdef HAVE_LIBUTIL_H
3668 #include <libutil.h>
3669 #endif /* HAVE_LIBUTIL_H */
3670 #endif /* HAVE_PTY_H */
3671 #ifdef HAVE_STROPTS_H
3672 #include <stropts.h>
3673 #endif
3674 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */
3676 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
3677 PyDoc_STRVAR(posix_openpty__doc__,
3678 "openpty() -> (master_fd, slave_fd)\n\n\
3679 Open a pseudo-terminal, returning open fd's for both master and slave end.\n");
3681 static PyObject *
3682 posix_openpty(PyObject *self, PyObject *noargs)
3684 int master_fd, slave_fd;
3685 #ifndef HAVE_OPENPTY
3686 char * slave_name;
3687 #endif
3688 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
3689 PyOS_sighandler_t sig_saved;
3690 #ifdef sun
3691 extern char *ptsname(int fildes);
3692 #endif
3693 #endif
3695 #ifdef HAVE_OPENPTY
3696 if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
3697 return posix_error();
3698 #elif defined(HAVE__GETPTY)
3699 slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
3700 if (slave_name == NULL)
3701 return posix_error();
3703 slave_fd = open(slave_name, O_RDWR);
3704 if (slave_fd < 0)
3705 return posix_error();
3706 #else
3707 master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
3708 if (master_fd < 0)
3709 return posix_error();
3710 sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
3711 /* change permission of slave */
3712 if (grantpt(master_fd) < 0) {
3713 PyOS_setsig(SIGCHLD, sig_saved);
3714 return posix_error();
3716 /* unlock slave */
3717 if (unlockpt(master_fd) < 0) {
3718 PyOS_setsig(SIGCHLD, sig_saved);
3719 return posix_error();
3721 PyOS_setsig(SIGCHLD, sig_saved);
3722 slave_name = ptsname(master_fd); /* get name of slave */
3723 if (slave_name == NULL)
3724 return posix_error();
3725 slave_fd = open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
3726 if (slave_fd < 0)
3727 return posix_error();
3728 #if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC)
3729 ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
3730 ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
3731 #ifndef __hpux
3732 ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
3733 #endif /* __hpux */
3734 #endif /* HAVE_CYGWIN */
3735 #endif /* HAVE_OPENPTY */
3737 return Py_BuildValue("(ii)", master_fd, slave_fd);
3740 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
3742 #ifdef HAVE_FORKPTY
3743 PyDoc_STRVAR(posix_forkpty__doc__,
3744 "forkpty() -> (pid, master_fd)\n\n\
3745 Fork a new process with a new pseudo-terminal as controlling tty.\n\n\
3746 Like fork(), return 0 as pid to child process, and PID of child to parent.\n\
3747 To both, return fd of newly opened pseudo-terminal.\n");
3749 static PyObject *
3750 posix_forkpty(PyObject *self, PyObject *noargs)
3752 int master_fd = -1, result;
3753 pid_t pid;
3755 _PyImport_AcquireLock();
3756 pid = forkpty(&master_fd, NULL, NULL, NULL);
3757 result = _PyImport_ReleaseLock();
3758 if (pid == -1)
3759 return posix_error();
3760 if (pid == 0)
3761 PyOS_AfterFork();
3762 if (result < 0) {
3763 /* Don't clobber the OSError if the fork failed. */
3764 PyErr_SetString(PyExc_RuntimeError,
3765 "not holding the import lock");
3766 return NULL;
3768 return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
3770 #endif
3772 #ifdef HAVE_GETEGID
3773 PyDoc_STRVAR(posix_getegid__doc__,
3774 "getegid() -> egid\n\n\
3775 Return the current process's effective group id.");
3777 static PyObject *
3778 posix_getegid(PyObject *self, PyObject *noargs)
3780 return PyInt_FromLong((long)getegid());
3782 #endif
3785 #ifdef HAVE_GETEUID
3786 PyDoc_STRVAR(posix_geteuid__doc__,
3787 "geteuid() -> euid\n\n\
3788 Return the current process's effective user id.");
3790 static PyObject *
3791 posix_geteuid(PyObject *self, PyObject *noargs)
3793 return PyInt_FromLong((long)geteuid());
3795 #endif
3798 #ifdef HAVE_GETGID
3799 PyDoc_STRVAR(posix_getgid__doc__,
3800 "getgid() -> gid\n\n\
3801 Return the current process's group id.");
3803 static PyObject *
3804 posix_getgid(PyObject *self, PyObject *noargs)
3806 return PyInt_FromLong((long)getgid());
3808 #endif
3811 PyDoc_STRVAR(posix_getpid__doc__,
3812 "getpid() -> pid\n\n\
3813 Return the current process id");
3815 static PyObject *
3816 posix_getpid(PyObject *self, PyObject *noargs)
3818 return PyLong_FromPid(getpid());
3822 #ifdef HAVE_GETGROUPS
3823 PyDoc_STRVAR(posix_getgroups__doc__,
3824 "getgroups() -> list of group IDs\n\n\
3825 Return list of supplemental group IDs for the process.");
3827 static PyObject *
3828 posix_getgroups(PyObject *self, PyObject *noargs)
3830 PyObject *result = NULL;
3832 #ifdef NGROUPS_MAX
3833 #define MAX_GROUPS NGROUPS_MAX
3834 #else
3835 /* defined to be 16 on Solaris7, so this should be a small number */
3836 #define MAX_GROUPS 64
3837 #endif
3838 gid_t grouplist[MAX_GROUPS];
3839 int n;
3841 n = getgroups(MAX_GROUPS, grouplist);
3842 if (n < 0)
3843 posix_error();
3844 else {
3845 result = PyList_New(n);
3846 if (result != NULL) {
3847 int i;
3848 for (i = 0; i < n; ++i) {
3849 PyObject *o = PyInt_FromLong((long)grouplist[i]);
3850 if (o == NULL) {
3851 Py_DECREF(result);
3852 result = NULL;
3853 break;
3855 PyList_SET_ITEM(result, i, o);
3860 return result;
3862 #endif
3864 #ifdef HAVE_INITGROUPS
3865 PyDoc_STRVAR(posix_initgroups__doc__,
3866 "initgroups(username, gid) -> None\n\n\
3867 Call the system initgroups() to initialize the group access list with all of\n\
3868 the groups of which the specified username is a member, plus the specified\n\
3869 group id.");
3871 static PyObject *
3872 posix_initgroups(PyObject *self, PyObject *args)
3874 char *username;
3875 long gid;
3877 if (!PyArg_ParseTuple(args, "sl:initgroups", &username, &gid))
3878 return NULL;
3880 if (initgroups(username, (gid_t) gid) == -1)
3881 return PyErr_SetFromErrno(PyExc_OSError);
3883 Py_INCREF(Py_None);
3884 return Py_None;
3886 #endif
3888 #ifdef HAVE_GETPGID
3889 PyDoc_STRVAR(posix_getpgid__doc__,
3890 "getpgid(pid) -> pgid\n\n\
3891 Call the system call getpgid().");
3893 static PyObject *
3894 posix_getpgid(PyObject *self, PyObject *args)
3896 pid_t pid, pgid;
3897 if (!PyArg_ParseTuple(args, PARSE_PID ":getpgid", &pid))
3898 return NULL;
3899 pgid = getpgid(pid);
3900 if (pgid < 0)
3901 return posix_error();
3902 return PyLong_FromPid(pgid);
3904 #endif /* HAVE_GETPGID */
3907 #ifdef HAVE_GETPGRP
3908 PyDoc_STRVAR(posix_getpgrp__doc__,
3909 "getpgrp() -> pgrp\n\n\
3910 Return the current process group id.");
3912 static PyObject *
3913 posix_getpgrp(PyObject *self, PyObject *noargs)
3915 #ifdef GETPGRP_HAVE_ARG
3916 return PyLong_FromPid(getpgrp(0));
3917 #else /* GETPGRP_HAVE_ARG */
3918 return PyLong_FromPid(getpgrp());
3919 #endif /* GETPGRP_HAVE_ARG */
3921 #endif /* HAVE_GETPGRP */
3924 #ifdef HAVE_SETPGRP
3925 PyDoc_STRVAR(posix_setpgrp__doc__,
3926 "setpgrp()\n\n\
3927 Make this process a session leader.");
3929 static PyObject *
3930 posix_setpgrp(PyObject *self, PyObject *noargs)
3932 #ifdef SETPGRP_HAVE_ARG
3933 if (setpgrp(0, 0) < 0)
3934 #else /* SETPGRP_HAVE_ARG */
3935 if (setpgrp() < 0)
3936 #endif /* SETPGRP_HAVE_ARG */
3937 return posix_error();
3938 Py_INCREF(Py_None);
3939 return Py_None;
3942 #endif /* HAVE_SETPGRP */
3944 #ifdef HAVE_GETPPID
3945 PyDoc_STRVAR(posix_getppid__doc__,
3946 "getppid() -> ppid\n\n\
3947 Return the parent's process id.");
3949 static PyObject *
3950 posix_getppid(PyObject *self, PyObject *noargs)
3952 return PyLong_FromPid(getppid());
3954 #endif
3957 #ifdef HAVE_GETLOGIN
3958 PyDoc_STRVAR(posix_getlogin__doc__,
3959 "getlogin() -> string\n\n\
3960 Return the actual login name.");
3962 static PyObject *
3963 posix_getlogin(PyObject *self, PyObject *noargs)
3965 PyObject *result = NULL;
3966 char *name;
3967 int old_errno = errno;
3969 errno = 0;
3970 name = getlogin();
3971 if (name == NULL) {
3972 if (errno)
3973 posix_error();
3974 else
3975 PyErr_SetString(PyExc_OSError,
3976 "unable to determine login name");
3978 else
3979 result = PyString_FromString(name);
3980 errno = old_errno;
3982 return result;
3984 #endif
3986 #ifdef HAVE_GETUID
3987 PyDoc_STRVAR(posix_getuid__doc__,
3988 "getuid() -> uid\n\n\
3989 Return the current process's user id.");
3991 static PyObject *
3992 posix_getuid(PyObject *self, PyObject *noargs)
3994 return PyInt_FromLong((long)getuid());
3996 #endif
3999 #ifdef HAVE_KILL
4000 PyDoc_STRVAR(posix_kill__doc__,
4001 "kill(pid, sig)\n\n\
4002 Kill a process with a signal.");
4004 static PyObject *
4005 posix_kill(PyObject *self, PyObject *args)
4007 pid_t pid;
4008 int sig;
4009 if (!PyArg_ParseTuple(args, PARSE_PID "i:kill", &pid, &sig))
4010 return NULL;
4011 #if defined(PYOS_OS2) && !defined(PYCC_GCC)
4012 if (sig == XCPT_SIGNAL_INTR || sig == XCPT_SIGNAL_BREAK) {
4013 APIRET rc;
4014 if ((rc = DosSendSignalException(pid, sig)) != NO_ERROR)
4015 return os2_error(rc);
4017 } else if (sig == XCPT_SIGNAL_KILLPROC) {
4018 APIRET rc;
4019 if ((rc = DosKillProcess(DKP_PROCESS, pid)) != NO_ERROR)
4020 return os2_error(rc);
4022 } else
4023 return NULL; /* Unrecognized Signal Requested */
4024 #else
4025 if (kill(pid, sig) == -1)
4026 return posix_error();
4027 #endif
4028 Py_INCREF(Py_None);
4029 return Py_None;
4031 #endif
4033 #ifdef HAVE_KILLPG
4034 PyDoc_STRVAR(posix_killpg__doc__,
4035 "killpg(pgid, sig)\n\n\
4036 Kill a process group with a signal.");
4038 static PyObject *
4039 posix_killpg(PyObject *self, PyObject *args)
4041 int sig;
4042 pid_t pgid;
4043 /* XXX some man pages make the `pgid` parameter an int, others
4044 a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
4045 take the same type. Moreover, pid_t is always at least as wide as
4046 int (else compilation of this module fails), which is safe. */
4047 if (!PyArg_ParseTuple(args, PARSE_PID "i:killpg", &pgid, &sig))
4048 return NULL;
4049 if (killpg(pgid, sig) == -1)
4050 return posix_error();
4051 Py_INCREF(Py_None);
4052 return Py_None;
4054 #endif
4056 #ifdef HAVE_PLOCK
4058 #ifdef HAVE_SYS_LOCK_H
4059 #include <sys/lock.h>
4060 #endif
4062 PyDoc_STRVAR(posix_plock__doc__,
4063 "plock(op)\n\n\
4064 Lock program segments into memory.");
4066 static PyObject *
4067 posix_plock(PyObject *self, PyObject *args)
4069 int op;
4070 if (!PyArg_ParseTuple(args, "i:plock", &op))
4071 return NULL;
4072 if (plock(op) == -1)
4073 return posix_error();
4074 Py_INCREF(Py_None);
4075 return Py_None;
4077 #endif
4080 #ifdef HAVE_POPEN
4081 PyDoc_STRVAR(posix_popen__doc__,
4082 "popen(command [, mode='r' [, bufsize]]) -> pipe\n\n\
4083 Open a pipe to/from a command returning a file object.");
4085 #if defined(PYOS_OS2)
4086 #if defined(PYCC_VACPP)
4087 static int
4088 async_system(const char *command)
4090 char errormsg[256], args[1024];
4091 RESULTCODES rcodes;
4092 APIRET rc;
4094 char *shell = getenv("COMSPEC");
4095 if (!shell)
4096 shell = "cmd";
4098 /* avoid overflowing the argument buffer */
4099 if (strlen(shell) + 3 + strlen(command) >= 1024)
4100 return ERROR_NOT_ENOUGH_MEMORY
4102 args[0] = '\0';
4103 strcat(args, shell);
4104 strcat(args, "/c ");
4105 strcat(args, command);
4107 /* execute asynchronously, inheriting the environment */
4108 rc = DosExecPgm(errormsg,
4109 sizeof(errormsg),
4110 EXEC_ASYNC,
4111 args,
4112 NULL,
4113 &rcodes,
4114 shell);
4115 return rc;
4118 static FILE *
4119 popen(const char *command, const char *mode, int pipesize, int *err)
4121 int oldfd, tgtfd;
4122 HFILE pipeh[2];
4123 APIRET rc;
4125 /* mode determines which of stdin or stdout is reconnected to
4126 * the pipe to the child
4128 if (strchr(mode, 'r') != NULL) {
4129 tgt_fd = 1; /* stdout */
4130 } else if (strchr(mode, 'w')) {
4131 tgt_fd = 0; /* stdin */
4132 } else {
4133 *err = ERROR_INVALID_ACCESS;
4134 return NULL;
4137 /* setup the pipe */
4138 if ((rc = DosCreatePipe(&pipeh[0], &pipeh[1], pipesize)) != NO_ERROR) {
4139 *err = rc;
4140 return NULL;
4143 /* prevent other threads accessing stdio */
4144 DosEnterCritSec();
4146 /* reconnect stdio and execute child */
4147 oldfd = dup(tgtfd);
4148 close(tgtfd);
4149 if (dup2(pipeh[tgtfd], tgtfd) == 0) {
4150 DosClose(pipeh[tgtfd]);
4151 rc = async_system(command);
4154 /* restore stdio */
4155 dup2(oldfd, tgtfd);
4156 close(oldfd);
4158 /* allow other threads access to stdio */
4159 DosExitCritSec();
4161 /* if execution of child was successful return file stream */
4162 if (rc == NO_ERROR)
4163 return fdopen(pipeh[1 - tgtfd], mode);
4164 else {
4165 DosClose(pipeh[1 - tgtfd]);
4166 *err = rc;
4167 return NULL;
4171 static PyObject *
4172 posix_popen(PyObject *self, PyObject *args)
4174 char *name;
4175 char *mode = "r";
4176 int err, bufsize = -1;
4177 FILE *fp;
4178 PyObject *f;
4179 if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize))
4180 return NULL;
4181 Py_BEGIN_ALLOW_THREADS
4182 fp = popen(name, mode, (bufsize > 0) ? bufsize : 4096, &err);
4183 Py_END_ALLOW_THREADS
4184 if (fp == NULL)
4185 return os2_error(err);
4187 f = PyFile_FromFile(fp, name, mode, fclose);
4188 if (f != NULL)
4189 PyFile_SetBufSize(f, bufsize);
4190 return f;
4193 #elif defined(PYCC_GCC)
4195 /* standard posix version of popen() support */
4196 static PyObject *
4197 posix_popen(PyObject *self, PyObject *args)
4199 char *name;
4200 char *mode = "r";
4201 int bufsize = -1;
4202 FILE *fp;
4203 PyObject *f;
4204 if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize))
4205 return NULL;
4206 Py_BEGIN_ALLOW_THREADS
4207 fp = popen(name, mode);
4208 Py_END_ALLOW_THREADS
4209 if (fp == NULL)
4210 return posix_error();
4211 f = PyFile_FromFile(fp, name, mode, pclose);
4212 if (f != NULL)
4213 PyFile_SetBufSize(f, bufsize);
4214 return f;
4217 /* fork() under OS/2 has lots'o'warts
4218 * EMX supports pipe() and spawn*() so we can synthesize popen[234]()
4219 * most of this code is a ripoff of the win32 code, but using the
4220 * capabilities of EMX's C library routines
4223 /* These tell _PyPopen() whether to return 1, 2, or 3 file objects. */
4224 #define POPEN_1 1
4225 #define POPEN_2 2
4226 #define POPEN_3 3
4227 #define POPEN_4 4
4229 static PyObject *_PyPopen(char *, int, int, int);
4230 static int _PyPclose(FILE *file);
4233 * Internal dictionary mapping popen* file pointers to process handles,
4234 * for use when retrieving the process exit code. See _PyPclose() below
4235 * for more information on this dictionary's use.
4237 static PyObject *_PyPopenProcs = NULL;
4239 /* os2emx version of popen2()
4241 * The result of this function is a pipe (file) connected to the
4242 * process's stdin, and a pipe connected to the process's stdout.
4245 static PyObject *
4246 os2emx_popen2(PyObject *self, PyObject *args)
4248 PyObject *f;
4249 int tm=0;
4251 char *cmdstring;
4252 char *mode = "t";
4253 int bufsize = -1;
4254 if (!PyArg_ParseTuple(args, "s|si:popen2", &cmdstring, &mode, &bufsize))
4255 return NULL;
4257 if (*mode == 't')
4258 tm = O_TEXT;
4259 else if (*mode != 'b') {
4260 PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'");
4261 return NULL;
4262 } else
4263 tm = O_BINARY;
4265 f = _PyPopen(cmdstring, tm, POPEN_2, bufsize);
4267 return f;
4271 * Variation on os2emx.popen2
4273 * The result of this function is 3 pipes - the process's stdin,
4274 * stdout and stderr
4277 static PyObject *
4278 os2emx_popen3(PyObject *self, PyObject *args)
4280 PyObject *f;
4281 int tm = 0;
4283 char *cmdstring;
4284 char *mode = "t";
4285 int bufsize = -1;
4286 if (!PyArg_ParseTuple(args, "s|si:popen3", &cmdstring, &mode, &bufsize))
4287 return NULL;
4289 if (*mode == 't')
4290 tm = O_TEXT;
4291 else if (*mode != 'b') {
4292 PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'");
4293 return NULL;
4294 } else
4295 tm = O_BINARY;
4297 f = _PyPopen(cmdstring, tm, POPEN_3, bufsize);
4299 return f;
4303 * Variation on os2emx.popen2
4305 * The result of this function is 2 pipes - the processes stdin,
4306 * and stdout+stderr combined as a single pipe.
4309 static PyObject *
4310 os2emx_popen4(PyObject *self, PyObject *args)
4312 PyObject *f;
4313 int tm = 0;
4315 char *cmdstring;
4316 char *mode = "t";
4317 int bufsize = -1;
4318 if (!PyArg_ParseTuple(args, "s|si:popen4", &cmdstring, &mode, &bufsize))
4319 return NULL;
4321 if (*mode == 't')
4322 tm = O_TEXT;
4323 else if (*mode != 'b') {
4324 PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'");
4325 return NULL;
4326 } else
4327 tm = O_BINARY;
4329 f = _PyPopen(cmdstring, tm, POPEN_4, bufsize);
4331 return f;
4334 /* a couple of structures for convenient handling of multiple
4335 * file handles and pipes
4337 struct file_ref
4339 int handle;
4340 int flags;
4343 struct pipe_ref
4345 int rd;
4346 int wr;
4349 /* The following code is derived from the win32 code */
4351 static PyObject *
4352 _PyPopen(char *cmdstring, int mode, int n, int bufsize)
4354 struct file_ref stdio[3];
4355 struct pipe_ref p_fd[3];
4356 FILE *p_s[3];
4357 int file_count, i, pipe_err;
4358 pid_t pipe_pid;
4359 char *shell, *sh_name, *opt, *rd_mode, *wr_mode;
4360 PyObject *f, *p_f[3];
4362 /* file modes for subsequent fdopen's on pipe handles */
4363 if (mode == O_TEXT)
4365 rd_mode = "rt";
4366 wr_mode = "wt";
4368 else
4370 rd_mode = "rb";
4371 wr_mode = "wb";
4374 /* prepare shell references */
4375 if ((shell = getenv("EMXSHELL")) == NULL)
4376 if ((shell = getenv("COMSPEC")) == NULL)
4378 errno = ENOENT;
4379 return posix_error();
4382 sh_name = _getname(shell);
4383 if (stricmp(sh_name, "cmd.exe") == 0 || stricmp(sh_name, "4os2.exe") == 0)
4384 opt = "/c";
4385 else
4386 opt = "-c";
4388 /* save current stdio fds + their flags, and set not inheritable */
4389 i = pipe_err = 0;
4390 while (pipe_err >= 0 && i < 3)
4392 pipe_err = stdio[i].handle = dup(i);
4393 stdio[i].flags = fcntl(i, F_GETFD, 0);
4394 fcntl(stdio[i].handle, F_SETFD, stdio[i].flags | FD_CLOEXEC);
4395 i++;
4397 if (pipe_err < 0)
4399 /* didn't get them all saved - clean up and bail out */
4400 int saved_err = errno;
4401 while (i-- > 0)
4403 close(stdio[i].handle);
4405 errno = saved_err;
4406 return posix_error();
4409 /* create pipe ends */
4410 file_count = 2;
4411 if (n == POPEN_3)
4412 file_count = 3;
4413 i = pipe_err = 0;
4414 while ((pipe_err == 0) && (i < file_count))
4415 pipe_err = pipe((int *)&p_fd[i++]);
4416 if (pipe_err < 0)
4418 /* didn't get them all made - clean up and bail out */
4419 while (i-- > 0)
4421 close(p_fd[i].wr);
4422 close(p_fd[i].rd);
4424 errno = EPIPE;
4425 return posix_error();
4428 /* change the actual standard IO streams over temporarily,
4429 * making the retained pipe ends non-inheritable
4431 pipe_err = 0;
4433 /* - stdin */
4434 if (dup2(p_fd[0].rd, 0) == 0)
4436 close(p_fd[0].rd);
4437 i = fcntl(p_fd[0].wr, F_GETFD, 0);
4438 fcntl(p_fd[0].wr, F_SETFD, i | FD_CLOEXEC);
4439 if ((p_s[0] = fdopen(p_fd[0].wr, wr_mode)) == NULL)
4441 close(p_fd[0].wr);
4442 pipe_err = -1;
4445 else
4447 pipe_err = -1;
4450 /* - stdout */
4451 if (pipe_err == 0)
4453 if (dup2(p_fd[1].wr, 1) == 1)
4455 close(p_fd[1].wr);
4456 i = fcntl(p_fd[1].rd, F_GETFD, 0);
4457 fcntl(p_fd[1].rd, F_SETFD, i | FD_CLOEXEC);
4458 if ((p_s[1] = fdopen(p_fd[1].rd, rd_mode)) == NULL)
4460 close(p_fd[1].rd);
4461 pipe_err = -1;
4464 else
4466 pipe_err = -1;
4470 /* - stderr, as required */
4471 if (pipe_err == 0)
4472 switch (n)
4474 case POPEN_3:
4476 if (dup2(p_fd[2].wr, 2) == 2)
4478 close(p_fd[2].wr);
4479 i = fcntl(p_fd[2].rd, F_GETFD, 0);
4480 fcntl(p_fd[2].rd, F_SETFD, i | FD_CLOEXEC);
4481 if ((p_s[2] = fdopen(p_fd[2].rd, rd_mode)) == NULL)
4483 close(p_fd[2].rd);
4484 pipe_err = -1;
4487 else
4489 pipe_err = -1;
4491 break;
4494 case POPEN_4:
4496 if (dup2(1, 2) != 2)
4498 pipe_err = -1;
4500 break;
4504 /* spawn the child process */
4505 if (pipe_err == 0)
4507 pipe_pid = spawnlp(P_NOWAIT, shell, shell, opt, cmdstring, (char *)0);
4508 if (pipe_pid == -1)
4510 pipe_err = -1;
4512 else
4514 /* save the PID into the FILE structure
4515 * NOTE: this implementation doesn't actually
4516 * take advantage of this, but do it for
4517 * completeness - AIM Apr01
4519 for (i = 0; i < file_count; i++)
4520 p_s[i]->_pid = pipe_pid;
4524 /* reset standard IO to normal */
4525 for (i = 0; i < 3; i++)
4527 dup2(stdio[i].handle, i);
4528 fcntl(i, F_SETFD, stdio[i].flags);
4529 close(stdio[i].handle);
4532 /* if any remnant problems, clean up and bail out */
4533 if (pipe_err < 0)
4535 for (i = 0; i < 3; i++)
4537 close(p_fd[i].rd);
4538 close(p_fd[i].wr);
4540 errno = EPIPE;
4541 return posix_error_with_filename(cmdstring);
4544 /* build tuple of file objects to return */
4545 if ((p_f[0] = PyFile_FromFile(p_s[0], cmdstring, wr_mode, _PyPclose)) != NULL)
4546 PyFile_SetBufSize(p_f[0], bufsize);
4547 if ((p_f[1] = PyFile_FromFile(p_s[1], cmdstring, rd_mode, _PyPclose)) != NULL)
4548 PyFile_SetBufSize(p_f[1], bufsize);
4549 if (n == POPEN_3)
4551 if ((p_f[2] = PyFile_FromFile(p_s[2], cmdstring, rd_mode, _PyPclose)) != NULL)
4552 PyFile_SetBufSize(p_f[0], bufsize);
4553 f = PyTuple_Pack(3, p_f[0], p_f[1], p_f[2]);
4555 else
4556 f = PyTuple_Pack(2, p_f[0], p_f[1]);
4559 * Insert the files we've created into the process dictionary
4560 * all referencing the list with the process handle and the
4561 * initial number of files (see description below in _PyPclose).
4562 * Since if _PyPclose later tried to wait on a process when all
4563 * handles weren't closed, it could create a deadlock with the
4564 * child, we spend some energy here to try to ensure that we
4565 * either insert all file handles into the dictionary or none
4566 * at all. It's a little clumsy with the various popen modes
4567 * and variable number of files involved.
4569 if (!_PyPopenProcs)
4571 _PyPopenProcs = PyDict_New();
4574 if (_PyPopenProcs)
4576 PyObject *procObj, *pidObj, *intObj, *fileObj[3];
4577 int ins_rc[3];
4579 fileObj[0] = fileObj[1] = fileObj[2] = NULL;
4580 ins_rc[0] = ins_rc[1] = ins_rc[2] = 0;
4582 procObj = PyList_New(2);
4583 pidObj = PyLong_FromPid(pipe_pid);
4584 intObj = PyInt_FromLong((long) file_count);
4586 if (procObj && pidObj && intObj)
4588 PyList_SetItem(procObj, 0, pidObj);
4589 PyList_SetItem(procObj, 1, intObj);
4591 fileObj[0] = PyLong_FromVoidPtr(p_s[0]);
4592 if (fileObj[0])
4594 ins_rc[0] = PyDict_SetItem(_PyPopenProcs,
4595 fileObj[0],
4596 procObj);
4598 fileObj[1] = PyLong_FromVoidPtr(p_s[1]);
4599 if (fileObj[1])
4601 ins_rc[1] = PyDict_SetItem(_PyPopenProcs,
4602 fileObj[1],
4603 procObj);
4605 if (file_count >= 3)
4607 fileObj[2] = PyLong_FromVoidPtr(p_s[2]);
4608 if (fileObj[2])
4610 ins_rc[2] = PyDict_SetItem(_PyPopenProcs,
4611 fileObj[2],
4612 procObj);
4616 if (ins_rc[0] < 0 || !fileObj[0] ||
4617 ins_rc[1] < 0 || (file_count > 1 && !fileObj[1]) ||
4618 ins_rc[2] < 0 || (file_count > 2 && !fileObj[2]))
4620 /* Something failed - remove any dictionary
4621 * entries that did make it.
4623 if (!ins_rc[0] && fileObj[0])
4625 PyDict_DelItem(_PyPopenProcs,
4626 fileObj[0]);
4628 if (!ins_rc[1] && fileObj[1])
4630 PyDict_DelItem(_PyPopenProcs,
4631 fileObj[1]);
4633 if (!ins_rc[2] && fileObj[2])
4635 PyDict_DelItem(_PyPopenProcs,
4636 fileObj[2]);
4642 * Clean up our localized references for the dictionary keys
4643 * and value since PyDict_SetItem will Py_INCREF any copies
4644 * that got placed in the dictionary.
4646 Py_XDECREF(procObj);
4647 Py_XDECREF(fileObj[0]);
4648 Py_XDECREF(fileObj[1]);
4649 Py_XDECREF(fileObj[2]);
4652 /* Child is launched. */
4653 return f;
4657 * Wrapper for fclose() to use for popen* files, so we can retrieve the
4658 * exit code for the child process and return as a result of the close.
4660 * This function uses the _PyPopenProcs dictionary in order to map the
4661 * input file pointer to information about the process that was
4662 * originally created by the popen* call that created the file pointer.
4663 * The dictionary uses the file pointer as a key (with one entry
4664 * inserted for each file returned by the original popen* call) and a
4665 * single list object as the value for all files from a single call.
4666 * The list object contains the Win32 process handle at [0], and a file
4667 * count at [1], which is initialized to the total number of file
4668 * handles using that list.
4670 * This function closes whichever handle it is passed, and decrements
4671 * the file count in the dictionary for the process handle pointed to
4672 * by this file. On the last close (when the file count reaches zero),
4673 * this function will wait for the child process and then return its
4674 * exit code as the result of the close() operation. This permits the
4675 * files to be closed in any order - it is always the close() of the
4676 * final handle that will return the exit code.
4678 * NOTE: This function is currently called with the GIL released.
4679 * hence we use the GILState API to manage our state.
4682 static int _PyPclose(FILE *file)
4684 int result;
4685 int exit_code;
4686 pid_t pipe_pid;
4687 PyObject *procObj, *pidObj, *intObj, *fileObj;
4688 int file_count;
4689 #ifdef WITH_THREAD
4690 PyGILState_STATE state;
4691 #endif
4693 /* Close the file handle first, to ensure it can't block the
4694 * child from exiting if it's the last handle.
4696 result = fclose(file);
4698 #ifdef WITH_THREAD
4699 state = PyGILState_Ensure();
4700 #endif
4701 if (_PyPopenProcs)
4703 if ((fileObj = PyLong_FromVoidPtr(file)) != NULL &&
4704 (procObj = PyDict_GetItem(_PyPopenProcs,
4705 fileObj)) != NULL &&
4706 (pidObj = PyList_GetItem(procObj,0)) != NULL &&
4707 (intObj = PyList_GetItem(procObj,1)) != NULL)
4709 pipe_pid = (pid_t) PyLong_AsPid(pidObj);
4710 file_count = (int) PyInt_AsLong(intObj);
4712 if (file_count > 1)
4714 /* Still other files referencing process */
4715 file_count--;
4716 PyList_SetItem(procObj,1,
4717 PyInt_FromLong((long) file_count));
4719 else
4721 /* Last file for this process */
4722 if (result != EOF &&
4723 waitpid(pipe_pid, &exit_code, 0) == pipe_pid)
4725 /* extract exit status */
4726 if (WIFEXITED(exit_code))
4728 result = WEXITSTATUS(exit_code);
4730 else
4732 errno = EPIPE;
4733 result = -1;
4736 else
4738 /* Indicate failure - this will cause the file object
4739 * to raise an I/O error and translate the last
4740 * error code from errno. We do have a problem with
4741 * last errors that overlap the normal errno table,
4742 * but that's a consistent problem with the file object.
4744 result = -1;
4748 /* Remove this file pointer from dictionary */
4749 PyDict_DelItem(_PyPopenProcs, fileObj);
4751 if (PyDict_Size(_PyPopenProcs) == 0)
4753 Py_DECREF(_PyPopenProcs);
4754 _PyPopenProcs = NULL;
4757 } /* if object retrieval ok */
4759 Py_XDECREF(fileObj);
4760 } /* if _PyPopenProcs */
4762 #ifdef WITH_THREAD
4763 PyGILState_Release(state);
4764 #endif
4765 return result;
4768 #endif /* PYCC_??? */
4770 #elif defined(MS_WINDOWS)
4773 * Portable 'popen' replacement for Win32.
4775 * Written by Bill Tutt <billtut@microsoft.com>. Minor tweaks
4776 * and 2.0 integration by Fredrik Lundh <fredrik@pythonware.com>
4777 * Return code handling by David Bolen <db3l@fitlinxx.com>.
4780 #include <malloc.h>
4781 #include <io.h>
4782 #include <fcntl.h>
4784 /* These tell _PyPopen() wether to return 1, 2, or 3 file objects. */
4785 #define POPEN_1 1
4786 #define POPEN_2 2
4787 #define POPEN_3 3
4788 #define POPEN_4 4
4790 static PyObject *_PyPopen(char *, int, int);
4791 static int _PyPclose(FILE *file);
4794 * Internal dictionary mapping popen* file pointers to process handles,
4795 * for use when retrieving the process exit code. See _PyPclose() below
4796 * for more information on this dictionary's use.
4798 static PyObject *_PyPopenProcs = NULL;
4801 /* popen that works from a GUI.
4803 * The result of this function is a pipe (file) connected to the
4804 * processes stdin or stdout, depending on the requested mode.
4807 static PyObject *
4808 posix_popen(PyObject *self, PyObject *args)
4810 PyObject *f;
4811 int tm = 0;
4813 char *cmdstring;
4814 char *mode = "r";
4815 int bufsize = -1;
4816 if (!PyArg_ParseTuple(args, "s|si:popen", &cmdstring, &mode, &bufsize))
4817 return NULL;
4819 if (*mode == 'r')
4820 tm = _O_RDONLY;
4821 else if (*mode != 'w') {
4822 PyErr_SetString(PyExc_ValueError, "popen() arg 2 must be 'r' or 'w'");
4823 return NULL;
4824 } else
4825 tm = _O_WRONLY;
4827 if (bufsize != -1) {
4828 PyErr_SetString(PyExc_ValueError, "popen() arg 3 must be -1");
4829 return NULL;
4832 if (*(mode+1) == 't')
4833 f = _PyPopen(cmdstring, tm | _O_TEXT, POPEN_1);
4834 else if (*(mode+1) == 'b')
4835 f = _PyPopen(cmdstring, tm | _O_BINARY, POPEN_1);
4836 else
4837 f = _PyPopen(cmdstring, tm | _O_TEXT, POPEN_1);
4839 return f;
4842 /* Variation on win32pipe.popen
4844 * The result of this function is a pipe (file) connected to the
4845 * process's stdin, and a pipe connected to the process's stdout.
4848 static PyObject *
4849 win32_popen2(PyObject *self, PyObject *args)
4851 PyObject *f;
4852 int tm=0;
4854 char *cmdstring;
4855 char *mode = "t";
4856 int bufsize = -1;
4857 if (!PyArg_ParseTuple(args, "s|si:popen2", &cmdstring, &mode, &bufsize))
4858 return NULL;
4860 if (*mode == 't')
4861 tm = _O_TEXT;
4862 else if (*mode != 'b') {
4863 PyErr_SetString(PyExc_ValueError, "popen2() arg 2 must be 't' or 'b'");
4864 return NULL;
4865 } else
4866 tm = _O_BINARY;
4868 if (bufsize != -1) {
4869 PyErr_SetString(PyExc_ValueError, "popen2() arg 3 must be -1");
4870 return NULL;
4873 f = _PyPopen(cmdstring, tm, POPEN_2);
4875 return f;
4879 * Variation on <om win32pipe.popen>
4881 * The result of this function is 3 pipes - the process's stdin,
4882 * stdout and stderr
4885 static PyObject *
4886 win32_popen3(PyObject *self, PyObject *args)
4888 PyObject *f;
4889 int tm = 0;
4891 char *cmdstring;
4892 char *mode = "t";
4893 int bufsize = -1;
4894 if (!PyArg_ParseTuple(args, "s|si:popen3", &cmdstring, &mode, &bufsize))
4895 return NULL;
4897 if (*mode == 't')
4898 tm = _O_TEXT;
4899 else if (*mode != 'b') {
4900 PyErr_SetString(PyExc_ValueError, "popen3() arg 2 must be 't' or 'b'");
4901 return NULL;
4902 } else
4903 tm = _O_BINARY;
4905 if (bufsize != -1) {
4906 PyErr_SetString(PyExc_ValueError, "popen3() arg 3 must be -1");
4907 return NULL;
4910 f = _PyPopen(cmdstring, tm, POPEN_3);
4912 return f;
4916 * Variation on win32pipe.popen
4918 * The result of this function is 2 pipes - the processes stdin,
4919 * and stdout+stderr combined as a single pipe.
4922 static PyObject *
4923 win32_popen4(PyObject *self, PyObject *args)
4925 PyObject *f;
4926 int tm = 0;
4928 char *cmdstring;
4929 char *mode = "t";
4930 int bufsize = -1;
4931 if (!PyArg_ParseTuple(args, "s|si:popen4", &cmdstring, &mode, &bufsize))
4932 return NULL;
4934 if (*mode == 't')
4935 tm = _O_TEXT;
4936 else if (*mode != 'b') {
4937 PyErr_SetString(PyExc_ValueError, "popen4() arg 2 must be 't' or 'b'");
4938 return NULL;
4939 } else
4940 tm = _O_BINARY;
4942 if (bufsize != -1) {
4943 PyErr_SetString(PyExc_ValueError, "popen4() arg 3 must be -1");
4944 return NULL;
4947 f = _PyPopen(cmdstring, tm, POPEN_4);
4949 return f;
4952 static BOOL
4953 _PyPopenCreateProcess(char *cmdstring,
4954 HANDLE hStdin,
4955 HANDLE hStdout,
4956 HANDLE hStderr,
4957 HANDLE *hProcess)
4959 PROCESS_INFORMATION piProcInfo;
4960 STARTUPINFO siStartInfo;
4961 DWORD dwProcessFlags = 0; /* no NEW_CONSOLE by default for Ctrl+C handling */
4962 char *s1,*s2, *s3 = " /c ";
4963 const char *szConsoleSpawn = "w9xpopen.exe";
4964 int i;
4965 Py_ssize_t x;
4967 if (i = GetEnvironmentVariable("COMSPEC",NULL,0)) {
4968 char *comshell;
4970 s1 = (char *)alloca(i);
4971 if (!(x = GetEnvironmentVariable("COMSPEC", s1, i)))
4972 /* x < i, so x fits into an integer */
4973 return (int)x;
4975 /* Explicitly check if we are using COMMAND.COM. If we are
4976 * then use the w9xpopen hack.
4978 comshell = s1 + x;
4979 while (comshell >= s1 && *comshell != '\\')
4980 --comshell;
4981 ++comshell;
4983 if (GetVersion() < 0x80000000 &&
4984 _stricmp(comshell, "command.com") != 0) {
4985 /* NT/2000 and not using command.com. */
4986 x = i + strlen(s3) + strlen(cmdstring) + 1;
4987 s2 = (char *)alloca(x);
4988 ZeroMemory(s2, x);
4989 PyOS_snprintf(s2, x, "%s%s%s", s1, s3, cmdstring);
4991 else {
4993 * Oh gag, we're on Win9x or using COMMAND.COM. Use
4994 * the workaround listed in KB: Q150956
4996 char modulepath[_MAX_PATH];
4997 struct stat statinfo;
4998 GetModuleFileName(NULL, modulepath, sizeof(modulepath));
4999 for (x = i = 0; modulepath[i]; i++)
5000 if (modulepath[i] == SEP)
5001 x = i+1;
5002 modulepath[x] = '\0';
5003 /* Create the full-name to w9xpopen, so we can test it exists */
5004 strncat(modulepath,
5005 szConsoleSpawn,
5006 (sizeof(modulepath)/sizeof(modulepath[0]))
5007 -strlen(modulepath));
5008 if (stat(modulepath, &statinfo) != 0) {
5009 size_t mplen = sizeof(modulepath)/sizeof(modulepath[0]);
5010 /* Eeek - file-not-found - possibly an embedding
5011 situation - see if we can locate it in sys.prefix
5013 strncpy(modulepath,
5014 Py_GetExecPrefix(),
5015 mplen);
5016 modulepath[mplen-1] = '\0';
5017 if (modulepath[strlen(modulepath)-1] != '\\')
5018 strcat(modulepath, "\\");
5019 strncat(modulepath,
5020 szConsoleSpawn,
5021 mplen-strlen(modulepath));
5022 /* No where else to look - raise an easily identifiable
5023 error, rather than leaving Windows to report
5024 "file not found" - as the user is probably blissfully
5025 unaware this shim EXE is used, and it will confuse them.
5026 (well, it confused me for a while ;-)
5028 if (stat(modulepath, &statinfo) != 0) {
5029 PyErr_Format(PyExc_RuntimeError,
5030 "Can not locate '%s' which is needed "
5031 "for popen to work with your shell "
5032 "or platform.",
5033 szConsoleSpawn);
5034 return FALSE;
5037 x = i + strlen(s3) + strlen(cmdstring) + 1 +
5038 strlen(modulepath) +
5039 strlen(szConsoleSpawn) + 1;
5041 s2 = (char *)alloca(x);
5042 ZeroMemory(s2, x);
5043 /* To maintain correct argument passing semantics,
5044 we pass the command-line as it stands, and allow
5045 quoting to be applied. w9xpopen.exe will then
5046 use its argv vector, and re-quote the necessary
5047 args for the ultimate child process.
5049 PyOS_snprintf(
5050 s2, x,
5051 "\"%s\" %s%s%s",
5052 modulepath,
5055 cmdstring);
5056 /* Not passing CREATE_NEW_CONSOLE has been known to
5057 cause random failures on win9x. Specifically a
5058 dialog:
5059 "Your program accessed mem currently in use at xxx"
5060 and a hopeful warning about the stability of your
5061 system.
5062 Cost is Ctrl+C won't kill children, but anyone
5063 who cares can have a go!
5065 dwProcessFlags |= CREATE_NEW_CONSOLE;
5069 /* Could be an else here to try cmd.exe / command.com in the path
5070 Now we'll just error out.. */
5071 else {
5072 PyErr_SetString(PyExc_RuntimeError,
5073 "Cannot locate a COMSPEC environment variable to "
5074 "use as the shell");
5075 return FALSE;
5078 ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
5079 siStartInfo.cb = sizeof(STARTUPINFO);
5080 siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
5081 siStartInfo.hStdInput = hStdin;
5082 siStartInfo.hStdOutput = hStdout;
5083 siStartInfo.hStdError = hStderr;
5084 siStartInfo.wShowWindow = SW_HIDE;
5086 if (CreateProcess(NULL,
5088 NULL,
5089 NULL,
5090 TRUE,
5091 dwProcessFlags,
5092 NULL,
5093 NULL,
5094 &siStartInfo,
5095 &piProcInfo) ) {
5096 /* Close the handles now so anyone waiting is woken. */
5097 CloseHandle(piProcInfo.hThread);
5099 /* Return process handle */
5100 *hProcess = piProcInfo.hProcess;
5101 return TRUE;
5103 win32_error("CreateProcess", s2);
5104 return FALSE;
5107 /* The following code is based off of KB: Q190351 */
5109 static PyObject *
5110 _PyPopen(char *cmdstring, int mode, int n)
5112 HANDLE hChildStdinRd, hChildStdinWr, hChildStdoutRd, hChildStdoutWr,
5113 hChildStderrRd, hChildStderrWr, hChildStdinWrDup, hChildStdoutRdDup,
5114 hChildStderrRdDup, hProcess; /* hChildStdoutWrDup; */
5116 SECURITY_ATTRIBUTES saAttr;
5117 BOOL fSuccess;
5118 int fd1, fd2, fd3;
5119 FILE *f1, *f2, *f3;
5120 long file_count;
5121 PyObject *f;
5123 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
5124 saAttr.bInheritHandle = TRUE;
5125 saAttr.lpSecurityDescriptor = NULL;
5127 if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
5128 return win32_error("CreatePipe", NULL);
5130 /* Create new output read handle and the input write handle. Set
5131 * the inheritance properties to FALSE. Otherwise, the child inherits
5132 * these handles; resulting in non-closeable handles to the pipes
5133 * being created. */
5134 fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
5135 GetCurrentProcess(), &hChildStdinWrDup, 0,
5136 FALSE,
5137 DUPLICATE_SAME_ACCESS);
5138 if (!fSuccess)
5139 return win32_error("DuplicateHandle", NULL);
5141 /* Close the inheritable version of ChildStdin
5142 that we're using. */
5143 CloseHandle(hChildStdinWr);
5145 if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
5146 return win32_error("CreatePipe", NULL);
5148 fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
5149 GetCurrentProcess(), &hChildStdoutRdDup, 0,
5150 FALSE, DUPLICATE_SAME_ACCESS);
5151 if (!fSuccess)
5152 return win32_error("DuplicateHandle", NULL);
5154 /* Close the inheritable version of ChildStdout
5155 that we're using. */
5156 CloseHandle(hChildStdoutRd);
5158 if (n != POPEN_4) {
5159 if (!CreatePipe(&hChildStderrRd, &hChildStderrWr, &saAttr, 0))
5160 return win32_error("CreatePipe", NULL);
5161 fSuccess = DuplicateHandle(GetCurrentProcess(),
5162 hChildStderrRd,
5163 GetCurrentProcess(),
5164 &hChildStderrRdDup, 0,
5165 FALSE, DUPLICATE_SAME_ACCESS);
5166 if (!fSuccess)
5167 return win32_error("DuplicateHandle", NULL);
5168 /* Close the inheritable version of ChildStdErr that we're using. */
5169 CloseHandle(hChildStderrRd);
5172 switch (n) {
5173 case POPEN_1:
5174 switch (mode & (_O_RDONLY | _O_TEXT | _O_BINARY | _O_WRONLY)) {
5175 case _O_WRONLY | _O_TEXT:
5176 /* Case for writing to child Stdin in text mode. */
5177 fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode);
5178 f1 = _fdopen(fd1, "w");
5179 f = PyFile_FromFile(f1, cmdstring, "w", _PyPclose);
5180 PyFile_SetBufSize(f, 0);
5181 /* We don't care about these pipes anymore, so close them. */
5182 CloseHandle(hChildStdoutRdDup);
5183 CloseHandle(hChildStderrRdDup);
5184 break;
5186 case _O_RDONLY | _O_TEXT:
5187 /* Case for reading from child Stdout in text mode. */
5188 fd1 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode);
5189 f1 = _fdopen(fd1, "r");
5190 f = PyFile_FromFile(f1, cmdstring, "r", _PyPclose);
5191 PyFile_SetBufSize(f, 0);
5192 /* We don't care about these pipes anymore, so close them. */
5193 CloseHandle(hChildStdinWrDup);
5194 CloseHandle(hChildStderrRdDup);
5195 break;
5197 case _O_RDONLY | _O_BINARY:
5198 /* Case for readinig from child Stdout in binary mode. */
5199 fd1 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode);
5200 f1 = _fdopen(fd1, "rb");
5201 f = PyFile_FromFile(f1, cmdstring, "rb", _PyPclose);
5202 PyFile_SetBufSize(f, 0);
5203 /* We don't care about these pipes anymore, so close them. */
5204 CloseHandle(hChildStdinWrDup);
5205 CloseHandle(hChildStderrRdDup);
5206 break;
5208 case _O_WRONLY | _O_BINARY:
5209 /* Case for writing to child Stdin in binary mode. */
5210 fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode);
5211 f1 = _fdopen(fd1, "wb");
5212 f = PyFile_FromFile(f1, cmdstring, "wb", _PyPclose);
5213 PyFile_SetBufSize(f, 0);
5214 /* We don't care about these pipes anymore, so close them. */
5215 CloseHandle(hChildStdoutRdDup);
5216 CloseHandle(hChildStderrRdDup);
5217 break;
5219 file_count = 1;
5220 break;
5222 case POPEN_2:
5223 case POPEN_4:
5225 char *m1, *m2;
5226 PyObject *p1, *p2;
5228 if (mode & _O_TEXT) {
5229 m1 = "r";
5230 m2 = "w";
5231 } else {
5232 m1 = "rb";
5233 m2 = "wb";
5236 fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode);
5237 f1 = _fdopen(fd1, m2);
5238 fd2 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode);
5239 f2 = _fdopen(fd2, m1);
5240 p1 = PyFile_FromFile(f1, cmdstring, m2, _PyPclose);
5241 PyFile_SetBufSize(p1, 0);
5242 p2 = PyFile_FromFile(f2, cmdstring, m1, _PyPclose);
5243 PyFile_SetBufSize(p2, 0);
5245 if (n != 4)
5246 CloseHandle(hChildStderrRdDup);
5248 f = PyTuple_Pack(2,p1,p2);
5249 Py_XDECREF(p1);
5250 Py_XDECREF(p2);
5251 file_count = 2;
5252 break;
5255 case POPEN_3:
5257 char *m1, *m2;
5258 PyObject *p1, *p2, *p3;
5260 if (mode & _O_TEXT) {
5261 m1 = "r";
5262 m2 = "w";
5263 } else {
5264 m1 = "rb";
5265 m2 = "wb";
5268 fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode);
5269 f1 = _fdopen(fd1, m2);
5270 fd2 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode);
5271 f2 = _fdopen(fd2, m1);
5272 fd3 = _open_osfhandle((Py_intptr_t)hChildStderrRdDup, mode);
5273 f3 = _fdopen(fd3, m1);
5274 p1 = PyFile_FromFile(f1, cmdstring, m2, _PyPclose);
5275 p2 = PyFile_FromFile(f2, cmdstring, m1, _PyPclose);
5276 p3 = PyFile_FromFile(f3, cmdstring, m1, _PyPclose);
5277 PyFile_SetBufSize(p1, 0);
5278 PyFile_SetBufSize(p2, 0);
5279 PyFile_SetBufSize(p3, 0);
5280 f = PyTuple_Pack(3,p1,p2,p3);
5281 Py_XDECREF(p1);
5282 Py_XDECREF(p2);
5283 Py_XDECREF(p3);
5284 file_count = 3;
5285 break;
5289 if (n == POPEN_4) {
5290 if (!_PyPopenCreateProcess(cmdstring,
5291 hChildStdinRd,
5292 hChildStdoutWr,
5293 hChildStdoutWr,
5294 &hProcess))
5295 return NULL;
5297 else {
5298 if (!_PyPopenCreateProcess(cmdstring,
5299 hChildStdinRd,
5300 hChildStdoutWr,
5301 hChildStderrWr,
5302 &hProcess))
5303 return NULL;
5307 * Insert the files we've created into the process dictionary
5308 * all referencing the list with the process handle and the
5309 * initial number of files (see description below in _PyPclose).
5310 * Since if _PyPclose later tried to wait on a process when all
5311 * handles weren't closed, it could create a deadlock with the
5312 * child, we spend some energy here to try to ensure that we
5313 * either insert all file handles into the dictionary or none
5314 * at all. It's a little clumsy with the various popen modes
5315 * and variable number of files involved.
5317 if (!_PyPopenProcs) {
5318 _PyPopenProcs = PyDict_New();
5321 if (_PyPopenProcs) {
5322 PyObject *procObj, *hProcessObj, *intObj, *fileObj[3];
5323 int ins_rc[3];
5325 fileObj[0] = fileObj[1] = fileObj[2] = NULL;
5326 ins_rc[0] = ins_rc[1] = ins_rc[2] = 0;
5328 procObj = PyList_New(2);
5329 hProcessObj = PyLong_FromVoidPtr(hProcess);
5330 intObj = PyInt_FromLong(file_count);
5332 if (procObj && hProcessObj && intObj) {
5333 PyList_SetItem(procObj,0,hProcessObj);
5334 PyList_SetItem(procObj,1,intObj);
5336 fileObj[0] = PyLong_FromVoidPtr(f1);
5337 if (fileObj[0]) {
5338 ins_rc[0] = PyDict_SetItem(_PyPopenProcs,
5339 fileObj[0],
5340 procObj);
5342 if (file_count >= 2) {
5343 fileObj[1] = PyLong_FromVoidPtr(f2);
5344 if (fileObj[1]) {
5345 ins_rc[1] = PyDict_SetItem(_PyPopenProcs,
5346 fileObj[1],
5347 procObj);
5350 if (file_count >= 3) {
5351 fileObj[2] = PyLong_FromVoidPtr(f3);
5352 if (fileObj[2]) {
5353 ins_rc[2] = PyDict_SetItem(_PyPopenProcs,
5354 fileObj[2],
5355 procObj);
5359 if (ins_rc[0] < 0 || !fileObj[0] ||
5360 ins_rc[1] < 0 || (file_count > 1 && !fileObj[1]) ||
5361 ins_rc[2] < 0 || (file_count > 2 && !fileObj[2])) {
5362 /* Something failed - remove any dictionary
5363 * entries that did make it.
5365 if (!ins_rc[0] && fileObj[0]) {
5366 PyDict_DelItem(_PyPopenProcs,
5367 fileObj[0]);
5369 if (!ins_rc[1] && fileObj[1]) {
5370 PyDict_DelItem(_PyPopenProcs,
5371 fileObj[1]);
5373 if (!ins_rc[2] && fileObj[2]) {
5374 PyDict_DelItem(_PyPopenProcs,
5375 fileObj[2]);
5381 * Clean up our localized references for the dictionary keys
5382 * and value since PyDict_SetItem will Py_INCREF any copies
5383 * that got placed in the dictionary.
5385 Py_XDECREF(procObj);
5386 Py_XDECREF(fileObj[0]);
5387 Py_XDECREF(fileObj[1]);
5388 Py_XDECREF(fileObj[2]);
5391 /* Child is launched. Close the parents copy of those pipe
5392 * handles that only the child should have open. You need to
5393 * make sure that no handles to the write end of the output pipe
5394 * are maintained in this process or else the pipe will not close
5395 * when the child process exits and the ReadFile will hang. */
5397 if (!CloseHandle(hChildStdinRd))
5398 return win32_error("CloseHandle", NULL);
5400 if (!CloseHandle(hChildStdoutWr))
5401 return win32_error("CloseHandle", NULL);
5403 if ((n != 4) && (!CloseHandle(hChildStderrWr)))
5404 return win32_error("CloseHandle", NULL);
5406 return f;
5410 * Wrapper for fclose() to use for popen* files, so we can retrieve the
5411 * exit code for the child process and return as a result of the close.
5413 * This function uses the _PyPopenProcs dictionary in order to map the
5414 * input file pointer to information about the process that was
5415 * originally created by the popen* call that created the file pointer.
5416 * The dictionary uses the file pointer as a key (with one entry
5417 * inserted for each file returned by the original popen* call) and a
5418 * single list object as the value for all files from a single call.
5419 * The list object contains the Win32 process handle at [0], and a file
5420 * count at [1], which is initialized to the total number of file
5421 * handles using that list.
5423 * This function closes whichever handle it is passed, and decrements
5424 * the file count in the dictionary for the process handle pointed to
5425 * by this file. On the last close (when the file count reaches zero),
5426 * this function will wait for the child process and then return its
5427 * exit code as the result of the close() operation. This permits the
5428 * files to be closed in any order - it is always the close() of the
5429 * final handle that will return the exit code.
5431 * NOTE: This function is currently called with the GIL released.
5432 * hence we use the GILState API to manage our state.
5435 static int _PyPclose(FILE *file)
5437 int result;
5438 DWORD exit_code;
5439 HANDLE hProcess;
5440 PyObject *procObj, *hProcessObj, *intObj, *fileObj;
5441 long file_count;
5442 #ifdef WITH_THREAD
5443 PyGILState_STATE state;
5444 #endif
5446 /* Close the file handle first, to ensure it can't block the
5447 * child from exiting if it's the last handle.
5449 result = fclose(file);
5450 #ifdef WITH_THREAD
5451 state = PyGILState_Ensure();
5452 #endif
5453 if (_PyPopenProcs) {
5454 if ((fileObj = PyLong_FromVoidPtr(file)) != NULL &&
5455 (procObj = PyDict_GetItem(_PyPopenProcs,
5456 fileObj)) != NULL &&
5457 (hProcessObj = PyList_GetItem(procObj,0)) != NULL &&
5458 (intObj = PyList_GetItem(procObj,1)) != NULL) {
5460 hProcess = PyLong_AsVoidPtr(hProcessObj);
5461 file_count = PyInt_AsLong(intObj);
5463 if (file_count > 1) {
5464 /* Still other files referencing process */
5465 file_count--;
5466 PyList_SetItem(procObj,1,
5467 PyInt_FromLong(file_count));
5468 } else {
5469 /* Last file for this process */
5470 if (result != EOF &&
5471 WaitForSingleObject(hProcess, INFINITE) != WAIT_FAILED &&
5472 GetExitCodeProcess(hProcess, &exit_code)) {
5473 /* Possible truncation here in 16-bit environments, but
5474 * real exit codes are just the lower byte in any event.
5476 result = exit_code;
5477 } else {
5478 /* Indicate failure - this will cause the file object
5479 * to raise an I/O error and translate the last Win32
5480 * error code from errno. We do have a problem with
5481 * last errors that overlap the normal errno table,
5482 * but that's a consistent problem with the file object.
5484 if (result != EOF) {
5485 /* If the error wasn't from the fclose(), then
5486 * set errno for the file object error handling.
5488 errno = GetLastError();
5490 result = -1;
5493 /* Free up the native handle at this point */
5494 CloseHandle(hProcess);
5497 /* Remove this file pointer from dictionary */
5498 PyDict_DelItem(_PyPopenProcs, fileObj);
5500 if (PyDict_Size(_PyPopenProcs) == 0) {
5501 Py_DECREF(_PyPopenProcs);
5502 _PyPopenProcs = NULL;
5505 } /* if object retrieval ok */
5507 Py_XDECREF(fileObj);
5508 } /* if _PyPopenProcs */
5510 #ifdef WITH_THREAD
5511 PyGILState_Release(state);
5512 #endif
5513 return result;
5516 #else /* which OS? */
5517 static PyObject *
5518 posix_popen(PyObject *self, PyObject *args)
5520 char *name;
5521 char *mode = "r";
5522 int bufsize = -1;
5523 FILE *fp;
5524 PyObject *f;
5525 if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize))
5526 return NULL;
5527 /* Strip mode of binary or text modifiers */
5528 if (strcmp(mode, "rb") == 0 || strcmp(mode, "rt") == 0)
5529 mode = "r";
5530 else if (strcmp(mode, "wb") == 0 || strcmp(mode, "wt") == 0)
5531 mode = "w";
5532 Py_BEGIN_ALLOW_THREADS
5533 fp = popen(name, mode);
5534 Py_END_ALLOW_THREADS
5535 if (fp == NULL)
5536 return posix_error();
5537 f = PyFile_FromFile(fp, name, mode, pclose);
5538 if (f != NULL)
5539 PyFile_SetBufSize(f, bufsize);
5540 return f;
5543 #endif /* PYOS_??? */
5544 #endif /* HAVE_POPEN */
5547 #ifdef HAVE_SETUID
5548 PyDoc_STRVAR(posix_setuid__doc__,
5549 "setuid(uid)\n\n\
5550 Set the current process's user id.");
5552 static PyObject *
5553 posix_setuid(PyObject *self, PyObject *args)
5555 long uid_arg;
5556 uid_t uid;
5557 if (!PyArg_ParseTuple(args, "l:setuid", &uid_arg))
5558 return NULL;
5559 uid = uid_arg;
5560 if (uid != uid_arg) {
5561 PyErr_SetString(PyExc_OverflowError, "user id too big");
5562 return NULL;
5564 if (setuid(uid) < 0)
5565 return posix_error();
5566 Py_INCREF(Py_None);
5567 return Py_None;
5569 #endif /* HAVE_SETUID */
5572 #ifdef HAVE_SETEUID
5573 PyDoc_STRVAR(posix_seteuid__doc__,
5574 "seteuid(uid)\n\n\
5575 Set the current process's effective user id.");
5577 static PyObject *
5578 posix_seteuid (PyObject *self, PyObject *args)
5580 long euid_arg;
5581 uid_t euid;
5582 if (!PyArg_ParseTuple(args, "l", &euid_arg))
5583 return NULL;
5584 euid = euid_arg;
5585 if (euid != euid_arg) {
5586 PyErr_SetString(PyExc_OverflowError, "user id too big");
5587 return NULL;
5589 if (seteuid(euid) < 0) {
5590 return posix_error();
5591 } else {
5592 Py_INCREF(Py_None);
5593 return Py_None;
5596 #endif /* HAVE_SETEUID */
5598 #ifdef HAVE_SETEGID
5599 PyDoc_STRVAR(posix_setegid__doc__,
5600 "setegid(gid)\n\n\
5601 Set the current process's effective group id.");
5603 static PyObject *
5604 posix_setegid (PyObject *self, PyObject *args)
5606 long egid_arg;
5607 gid_t egid;
5608 if (!PyArg_ParseTuple(args, "l", &egid_arg))
5609 return NULL;
5610 egid = egid_arg;
5611 if (egid != egid_arg) {
5612 PyErr_SetString(PyExc_OverflowError, "group id too big");
5613 return NULL;
5615 if (setegid(egid) < 0) {
5616 return posix_error();
5617 } else {
5618 Py_INCREF(Py_None);
5619 return Py_None;
5622 #endif /* HAVE_SETEGID */
5624 #ifdef HAVE_SETREUID
5625 PyDoc_STRVAR(posix_setreuid__doc__,
5626 "setreuid(ruid, euid)\n\n\
5627 Set the current process's real and effective user ids.");
5629 static PyObject *
5630 posix_setreuid (PyObject *self, PyObject *args)
5632 long ruid_arg, euid_arg;
5633 uid_t ruid, euid;
5634 if (!PyArg_ParseTuple(args, "ll", &ruid_arg, &euid_arg))
5635 return NULL;
5636 ruid = ruid_arg;
5637 euid = euid_arg;
5638 if (euid != euid_arg || ruid != ruid_arg) {
5639 PyErr_SetString(PyExc_OverflowError, "user id too big");
5640 return NULL;
5642 if (setreuid(ruid, euid) < 0) {
5643 return posix_error();
5644 } else {
5645 Py_INCREF(Py_None);
5646 return Py_None;
5649 #endif /* HAVE_SETREUID */
5651 #ifdef HAVE_SETREGID
5652 PyDoc_STRVAR(posix_setregid__doc__,
5653 "setregid(rgid, egid)\n\n\
5654 Set the current process's real and effective group ids.");
5656 static PyObject *
5657 posix_setregid (PyObject *self, PyObject *args)
5659 long rgid_arg, egid_arg;
5660 gid_t rgid, egid;
5661 if (!PyArg_ParseTuple(args, "ll", &rgid_arg, &egid_arg))
5662 return NULL;
5663 rgid = rgid_arg;
5664 egid = egid_arg;
5665 if (egid != egid_arg || rgid != rgid_arg) {
5666 PyErr_SetString(PyExc_OverflowError, "group id too big");
5667 return NULL;
5669 if (setregid(rgid, egid) < 0) {
5670 return posix_error();
5671 } else {
5672 Py_INCREF(Py_None);
5673 return Py_None;
5676 #endif /* HAVE_SETREGID */
5678 #ifdef HAVE_SETGID
5679 PyDoc_STRVAR(posix_setgid__doc__,
5680 "setgid(gid)\n\n\
5681 Set the current process's group id.");
5683 static PyObject *
5684 posix_setgid(PyObject *self, PyObject *args)
5686 long gid_arg;
5687 gid_t gid;
5688 if (!PyArg_ParseTuple(args, "l:setgid", &gid_arg))
5689 return NULL;
5690 gid = gid_arg;
5691 if (gid != gid_arg) {
5692 PyErr_SetString(PyExc_OverflowError, "group id too big");
5693 return NULL;
5695 if (setgid(gid) < 0)
5696 return posix_error();
5697 Py_INCREF(Py_None);
5698 return Py_None;
5700 #endif /* HAVE_SETGID */
5702 #ifdef HAVE_SETGROUPS
5703 PyDoc_STRVAR(posix_setgroups__doc__,
5704 "setgroups(list)\n\n\
5705 Set the groups of the current process to list.");
5707 static PyObject *
5708 posix_setgroups(PyObject *self, PyObject *groups)
5710 int i, len;
5711 gid_t grouplist[MAX_GROUPS];
5713 if (!PySequence_Check(groups)) {
5714 PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
5715 return NULL;
5717 len = PySequence_Size(groups);
5718 if (len > MAX_GROUPS) {
5719 PyErr_SetString(PyExc_ValueError, "too many groups");
5720 return NULL;
5722 for(i = 0; i < len; i++) {
5723 PyObject *elem;
5724 elem = PySequence_GetItem(groups, i);
5725 if (!elem)
5726 return NULL;
5727 if (!PyInt_Check(elem)) {
5728 if (!PyLong_Check(elem)) {
5729 PyErr_SetString(PyExc_TypeError,
5730 "groups must be integers");
5731 Py_DECREF(elem);
5732 return NULL;
5733 } else {
5734 unsigned long x = PyLong_AsUnsignedLong(elem);
5735 if (PyErr_Occurred()) {
5736 PyErr_SetString(PyExc_TypeError,
5737 "group id too big");
5738 Py_DECREF(elem);
5739 return NULL;
5741 grouplist[i] = x;
5742 /* read back to see if it fits in gid_t */
5743 if (grouplist[i] != x) {
5744 PyErr_SetString(PyExc_TypeError,
5745 "group id too big");
5746 Py_DECREF(elem);
5747 return NULL;
5750 } else {
5751 long x = PyInt_AsLong(elem);
5752 grouplist[i] = x;
5753 if (grouplist[i] != x) {
5754 PyErr_SetString(PyExc_TypeError,
5755 "group id too big");
5756 Py_DECREF(elem);
5757 return NULL;
5760 Py_DECREF(elem);
5763 if (setgroups(len, grouplist) < 0)
5764 return posix_error();
5765 Py_INCREF(Py_None);
5766 return Py_None;
5768 #endif /* HAVE_SETGROUPS */
5770 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
5771 static PyObject *
5772 wait_helper(pid_t pid, int status, struct rusage *ru)
5774 PyObject *result;
5775 static PyObject *struct_rusage;
5777 if (pid == -1)
5778 return posix_error();
5780 if (struct_rusage == NULL) {
5781 PyObject *m = PyImport_ImportModuleNoBlock("resource");
5782 if (m == NULL)
5783 return NULL;
5784 struct_rusage = PyObject_GetAttrString(m, "struct_rusage");
5785 Py_DECREF(m);
5786 if (struct_rusage == NULL)
5787 return NULL;
5790 /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
5791 result = PyStructSequence_New((PyTypeObject*) struct_rusage);
5792 if (!result)
5793 return NULL;
5795 #ifndef doubletime
5796 #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
5797 #endif
5799 PyStructSequence_SET_ITEM(result, 0,
5800 PyFloat_FromDouble(doubletime(ru->ru_utime)));
5801 PyStructSequence_SET_ITEM(result, 1,
5802 PyFloat_FromDouble(doubletime(ru->ru_stime)));
5803 #define SET_INT(result, index, value)\
5804 PyStructSequence_SET_ITEM(result, index, PyInt_FromLong(value))
5805 SET_INT(result, 2, ru->ru_maxrss);
5806 SET_INT(result, 3, ru->ru_ixrss);
5807 SET_INT(result, 4, ru->ru_idrss);
5808 SET_INT(result, 5, ru->ru_isrss);
5809 SET_INT(result, 6, ru->ru_minflt);
5810 SET_INT(result, 7, ru->ru_majflt);
5811 SET_INT(result, 8, ru->ru_nswap);
5812 SET_INT(result, 9, ru->ru_inblock);
5813 SET_INT(result, 10, ru->ru_oublock);
5814 SET_INT(result, 11, ru->ru_msgsnd);
5815 SET_INT(result, 12, ru->ru_msgrcv);
5816 SET_INT(result, 13, ru->ru_nsignals);
5817 SET_INT(result, 14, ru->ru_nvcsw);
5818 SET_INT(result, 15, ru->ru_nivcsw);
5819 #undef SET_INT
5821 if (PyErr_Occurred()) {
5822 Py_DECREF(result);
5823 return NULL;
5826 return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
5828 #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
5830 #ifdef HAVE_WAIT3
5831 PyDoc_STRVAR(posix_wait3__doc__,
5832 "wait3(options) -> (pid, status, rusage)\n\n\
5833 Wait for completion of a child process.");
5835 static PyObject *
5836 posix_wait3(PyObject *self, PyObject *args)
5838 pid_t pid;
5839 int options;
5840 struct rusage ru;
5841 WAIT_TYPE status;
5842 WAIT_STATUS_INT(status) = 0;
5844 if (!PyArg_ParseTuple(args, "i:wait3", &options))
5845 return NULL;
5847 Py_BEGIN_ALLOW_THREADS
5848 pid = wait3(&status, options, &ru);
5849 Py_END_ALLOW_THREADS
5851 return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
5853 #endif /* HAVE_WAIT3 */
5855 #ifdef HAVE_WAIT4
5856 PyDoc_STRVAR(posix_wait4__doc__,
5857 "wait4(pid, options) -> (pid, status, rusage)\n\n\
5858 Wait for completion of a given child process.");
5860 static PyObject *
5861 posix_wait4(PyObject *self, PyObject *args)
5863 pid_t pid;
5864 int options;
5865 struct rusage ru;
5866 WAIT_TYPE status;
5867 WAIT_STATUS_INT(status) = 0;
5869 if (!PyArg_ParseTuple(args, PARSE_PID "i:wait4", &pid, &options))
5870 return NULL;
5872 Py_BEGIN_ALLOW_THREADS
5873 pid = wait4(pid, &status, options, &ru);
5874 Py_END_ALLOW_THREADS
5876 return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
5878 #endif /* HAVE_WAIT4 */
5880 #ifdef HAVE_WAITPID
5881 PyDoc_STRVAR(posix_waitpid__doc__,
5882 "waitpid(pid, options) -> (pid, status)\n\n\
5883 Wait for completion of a given child process.");
5885 static PyObject *
5886 posix_waitpid(PyObject *self, PyObject *args)
5888 pid_t pid;
5889 int options;
5890 WAIT_TYPE status;
5891 WAIT_STATUS_INT(status) = 0;
5893 if (!PyArg_ParseTuple(args, PARSE_PID "i:waitpid", &pid, &options))
5894 return NULL;
5895 Py_BEGIN_ALLOW_THREADS
5896 pid = waitpid(pid, &status, options);
5897 Py_END_ALLOW_THREADS
5898 if (pid == -1)
5899 return posix_error();
5901 return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
5904 #elif defined(HAVE_CWAIT)
5906 /* MS C has a variant of waitpid() that's usable for most purposes. */
5907 PyDoc_STRVAR(posix_waitpid__doc__,
5908 "waitpid(pid, options) -> (pid, status << 8)\n\n"
5909 "Wait for completion of a given process. options is ignored on Windows.");
5911 static PyObject *
5912 posix_waitpid(PyObject *self, PyObject *args)
5914 Py_intptr_t pid;
5915 int status, options;
5917 if (!PyArg_ParseTuple(args, PARSE_PID "i:waitpid", &pid, &options))
5918 return NULL;
5919 Py_BEGIN_ALLOW_THREADS
5920 pid = _cwait(&status, pid, options);
5921 Py_END_ALLOW_THREADS
5922 if (pid == -1)
5923 return posix_error();
5925 /* shift the status left a byte so this is more like the POSIX waitpid */
5926 return Py_BuildValue("Ni", PyLong_FromPid(pid), status << 8);
5928 #endif /* HAVE_WAITPID || HAVE_CWAIT */
5930 #ifdef HAVE_WAIT
5931 PyDoc_STRVAR(posix_wait__doc__,
5932 "wait() -> (pid, status)\n\n\
5933 Wait for completion of a child process.");
5935 static PyObject *
5936 posix_wait(PyObject *self, PyObject *noargs)
5938 pid_t pid;
5939 WAIT_TYPE status;
5940 WAIT_STATUS_INT(status) = 0;
5942 Py_BEGIN_ALLOW_THREADS
5943 pid = wait(&status);
5944 Py_END_ALLOW_THREADS
5945 if (pid == -1)
5946 return posix_error();
5948 return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
5950 #endif
5953 PyDoc_STRVAR(posix_lstat__doc__,
5954 "lstat(path) -> stat result\n\n\
5955 Like stat(path), but do not follow symbolic links.");
5957 static PyObject *
5958 posix_lstat(PyObject *self, PyObject *args)
5960 #ifdef HAVE_LSTAT
5961 return posix_do_stat(self, args, "et:lstat", lstat, NULL, NULL);
5962 #else /* !HAVE_LSTAT */
5963 #ifdef MS_WINDOWS
5964 return posix_do_stat(self, args, "et:lstat", STAT, "U:lstat", win32_wstat);
5965 #else
5966 return posix_do_stat(self, args, "et:lstat", STAT, NULL, NULL);
5967 #endif
5968 #endif /* !HAVE_LSTAT */
5972 #ifdef HAVE_READLINK
5973 PyDoc_STRVAR(posix_readlink__doc__,
5974 "readlink(path) -> path\n\n\
5975 Return a string representing the path to which the symbolic link points.");
5977 static PyObject *
5978 posix_readlink(PyObject *self, PyObject *args)
5980 PyObject* v;
5981 char buf[MAXPATHLEN];
5982 char *path;
5983 int n;
5984 #ifdef Py_USING_UNICODE
5985 int arg_is_unicode = 0;
5986 #endif
5988 if (!PyArg_ParseTuple(args, "et:readlink",
5989 Py_FileSystemDefaultEncoding, &path))
5990 return NULL;
5991 #ifdef Py_USING_UNICODE
5992 v = PySequence_GetItem(args, 0);
5993 if (v == NULL) {
5994 PyMem_Free(path);
5995 return NULL;
5998 if (PyUnicode_Check(v)) {
5999 arg_is_unicode = 1;
6001 Py_DECREF(v);
6002 #endif
6004 Py_BEGIN_ALLOW_THREADS
6005 n = readlink(path, buf, (int) sizeof buf);
6006 Py_END_ALLOW_THREADS
6007 if (n < 0)
6008 return posix_error_with_allocated_filename(path);
6010 PyMem_Free(path);
6011 v = PyString_FromStringAndSize(buf, n);
6012 #ifdef Py_USING_UNICODE
6013 if (arg_is_unicode) {
6014 PyObject *w;
6016 w = PyUnicode_FromEncodedObject(v,
6017 Py_FileSystemDefaultEncoding,
6018 "strict");
6019 if (w != NULL) {
6020 Py_DECREF(v);
6021 v = w;
6023 else {
6024 /* fall back to the original byte string, as
6025 discussed in patch #683592 */
6026 PyErr_Clear();
6029 #endif
6030 return v;
6032 #endif /* HAVE_READLINK */
6035 #ifdef HAVE_SYMLINK
6036 PyDoc_STRVAR(posix_symlink__doc__,
6037 "symlink(src, dst)\n\n\
6038 Create a symbolic link pointing to src named dst.");
6040 static PyObject *
6041 posix_symlink(PyObject *self, PyObject *args)
6043 return posix_2str(args, "etet:symlink", symlink);
6045 #endif /* HAVE_SYMLINK */
6048 #ifdef HAVE_TIMES
6049 #if defined(PYCC_VACPP) && defined(PYOS_OS2)
6050 static long
6051 system_uptime(void)
6053 ULONG value = 0;
6055 Py_BEGIN_ALLOW_THREADS
6056 DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &value, sizeof(value));
6057 Py_END_ALLOW_THREADS
6059 return value;
6062 static PyObject *
6063 posix_times(PyObject *self, PyObject *noargs)
6065 /* Currently Only Uptime is Provided -- Others Later */
6066 return Py_BuildValue("ddddd",
6067 (double)0 /* t.tms_utime / HZ */,
6068 (double)0 /* t.tms_stime / HZ */,
6069 (double)0 /* t.tms_cutime / HZ */,
6070 (double)0 /* t.tms_cstime / HZ */,
6071 (double)system_uptime() / 1000);
6073 #else /* not OS2 */
6074 #define NEED_TICKS_PER_SECOND
6075 static long ticks_per_second = -1;
6076 static PyObject *
6077 posix_times(PyObject *self, PyObject *noargs)
6079 struct tms t;
6080 clock_t c;
6081 errno = 0;
6082 c = times(&t);
6083 if (c == (clock_t) -1)
6084 return posix_error();
6085 return Py_BuildValue("ddddd",
6086 (double)t.tms_utime / ticks_per_second,
6087 (double)t.tms_stime / ticks_per_second,
6088 (double)t.tms_cutime / ticks_per_second,
6089 (double)t.tms_cstime / ticks_per_second,
6090 (double)c / ticks_per_second);
6092 #endif /* not OS2 */
6093 #endif /* HAVE_TIMES */
6096 #ifdef MS_WINDOWS
6097 #define HAVE_TIMES /* so the method table will pick it up */
6098 static PyObject *
6099 posix_times(PyObject *self, PyObject *noargs)
6101 FILETIME create, exit, kernel, user;
6102 HANDLE hProc;
6103 hProc = GetCurrentProcess();
6104 GetProcessTimes(hProc, &create, &exit, &kernel, &user);
6105 /* The fields of a FILETIME structure are the hi and lo part
6106 of a 64-bit value expressed in 100 nanosecond units.
6107 1e7 is one second in such units; 1e-7 the inverse.
6108 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
6110 return Py_BuildValue(
6111 "ddddd",
6112 (double)(user.dwHighDateTime*429.4967296 +
6113 user.dwLowDateTime*1e-7),
6114 (double)(kernel.dwHighDateTime*429.4967296 +
6115 kernel.dwLowDateTime*1e-7),
6116 (double)0,
6117 (double)0,
6118 (double)0);
6120 #endif /* MS_WINDOWS */
6122 #ifdef HAVE_TIMES
6123 PyDoc_STRVAR(posix_times__doc__,
6124 "times() -> (utime, stime, cutime, cstime, elapsed_time)\n\n\
6125 Return a tuple of floating point numbers indicating process times.");
6126 #endif
6129 #ifdef HAVE_GETSID
6130 PyDoc_STRVAR(posix_getsid__doc__,
6131 "getsid(pid) -> sid\n\n\
6132 Call the system call getsid().");
6134 static PyObject *
6135 posix_getsid(PyObject *self, PyObject *args)
6137 pid_t pid;
6138 int sid;
6139 if (!PyArg_ParseTuple(args, PARSE_PID ":getsid", &pid))
6140 return NULL;
6141 sid = getsid(pid);
6142 if (sid < 0)
6143 return posix_error();
6144 return PyInt_FromLong((long)sid);
6146 #endif /* HAVE_GETSID */
6149 #ifdef HAVE_SETSID
6150 PyDoc_STRVAR(posix_setsid__doc__,
6151 "setsid()\n\n\
6152 Call the system call setsid().");
6154 static PyObject *
6155 posix_setsid(PyObject *self, PyObject *noargs)
6157 if (setsid() < 0)
6158 return posix_error();
6159 Py_INCREF(Py_None);
6160 return Py_None;
6162 #endif /* HAVE_SETSID */
6164 #ifdef HAVE_SETPGID
6165 PyDoc_STRVAR(posix_setpgid__doc__,
6166 "setpgid(pid, pgrp)\n\n\
6167 Call the system call setpgid().");
6169 static PyObject *
6170 posix_setpgid(PyObject *self, PyObject *args)
6172 pid_t pid;
6173 int pgrp;
6174 if (!PyArg_ParseTuple(args, PARSE_PID "i:setpgid", &pid, &pgrp))
6175 return NULL;
6176 if (setpgid(pid, pgrp) < 0)
6177 return posix_error();
6178 Py_INCREF(Py_None);
6179 return Py_None;
6181 #endif /* HAVE_SETPGID */
6184 #ifdef HAVE_TCGETPGRP
6185 PyDoc_STRVAR(posix_tcgetpgrp__doc__,
6186 "tcgetpgrp(fd) -> pgid\n\n\
6187 Return the process group associated with the terminal given by a fd.");
6189 static PyObject *
6190 posix_tcgetpgrp(PyObject *self, PyObject *args)
6192 int fd;
6193 pid_t pgid;
6194 if (!PyArg_ParseTuple(args, "i:tcgetpgrp", &fd))
6195 return NULL;
6196 pgid = tcgetpgrp(fd);
6197 if (pgid < 0)
6198 return posix_error();
6199 return PyLong_FromPid(pgid);
6201 #endif /* HAVE_TCGETPGRP */
6204 #ifdef HAVE_TCSETPGRP
6205 PyDoc_STRVAR(posix_tcsetpgrp__doc__,
6206 "tcsetpgrp(fd, pgid)\n\n\
6207 Set the process group associated with the terminal given by a fd.");
6209 static PyObject *
6210 posix_tcsetpgrp(PyObject *self, PyObject *args)
6212 int fd;
6213 pid_t pgid;
6214 if (!PyArg_ParseTuple(args, "i" PARSE_PID ":tcsetpgrp", &fd, &pgid))
6215 return NULL;
6216 if (tcsetpgrp(fd, pgid) < 0)
6217 return posix_error();
6218 Py_INCREF(Py_None);
6219 return Py_None;
6221 #endif /* HAVE_TCSETPGRP */
6223 /* Functions acting on file descriptors */
6225 PyDoc_STRVAR(posix_open__doc__,
6226 "open(filename, flag [, mode=0777]) -> fd\n\n\
6227 Open a file (for low level IO).");
6229 static PyObject *
6230 posix_open(PyObject *self, PyObject *args)
6232 char *file = NULL;
6233 int flag;
6234 int mode = 0777;
6235 int fd;
6237 #ifdef MS_WINDOWS
6238 PyUnicodeObject *po;
6239 if (PyArg_ParseTuple(args, "Ui|i:mkdir", &po, &flag, &mode)) {
6240 Py_BEGIN_ALLOW_THREADS
6241 /* PyUnicode_AS_UNICODE OK without thread
6242 lock as it is a simple dereference. */
6243 fd = _wopen(PyUnicode_AS_UNICODE(po), flag, mode);
6244 Py_END_ALLOW_THREADS
6245 if (fd < 0)
6246 return posix_error();
6247 return PyInt_FromLong((long)fd);
6249 /* Drop the argument parsing error as narrow strings
6250 are also valid. */
6251 PyErr_Clear();
6252 #endif
6254 if (!PyArg_ParseTuple(args, "eti|i",
6255 Py_FileSystemDefaultEncoding, &file,
6256 &flag, &mode))
6257 return NULL;
6259 Py_BEGIN_ALLOW_THREADS
6260 fd = open(file, flag, mode);
6261 Py_END_ALLOW_THREADS
6262 if (fd < 0)
6263 return posix_error_with_allocated_filename(file);
6264 PyMem_Free(file);
6265 return PyInt_FromLong((long)fd);
6269 PyDoc_STRVAR(posix_close__doc__,
6270 "close(fd)\n\n\
6271 Close a file descriptor (for low level IO).");
6273 static PyObject *
6274 posix_close(PyObject *self, PyObject *args)
6276 int fd, res;
6277 if (!PyArg_ParseTuple(args, "i:close", &fd))
6278 return NULL;
6279 if (!_PyVerify_fd(fd))
6280 return posix_error();
6281 Py_BEGIN_ALLOW_THREADS
6282 res = close(fd);
6283 Py_END_ALLOW_THREADS
6284 if (res < 0)
6285 return posix_error();
6286 Py_INCREF(Py_None);
6287 return Py_None;
6291 PyDoc_STRVAR(posix_closerange__doc__,
6292 "closerange(fd_low, fd_high)\n\n\
6293 Closes all file descriptors in [fd_low, fd_high), ignoring errors.");
6295 static PyObject *
6296 posix_closerange(PyObject *self, PyObject *args)
6298 int fd_from, fd_to, i;
6299 if (!PyArg_ParseTuple(args, "ii:closerange", &fd_from, &fd_to))
6300 return NULL;
6301 Py_BEGIN_ALLOW_THREADS
6302 for (i = fd_from; i < fd_to; i++)
6303 if (_PyVerify_fd(i))
6304 close(i);
6305 Py_END_ALLOW_THREADS
6306 Py_RETURN_NONE;
6310 PyDoc_STRVAR(posix_dup__doc__,
6311 "dup(fd) -> fd2\n\n\
6312 Return a duplicate of a file descriptor.");
6314 static PyObject *
6315 posix_dup(PyObject *self, PyObject *args)
6317 int fd;
6318 if (!PyArg_ParseTuple(args, "i:dup", &fd))
6319 return NULL;
6320 if (!_PyVerify_fd(fd))
6321 return posix_error();
6322 Py_BEGIN_ALLOW_THREADS
6323 fd = dup(fd);
6324 Py_END_ALLOW_THREADS
6325 if (fd < 0)
6326 return posix_error();
6327 return PyInt_FromLong((long)fd);
6331 PyDoc_STRVAR(posix_dup2__doc__,
6332 "dup2(old_fd, new_fd)\n\n\
6333 Duplicate file descriptor.");
6335 static PyObject *
6336 posix_dup2(PyObject *self, PyObject *args)
6338 int fd, fd2, res;
6339 if (!PyArg_ParseTuple(args, "ii:dup2", &fd, &fd2))
6340 return NULL;
6341 if (!_PyVerify_fd_dup2(fd, fd2))
6342 return posix_error();
6343 Py_BEGIN_ALLOW_THREADS
6344 res = dup2(fd, fd2);
6345 Py_END_ALLOW_THREADS
6346 if (res < 0)
6347 return posix_error();
6348 Py_INCREF(Py_None);
6349 return Py_None;
6353 PyDoc_STRVAR(posix_lseek__doc__,
6354 "lseek(fd, pos, how) -> newpos\n\n\
6355 Set the current position of a file descriptor.");
6357 static PyObject *
6358 posix_lseek(PyObject *self, PyObject *args)
6360 int fd, how;
6361 #if defined(MS_WIN64) || defined(MS_WINDOWS)
6362 PY_LONG_LONG pos, res;
6363 #else
6364 off_t pos, res;
6365 #endif
6366 PyObject *posobj;
6367 if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how))
6368 return NULL;
6369 #ifdef SEEK_SET
6370 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
6371 switch (how) {
6372 case 0: how = SEEK_SET; break;
6373 case 1: how = SEEK_CUR; break;
6374 case 2: how = SEEK_END; break;
6376 #endif /* SEEK_END */
6378 #if !defined(HAVE_LARGEFILE_SUPPORT)
6379 pos = PyInt_AsLong(posobj);
6380 #else
6381 pos = PyLong_Check(posobj) ?
6382 PyLong_AsLongLong(posobj) : PyInt_AsLong(posobj);
6383 #endif
6384 if (PyErr_Occurred())
6385 return NULL;
6387 if (!_PyVerify_fd(fd))
6388 return posix_error();
6389 Py_BEGIN_ALLOW_THREADS
6390 #if defined(MS_WIN64) || defined(MS_WINDOWS)
6391 res = _lseeki64(fd, pos, how);
6392 #else
6393 res = lseek(fd, pos, how);
6394 #endif
6395 Py_END_ALLOW_THREADS
6396 if (res < 0)
6397 return posix_error();
6399 #if !defined(HAVE_LARGEFILE_SUPPORT)
6400 return PyInt_FromLong(res);
6401 #else
6402 return PyLong_FromLongLong(res);
6403 #endif
6407 PyDoc_STRVAR(posix_read__doc__,
6408 "read(fd, buffersize) -> string\n\n\
6409 Read a file descriptor.");
6411 static PyObject *
6412 posix_read(PyObject *self, PyObject *args)
6414 int fd, size, n;
6415 PyObject *buffer;
6416 if (!PyArg_ParseTuple(args, "ii:read", &fd, &size))
6417 return NULL;
6418 if (size < 0) {
6419 errno = EINVAL;
6420 return posix_error();
6422 buffer = PyString_FromStringAndSize((char *)NULL, size);
6423 if (buffer == NULL)
6424 return NULL;
6425 if (!_PyVerify_fd(fd))
6426 return posix_error();
6427 Py_BEGIN_ALLOW_THREADS
6428 n = read(fd, PyString_AsString(buffer), size);
6429 Py_END_ALLOW_THREADS
6430 if (n < 0) {
6431 Py_DECREF(buffer);
6432 return posix_error();
6434 if (n != size)
6435 _PyString_Resize(&buffer, n);
6436 return buffer;
6440 PyDoc_STRVAR(posix_write__doc__,
6441 "write(fd, string) -> byteswritten\n\n\
6442 Write a string to a file descriptor.");
6444 static PyObject *
6445 posix_write(PyObject *self, PyObject *args)
6447 Py_buffer pbuf;
6448 int fd;
6449 Py_ssize_t size;
6451 if (!PyArg_ParseTuple(args, "is*:write", &fd, &pbuf))
6452 return NULL;
6453 if (!_PyVerify_fd(fd))
6454 return posix_error();
6455 Py_BEGIN_ALLOW_THREADS
6456 size = write(fd, pbuf.buf, (size_t)pbuf.len);
6457 Py_END_ALLOW_THREADS
6458 PyBuffer_Release(&pbuf);
6459 if (size < 0)
6460 return posix_error();
6461 return PyInt_FromSsize_t(size);
6465 PyDoc_STRVAR(posix_fstat__doc__,
6466 "fstat(fd) -> stat result\n\n\
6467 Like stat(), but for an open file descriptor.");
6469 static PyObject *
6470 posix_fstat(PyObject *self, PyObject *args)
6472 int fd;
6473 STRUCT_STAT st;
6474 int res;
6475 if (!PyArg_ParseTuple(args, "i:fstat", &fd))
6476 return NULL;
6477 #ifdef __VMS
6478 /* on OpenVMS we must ensure that all bytes are written to the file */
6479 fsync(fd);
6480 #endif
6481 if (!_PyVerify_fd(fd))
6482 return posix_error();
6483 Py_BEGIN_ALLOW_THREADS
6484 res = FSTAT(fd, &st);
6485 Py_END_ALLOW_THREADS
6486 if (res != 0) {
6487 #ifdef MS_WINDOWS
6488 return win32_error("fstat", NULL);
6489 #else
6490 return posix_error();
6491 #endif
6494 return _pystat_fromstructstat(&st);
6498 PyDoc_STRVAR(posix_fdopen__doc__,
6499 "fdopen(fd [, mode='r' [, bufsize]]) -> file_object\n\n\
6500 Return an open file object connected to a file descriptor.");
6502 static PyObject *
6503 posix_fdopen(PyObject *self, PyObject *args)
6505 int fd;
6506 char *orgmode = "r";
6507 int bufsize = -1;
6508 FILE *fp;
6509 PyObject *f;
6510 char *mode;
6511 if (!PyArg_ParseTuple(args, "i|si", &fd, &orgmode, &bufsize))
6512 return NULL;
6514 /* Sanitize mode. See fileobject.c */
6515 mode = PyMem_MALLOC(strlen(orgmode)+3);
6516 if (!mode) {
6517 PyErr_NoMemory();
6518 return NULL;
6520 strcpy(mode, orgmode);
6521 if (_PyFile_SanitizeMode(mode)) {
6522 PyMem_FREE(mode);
6523 return NULL;
6525 if (!_PyVerify_fd(fd))
6526 return posix_error();
6527 Py_BEGIN_ALLOW_THREADS
6528 #if !defined(MS_WINDOWS) && defined(HAVE_FCNTL_H)
6529 if (mode[0] == 'a') {
6530 /* try to make sure the O_APPEND flag is set */
6531 int flags;
6532 flags = fcntl(fd, F_GETFL);
6533 if (flags != -1)
6534 fcntl(fd, F_SETFL, flags | O_APPEND);
6535 fp = fdopen(fd, mode);
6536 if (fp == NULL && flags != -1)
6537 /* restore old mode if fdopen failed */
6538 fcntl(fd, F_SETFL, flags);
6539 } else {
6540 fp = fdopen(fd, mode);
6542 #else
6543 fp = fdopen(fd, mode);
6544 #endif
6545 Py_END_ALLOW_THREADS
6546 PyMem_FREE(mode);
6547 if (fp == NULL)
6548 return posix_error();
6549 f = PyFile_FromFile(fp, "<fdopen>", orgmode, fclose);
6550 if (f != NULL)
6551 PyFile_SetBufSize(f, bufsize);
6552 return f;
6555 PyDoc_STRVAR(posix_isatty__doc__,
6556 "isatty(fd) -> bool\n\n\
6557 Return True if the file descriptor 'fd' is an open file descriptor\n\
6558 connected to the slave end of a terminal.");
6560 static PyObject *
6561 posix_isatty(PyObject *self, PyObject *args)
6563 int fd;
6564 if (!PyArg_ParseTuple(args, "i:isatty", &fd))
6565 return NULL;
6566 if (!_PyVerify_fd(fd))
6567 return PyBool_FromLong(0);
6568 return PyBool_FromLong(isatty(fd));
6571 #ifdef HAVE_PIPE
6572 PyDoc_STRVAR(posix_pipe__doc__,
6573 "pipe() -> (read_end, write_end)\n\n\
6574 Create a pipe.");
6576 static PyObject *
6577 posix_pipe(PyObject *self, PyObject *noargs)
6579 #if defined(PYOS_OS2)
6580 HFILE read, write;
6581 APIRET rc;
6583 Py_BEGIN_ALLOW_THREADS
6584 rc = DosCreatePipe( &read, &write, 4096);
6585 Py_END_ALLOW_THREADS
6586 if (rc != NO_ERROR)
6587 return os2_error(rc);
6589 return Py_BuildValue("(ii)", read, write);
6590 #else
6591 #if !defined(MS_WINDOWS)
6592 int fds[2];
6593 int res;
6594 Py_BEGIN_ALLOW_THREADS
6595 res = pipe(fds);
6596 Py_END_ALLOW_THREADS
6597 if (res != 0)
6598 return posix_error();
6599 return Py_BuildValue("(ii)", fds[0], fds[1]);
6600 #else /* MS_WINDOWS */
6601 HANDLE read, write;
6602 int read_fd, write_fd;
6603 BOOL ok;
6604 Py_BEGIN_ALLOW_THREADS
6605 ok = CreatePipe(&read, &write, NULL, 0);
6606 Py_END_ALLOW_THREADS
6607 if (!ok)
6608 return win32_error("CreatePipe", NULL);
6609 read_fd = _open_osfhandle((Py_intptr_t)read, 0);
6610 write_fd = _open_osfhandle((Py_intptr_t)write, 1);
6611 return Py_BuildValue("(ii)", read_fd, write_fd);
6612 #endif /* MS_WINDOWS */
6613 #endif
6615 #endif /* HAVE_PIPE */
6618 #ifdef HAVE_MKFIFO
6619 PyDoc_STRVAR(posix_mkfifo__doc__,
6620 "mkfifo(filename [, mode=0666])\n\n\
6621 Create a FIFO (a POSIX named pipe).");
6623 static PyObject *
6624 posix_mkfifo(PyObject *self, PyObject *args)
6626 char *filename;
6627 int mode = 0666;
6628 int res;
6629 if (!PyArg_ParseTuple(args, "s|i:mkfifo", &filename, &mode))
6630 return NULL;
6631 Py_BEGIN_ALLOW_THREADS
6632 res = mkfifo(filename, mode);
6633 Py_END_ALLOW_THREADS
6634 if (res < 0)
6635 return posix_error();
6636 Py_INCREF(Py_None);
6637 return Py_None;
6639 #endif
6642 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
6643 PyDoc_STRVAR(posix_mknod__doc__,
6644 "mknod(filename [, mode=0600, device])\n\n\
6645 Create a filesystem node (file, device special file or named pipe)\n\
6646 named filename. mode specifies both the permissions to use and the\n\
6647 type of node to be created, being combined (bitwise OR) with one of\n\
6648 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\
6649 device defines the newly created device special file (probably using\n\
6650 os.makedev()), otherwise it is ignored.");
6653 static PyObject *
6654 posix_mknod(PyObject *self, PyObject *args)
6656 char *filename;
6657 int mode = 0600;
6658 int device = 0;
6659 int res;
6660 if (!PyArg_ParseTuple(args, "s|ii:mknod", &filename, &mode, &device))
6661 return NULL;
6662 Py_BEGIN_ALLOW_THREADS
6663 res = mknod(filename, mode, device);
6664 Py_END_ALLOW_THREADS
6665 if (res < 0)
6666 return posix_error();
6667 Py_INCREF(Py_None);
6668 return Py_None;
6670 #endif
6672 #ifdef HAVE_DEVICE_MACROS
6673 PyDoc_STRVAR(posix_major__doc__,
6674 "major(device) -> major number\n\
6675 Extracts a device major number from a raw device number.");
6677 static PyObject *
6678 posix_major(PyObject *self, PyObject *args)
6680 int device;
6681 if (!PyArg_ParseTuple(args, "i:major", &device))
6682 return NULL;
6683 return PyInt_FromLong((long)major(device));
6686 PyDoc_STRVAR(posix_minor__doc__,
6687 "minor(device) -> minor number\n\
6688 Extracts a device minor number from a raw device number.");
6690 static PyObject *
6691 posix_minor(PyObject *self, PyObject *args)
6693 int device;
6694 if (!PyArg_ParseTuple(args, "i:minor", &device))
6695 return NULL;
6696 return PyInt_FromLong((long)minor(device));
6699 PyDoc_STRVAR(posix_makedev__doc__,
6700 "makedev(major, minor) -> device number\n\
6701 Composes a raw device number from the major and minor device numbers.");
6703 static PyObject *
6704 posix_makedev(PyObject *self, PyObject *args)
6706 int major, minor;
6707 if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor))
6708 return NULL;
6709 return PyInt_FromLong((long)makedev(major, minor));
6711 #endif /* device macros */
6714 #ifdef HAVE_FTRUNCATE
6715 PyDoc_STRVAR(posix_ftruncate__doc__,
6716 "ftruncate(fd, length)\n\n\
6717 Truncate a file to a specified length.");
6719 static PyObject *
6720 posix_ftruncate(PyObject *self, PyObject *args)
6722 int fd;
6723 off_t length;
6724 int res;
6725 PyObject *lenobj;
6727 if (!PyArg_ParseTuple(args, "iO:ftruncate", &fd, &lenobj))
6728 return NULL;
6730 #if !defined(HAVE_LARGEFILE_SUPPORT)
6731 length = PyInt_AsLong(lenobj);
6732 #else
6733 length = PyLong_Check(lenobj) ?
6734 PyLong_AsLongLong(lenobj) : PyInt_AsLong(lenobj);
6735 #endif
6736 if (PyErr_Occurred())
6737 return NULL;
6739 Py_BEGIN_ALLOW_THREADS
6740 res = ftruncate(fd, length);
6741 Py_END_ALLOW_THREADS
6742 if (res < 0)
6743 return posix_error();
6744 Py_INCREF(Py_None);
6745 return Py_None;
6747 #endif
6749 #ifdef HAVE_PUTENV
6750 PyDoc_STRVAR(posix_putenv__doc__,
6751 "putenv(key, value)\n\n\
6752 Change or add an environment variable.");
6754 /* Save putenv() parameters as values here, so we can collect them when they
6755 * get re-set with another call for the same key. */
6756 static PyObject *posix_putenv_garbage;
6758 static PyObject *
6759 posix_putenv(PyObject *self, PyObject *args)
6761 char *s1, *s2;
6762 char *newenv;
6763 PyObject *newstr;
6764 size_t len;
6766 if (!PyArg_ParseTuple(args, "ss:putenv", &s1, &s2))
6767 return NULL;
6769 #if defined(PYOS_OS2)
6770 if (stricmp(s1, "BEGINLIBPATH") == 0) {
6771 APIRET rc;
6773 rc = DosSetExtLIBPATH(s2, BEGIN_LIBPATH);
6774 if (rc != NO_ERROR)
6775 return os2_error(rc);
6777 } else if (stricmp(s1, "ENDLIBPATH") == 0) {
6778 APIRET rc;
6780 rc = DosSetExtLIBPATH(s2, END_LIBPATH);
6781 if (rc != NO_ERROR)
6782 return os2_error(rc);
6783 } else {
6784 #endif
6786 /* XXX This can leak memory -- not easy to fix :-( */
6787 len = strlen(s1) + strlen(s2) + 2;
6788 /* len includes space for a trailing \0; the size arg to
6789 PyString_FromStringAndSize does not count that */
6790 newstr = PyString_FromStringAndSize(NULL, (int)len - 1);
6791 if (newstr == NULL)
6792 return PyErr_NoMemory();
6793 newenv = PyString_AS_STRING(newstr);
6794 PyOS_snprintf(newenv, len, "%s=%s", s1, s2);
6795 if (putenv(newenv)) {
6796 Py_DECREF(newstr);
6797 posix_error();
6798 return NULL;
6800 /* Install the first arg and newstr in posix_putenv_garbage;
6801 * this will cause previous value to be collected. This has to
6802 * happen after the real putenv() call because the old value
6803 * was still accessible until then. */
6804 if (PyDict_SetItem(posix_putenv_garbage,
6805 PyTuple_GET_ITEM(args, 0), newstr)) {
6806 /* really not much we can do; just leak */
6807 PyErr_Clear();
6809 else {
6810 Py_DECREF(newstr);
6813 #if defined(PYOS_OS2)
6815 #endif
6816 Py_INCREF(Py_None);
6817 return Py_None;
6819 #endif /* putenv */
6821 #ifdef HAVE_UNSETENV
6822 PyDoc_STRVAR(posix_unsetenv__doc__,
6823 "unsetenv(key)\n\n\
6824 Delete an environment variable.");
6826 static PyObject *
6827 posix_unsetenv(PyObject *self, PyObject *args)
6829 char *s1;
6831 if (!PyArg_ParseTuple(args, "s:unsetenv", &s1))
6832 return NULL;
6834 unsetenv(s1);
6836 /* Remove the key from posix_putenv_garbage;
6837 * this will cause it to be collected. This has to
6838 * happen after the real unsetenv() call because the
6839 * old value was still accessible until then.
6841 if (PyDict_DelItem(posix_putenv_garbage,
6842 PyTuple_GET_ITEM(args, 0))) {
6843 /* really not much we can do; just leak */
6844 PyErr_Clear();
6847 Py_INCREF(Py_None);
6848 return Py_None;
6850 #endif /* unsetenv */
6852 PyDoc_STRVAR(posix_strerror__doc__,
6853 "strerror(code) -> string\n\n\
6854 Translate an error code to a message string.");
6856 static PyObject *
6857 posix_strerror(PyObject *self, PyObject *args)
6859 int code;
6860 char *message;
6861 if (!PyArg_ParseTuple(args, "i:strerror", &code))
6862 return NULL;
6863 message = strerror(code);
6864 if (message == NULL) {
6865 PyErr_SetString(PyExc_ValueError,
6866 "strerror() argument out of range");
6867 return NULL;
6869 return PyString_FromString(message);
6873 #ifdef HAVE_SYS_WAIT_H
6875 #ifdef WCOREDUMP
6876 PyDoc_STRVAR(posix_WCOREDUMP__doc__,
6877 "WCOREDUMP(status) -> bool\n\n\
6878 Return True if the process returning 'status' was dumped to a core file.");
6880 static PyObject *
6881 posix_WCOREDUMP(PyObject *self, PyObject *args)
6883 WAIT_TYPE status;
6884 WAIT_STATUS_INT(status) = 0;
6886 if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status)))
6887 return NULL;
6889 return PyBool_FromLong(WCOREDUMP(status));
6891 #endif /* WCOREDUMP */
6893 #ifdef WIFCONTINUED
6894 PyDoc_STRVAR(posix_WIFCONTINUED__doc__,
6895 "WIFCONTINUED(status) -> bool\n\n\
6896 Return True if the process returning 'status' was continued from a\n\
6897 job control stop.");
6899 static PyObject *
6900 posix_WIFCONTINUED(PyObject *self, PyObject *args)
6902 WAIT_TYPE status;
6903 WAIT_STATUS_INT(status) = 0;
6905 if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status)))
6906 return NULL;
6908 return PyBool_FromLong(WIFCONTINUED(status));
6910 #endif /* WIFCONTINUED */
6912 #ifdef WIFSTOPPED
6913 PyDoc_STRVAR(posix_WIFSTOPPED__doc__,
6914 "WIFSTOPPED(status) -> bool\n\n\
6915 Return True if the process returning 'status' was stopped.");
6917 static PyObject *
6918 posix_WIFSTOPPED(PyObject *self, PyObject *args)
6920 WAIT_TYPE status;
6921 WAIT_STATUS_INT(status) = 0;
6923 if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status)))
6924 return NULL;
6926 return PyBool_FromLong(WIFSTOPPED(status));
6928 #endif /* WIFSTOPPED */
6930 #ifdef WIFSIGNALED
6931 PyDoc_STRVAR(posix_WIFSIGNALED__doc__,
6932 "WIFSIGNALED(status) -> bool\n\n\
6933 Return True if the process returning 'status' was terminated by a signal.");
6935 static PyObject *
6936 posix_WIFSIGNALED(PyObject *self, PyObject *args)
6938 WAIT_TYPE status;
6939 WAIT_STATUS_INT(status) = 0;
6941 if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status)))
6942 return NULL;
6944 return PyBool_FromLong(WIFSIGNALED(status));
6946 #endif /* WIFSIGNALED */
6948 #ifdef WIFEXITED
6949 PyDoc_STRVAR(posix_WIFEXITED__doc__,
6950 "WIFEXITED(status) -> bool\n\n\
6951 Return true if the process returning 'status' exited using the exit()\n\
6952 system call.");
6954 static PyObject *
6955 posix_WIFEXITED(PyObject *self, PyObject *args)
6957 WAIT_TYPE status;
6958 WAIT_STATUS_INT(status) = 0;
6960 if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status)))
6961 return NULL;
6963 return PyBool_FromLong(WIFEXITED(status));
6965 #endif /* WIFEXITED */
6967 #ifdef WEXITSTATUS
6968 PyDoc_STRVAR(posix_WEXITSTATUS__doc__,
6969 "WEXITSTATUS(status) -> integer\n\n\
6970 Return the process return code from 'status'.");
6972 static PyObject *
6973 posix_WEXITSTATUS(PyObject *self, PyObject *args)
6975 WAIT_TYPE status;
6976 WAIT_STATUS_INT(status) = 0;
6978 if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status)))
6979 return NULL;
6981 return Py_BuildValue("i", WEXITSTATUS(status));
6983 #endif /* WEXITSTATUS */
6985 #ifdef WTERMSIG
6986 PyDoc_STRVAR(posix_WTERMSIG__doc__,
6987 "WTERMSIG(status) -> integer\n\n\
6988 Return the signal that terminated the process that provided the 'status'\n\
6989 value.");
6991 static PyObject *
6992 posix_WTERMSIG(PyObject *self, PyObject *args)
6994 WAIT_TYPE status;
6995 WAIT_STATUS_INT(status) = 0;
6997 if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status)))
6998 return NULL;
7000 return Py_BuildValue("i", WTERMSIG(status));
7002 #endif /* WTERMSIG */
7004 #ifdef WSTOPSIG
7005 PyDoc_STRVAR(posix_WSTOPSIG__doc__,
7006 "WSTOPSIG(status) -> integer\n\n\
7007 Return the signal that stopped the process that provided\n\
7008 the 'status' value.");
7010 static PyObject *
7011 posix_WSTOPSIG(PyObject *self, PyObject *args)
7013 WAIT_TYPE status;
7014 WAIT_STATUS_INT(status) = 0;
7016 if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status)))
7017 return NULL;
7019 return Py_BuildValue("i", WSTOPSIG(status));
7021 #endif /* WSTOPSIG */
7023 #endif /* HAVE_SYS_WAIT_H */
7026 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
7027 #ifdef _SCO_DS
7028 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
7029 needed definitions in sys/statvfs.h */
7030 #define _SVID3
7031 #endif
7032 #include <sys/statvfs.h>
7034 static PyObject*
7035 _pystatvfs_fromstructstatvfs(struct statvfs st) {
7036 PyObject *v = PyStructSequence_New(&StatVFSResultType);
7037 if (v == NULL)
7038 return NULL;
7040 #if !defined(HAVE_LARGEFILE_SUPPORT)
7041 PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long) st.f_bsize));
7042 PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long) st.f_frsize));
7043 PyStructSequence_SET_ITEM(v, 2, PyInt_FromLong((long) st.f_blocks));
7044 PyStructSequence_SET_ITEM(v, 3, PyInt_FromLong((long) st.f_bfree));
7045 PyStructSequence_SET_ITEM(v, 4, PyInt_FromLong((long) st.f_bavail));
7046 PyStructSequence_SET_ITEM(v, 5, PyInt_FromLong((long) st.f_files));
7047 PyStructSequence_SET_ITEM(v, 6, PyInt_FromLong((long) st.f_ffree));
7048 PyStructSequence_SET_ITEM(v, 7, PyInt_FromLong((long) st.f_favail));
7049 PyStructSequence_SET_ITEM(v, 8, PyInt_FromLong((long) st.f_flag));
7050 PyStructSequence_SET_ITEM(v, 9, PyInt_FromLong((long) st.f_namemax));
7051 #else
7052 PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long) st.f_bsize));
7053 PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long) st.f_frsize));
7054 PyStructSequence_SET_ITEM(v, 2,
7055 PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks));
7056 PyStructSequence_SET_ITEM(v, 3,
7057 PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree));
7058 PyStructSequence_SET_ITEM(v, 4,
7059 PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail));
7060 PyStructSequence_SET_ITEM(v, 5,
7061 PyLong_FromLongLong((PY_LONG_LONG) st.f_files));
7062 PyStructSequence_SET_ITEM(v, 6,
7063 PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree));
7064 PyStructSequence_SET_ITEM(v, 7,
7065 PyLong_FromLongLong((PY_LONG_LONG) st.f_favail));
7066 PyStructSequence_SET_ITEM(v, 8, PyInt_FromLong((long) st.f_flag));
7067 PyStructSequence_SET_ITEM(v, 9, PyInt_FromLong((long) st.f_namemax));
7068 #endif
7070 return v;
7073 PyDoc_STRVAR(posix_fstatvfs__doc__,
7074 "fstatvfs(fd) -> statvfs result\n\n\
7075 Perform an fstatvfs system call on the given fd.");
7077 static PyObject *
7078 posix_fstatvfs(PyObject *self, PyObject *args)
7080 int fd, res;
7081 struct statvfs st;
7083 if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd))
7084 return NULL;
7085 Py_BEGIN_ALLOW_THREADS
7086 res = fstatvfs(fd, &st);
7087 Py_END_ALLOW_THREADS
7088 if (res != 0)
7089 return posix_error();
7091 return _pystatvfs_fromstructstatvfs(st);
7093 #endif /* HAVE_FSTATVFS && HAVE_SYS_STATVFS_H */
7096 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
7097 #include <sys/statvfs.h>
7099 PyDoc_STRVAR(posix_statvfs__doc__,
7100 "statvfs(path) -> statvfs result\n\n\
7101 Perform a statvfs system call on the given path.");
7103 static PyObject *
7104 posix_statvfs(PyObject *self, PyObject *args)
7106 char *path;
7107 int res;
7108 struct statvfs st;
7109 if (!PyArg_ParseTuple(args, "s:statvfs", &path))
7110 return NULL;
7111 Py_BEGIN_ALLOW_THREADS
7112 res = statvfs(path, &st);
7113 Py_END_ALLOW_THREADS
7114 if (res != 0)
7115 return posix_error_with_filename(path);
7117 return _pystatvfs_fromstructstatvfs(st);
7119 #endif /* HAVE_STATVFS */
7122 #ifdef HAVE_TEMPNAM
7123 PyDoc_STRVAR(posix_tempnam__doc__,
7124 "tempnam([dir[, prefix]]) -> string\n\n\
7125 Return a unique name for a temporary file.\n\
7126 The directory and a prefix may be specified as strings; they may be omitted\n\
7127 or None if not needed.");
7129 static PyObject *
7130 posix_tempnam(PyObject *self, PyObject *args)
7132 PyObject *result = NULL;
7133 char *dir = NULL;
7134 char *pfx = NULL;
7135 char *name;
7137 if (!PyArg_ParseTuple(args, "|zz:tempnam", &dir, &pfx))
7138 return NULL;
7140 if (PyErr_Warn(PyExc_RuntimeWarning,
7141 "tempnam is a potential security risk to your program") < 0)
7142 return NULL;
7144 #ifdef MS_WINDOWS
7145 name = _tempnam(dir, pfx);
7146 #else
7147 name = tempnam(dir, pfx);
7148 #endif
7149 if (name == NULL)
7150 return PyErr_NoMemory();
7151 result = PyString_FromString(name);
7152 free(name);
7153 return result;
7155 #endif
7158 #ifdef HAVE_TMPFILE
7159 PyDoc_STRVAR(posix_tmpfile__doc__,
7160 "tmpfile() -> file object\n\n\
7161 Create a temporary file with no directory entries.");
7163 static PyObject *
7164 posix_tmpfile(PyObject *self, PyObject *noargs)
7166 FILE *fp;
7168 fp = tmpfile();
7169 if (fp == NULL)
7170 return posix_error();
7171 return PyFile_FromFile(fp, "<tmpfile>", "w+b", fclose);
7173 #endif
7176 #ifdef HAVE_TMPNAM
7177 PyDoc_STRVAR(posix_tmpnam__doc__,
7178 "tmpnam() -> string\n\n\
7179 Return a unique name for a temporary file.");
7181 static PyObject *
7182 posix_tmpnam(PyObject *self, PyObject *noargs)
7184 char buffer[L_tmpnam];
7185 char *name;
7187 if (PyErr_Warn(PyExc_RuntimeWarning,
7188 "tmpnam is a potential security risk to your program") < 0)
7189 return NULL;
7191 #ifdef USE_TMPNAM_R
7192 name = tmpnam_r(buffer);
7193 #else
7194 name = tmpnam(buffer);
7195 #endif
7196 if (name == NULL) {
7197 PyObject *err = Py_BuildValue("is", 0,
7198 #ifdef USE_TMPNAM_R
7199 "unexpected NULL from tmpnam_r"
7200 #else
7201 "unexpected NULL from tmpnam"
7202 #endif
7204 PyErr_SetObject(PyExc_OSError, err);
7205 Py_XDECREF(err);
7206 return NULL;
7208 return PyString_FromString(buffer);
7210 #endif
7213 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
7214 * It maps strings representing configuration variable names to
7215 * integer values, allowing those functions to be called with the
7216 * magic names instead of polluting the module's namespace with tons of
7217 * rarely-used constants. There are three separate tables that use
7218 * these definitions.
7220 * This code is always included, even if none of the interfaces that
7221 * need it are included. The #if hackery needed to avoid it would be
7222 * sufficiently pervasive that it's not worth the loss of readability.
7224 struct constdef {
7225 char *name;
7226 long value;
7229 static int
7230 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
7231 size_t tablesize)
7233 if (PyInt_Check(arg)) {
7234 *valuep = PyInt_AS_LONG(arg);
7235 return 1;
7237 if (PyString_Check(arg)) {
7238 /* look up the value in the table using a binary search */
7239 size_t lo = 0;
7240 size_t mid;
7241 size_t hi = tablesize;
7242 int cmp;
7243 char *confname = PyString_AS_STRING(arg);
7244 while (lo < hi) {
7245 mid = (lo + hi) / 2;
7246 cmp = strcmp(confname, table[mid].name);
7247 if (cmp < 0)
7248 hi = mid;
7249 else if (cmp > 0)
7250 lo = mid + 1;
7251 else {
7252 *valuep = table[mid].value;
7253 return 1;
7256 PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
7258 else
7259 PyErr_SetString(PyExc_TypeError,
7260 "configuration names must be strings or integers");
7261 return 0;
7265 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
7266 static struct constdef posix_constants_pathconf[] = {
7267 #ifdef _PC_ABI_AIO_XFER_MAX
7268 {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX},
7269 #endif
7270 #ifdef _PC_ABI_ASYNC_IO
7271 {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
7272 #endif
7273 #ifdef _PC_ASYNC_IO
7274 {"PC_ASYNC_IO", _PC_ASYNC_IO},
7275 #endif
7276 #ifdef _PC_CHOWN_RESTRICTED
7277 {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED},
7278 #endif
7279 #ifdef _PC_FILESIZEBITS
7280 {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
7281 #endif
7282 #ifdef _PC_LAST
7283 {"PC_LAST", _PC_LAST},
7284 #endif
7285 #ifdef _PC_LINK_MAX
7286 {"PC_LINK_MAX", _PC_LINK_MAX},
7287 #endif
7288 #ifdef _PC_MAX_CANON
7289 {"PC_MAX_CANON", _PC_MAX_CANON},
7290 #endif
7291 #ifdef _PC_MAX_INPUT
7292 {"PC_MAX_INPUT", _PC_MAX_INPUT},
7293 #endif
7294 #ifdef _PC_NAME_MAX
7295 {"PC_NAME_MAX", _PC_NAME_MAX},
7296 #endif
7297 #ifdef _PC_NO_TRUNC
7298 {"PC_NO_TRUNC", _PC_NO_TRUNC},
7299 #endif
7300 #ifdef _PC_PATH_MAX
7301 {"PC_PATH_MAX", _PC_PATH_MAX},
7302 #endif
7303 #ifdef _PC_PIPE_BUF
7304 {"PC_PIPE_BUF", _PC_PIPE_BUF},
7305 #endif
7306 #ifdef _PC_PRIO_IO
7307 {"PC_PRIO_IO", _PC_PRIO_IO},
7308 #endif
7309 #ifdef _PC_SOCK_MAXBUF
7310 {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF},
7311 #endif
7312 #ifdef _PC_SYNC_IO
7313 {"PC_SYNC_IO", _PC_SYNC_IO},
7314 #endif
7315 #ifdef _PC_VDISABLE
7316 {"PC_VDISABLE", _PC_VDISABLE},
7317 #endif
7320 static int
7321 conv_path_confname(PyObject *arg, int *valuep)
7323 return conv_confname(arg, valuep, posix_constants_pathconf,
7324 sizeof(posix_constants_pathconf)
7325 / sizeof(struct constdef));
7327 #endif
7329 #ifdef HAVE_FPATHCONF
7330 PyDoc_STRVAR(posix_fpathconf__doc__,
7331 "fpathconf(fd, name) -> integer\n\n\
7332 Return the configuration limit name for the file descriptor fd.\n\
7333 If there is no limit, return -1.");
7335 static PyObject *
7336 posix_fpathconf(PyObject *self, PyObject *args)
7338 PyObject *result = NULL;
7339 int name, fd;
7341 if (PyArg_ParseTuple(args, "iO&:fpathconf", &fd,
7342 conv_path_confname, &name)) {
7343 long limit;
7345 errno = 0;
7346 limit = fpathconf(fd, name);
7347 if (limit == -1 && errno != 0)
7348 posix_error();
7349 else
7350 result = PyInt_FromLong(limit);
7352 return result;
7354 #endif
7357 #ifdef HAVE_PATHCONF
7358 PyDoc_STRVAR(posix_pathconf__doc__,
7359 "pathconf(path, name) -> integer\n\n\
7360 Return the configuration limit name for the file or directory path.\n\
7361 If there is no limit, return -1.");
7363 static PyObject *
7364 posix_pathconf(PyObject *self, PyObject *args)
7366 PyObject *result = NULL;
7367 int name;
7368 char *path;
7370 if (PyArg_ParseTuple(args, "sO&:pathconf", &path,
7371 conv_path_confname, &name)) {
7372 long limit;
7374 errno = 0;
7375 limit = pathconf(path, name);
7376 if (limit == -1 && errno != 0) {
7377 if (errno == EINVAL)
7378 /* could be a path or name problem */
7379 posix_error();
7380 else
7381 posix_error_with_filename(path);
7383 else
7384 result = PyInt_FromLong(limit);
7386 return result;
7388 #endif
7390 #ifdef HAVE_CONFSTR
7391 static struct constdef posix_constants_confstr[] = {
7392 #ifdef _CS_ARCHITECTURE
7393 {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
7394 #endif
7395 #ifdef _CS_HOSTNAME
7396 {"CS_HOSTNAME", _CS_HOSTNAME},
7397 #endif
7398 #ifdef _CS_HW_PROVIDER
7399 {"CS_HW_PROVIDER", _CS_HW_PROVIDER},
7400 #endif
7401 #ifdef _CS_HW_SERIAL
7402 {"CS_HW_SERIAL", _CS_HW_SERIAL},
7403 #endif
7404 #ifdef _CS_INITTAB_NAME
7405 {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
7406 #endif
7407 #ifdef _CS_LFS64_CFLAGS
7408 {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
7409 #endif
7410 #ifdef _CS_LFS64_LDFLAGS
7411 {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS},
7412 #endif
7413 #ifdef _CS_LFS64_LIBS
7414 {"CS_LFS64_LIBS", _CS_LFS64_LIBS},
7415 #endif
7416 #ifdef _CS_LFS64_LINTFLAGS
7417 {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS},
7418 #endif
7419 #ifdef _CS_LFS_CFLAGS
7420 {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS},
7421 #endif
7422 #ifdef _CS_LFS_LDFLAGS
7423 {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS},
7424 #endif
7425 #ifdef _CS_LFS_LIBS
7426 {"CS_LFS_LIBS", _CS_LFS_LIBS},
7427 #endif
7428 #ifdef _CS_LFS_LINTFLAGS
7429 {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS},
7430 #endif
7431 #ifdef _CS_MACHINE
7432 {"CS_MACHINE", _CS_MACHINE},
7433 #endif
7434 #ifdef _CS_PATH
7435 {"CS_PATH", _CS_PATH},
7436 #endif
7437 #ifdef _CS_RELEASE
7438 {"CS_RELEASE", _CS_RELEASE},
7439 #endif
7440 #ifdef _CS_SRPC_DOMAIN
7441 {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN},
7442 #endif
7443 #ifdef _CS_SYSNAME
7444 {"CS_SYSNAME", _CS_SYSNAME},
7445 #endif
7446 #ifdef _CS_VERSION
7447 {"CS_VERSION", _CS_VERSION},
7448 #endif
7449 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
7450 {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS},
7451 #endif
7452 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
7453 {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS},
7454 #endif
7455 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
7456 {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS},
7457 #endif
7458 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
7459 {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS},
7460 #endif
7461 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
7462 {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS},
7463 #endif
7464 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
7465 {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
7466 #endif
7467 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
7468 {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS},
7469 #endif
7470 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
7471 {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
7472 #endif
7473 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
7474 {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS},
7475 #endif
7476 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
7477 {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS},
7478 #endif
7479 #ifdef _CS_XBS5_LP64_OFF64_LIBS
7480 {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
7481 #endif
7482 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
7483 {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS},
7484 #endif
7485 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
7486 {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
7487 #endif
7488 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
7489 {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
7490 #endif
7491 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
7492 {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS},
7493 #endif
7494 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
7495 {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
7496 #endif
7497 #ifdef _MIPS_CS_AVAIL_PROCESSORS
7498 {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS},
7499 #endif
7500 #ifdef _MIPS_CS_BASE
7501 {"MIPS_CS_BASE", _MIPS_CS_BASE},
7502 #endif
7503 #ifdef _MIPS_CS_HOSTID
7504 {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID},
7505 #endif
7506 #ifdef _MIPS_CS_HW_NAME
7507 {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
7508 #endif
7509 #ifdef _MIPS_CS_NUM_PROCESSORS
7510 {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS},
7511 #endif
7512 #ifdef _MIPS_CS_OSREL_MAJ
7513 {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ},
7514 #endif
7515 #ifdef _MIPS_CS_OSREL_MIN
7516 {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN},
7517 #endif
7518 #ifdef _MIPS_CS_OSREL_PATCH
7519 {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH},
7520 #endif
7521 #ifdef _MIPS_CS_OS_NAME
7522 {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
7523 #endif
7524 #ifdef _MIPS_CS_OS_PROVIDER
7525 {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER},
7526 #endif
7527 #ifdef _MIPS_CS_PROCESSORS
7528 {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS},
7529 #endif
7530 #ifdef _MIPS_CS_SERIAL
7531 {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL},
7532 #endif
7533 #ifdef _MIPS_CS_VENDOR
7534 {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR},
7535 #endif
7538 static int
7539 conv_confstr_confname(PyObject *arg, int *valuep)
7541 return conv_confname(arg, valuep, posix_constants_confstr,
7542 sizeof(posix_constants_confstr)
7543 / sizeof(struct constdef));
7546 PyDoc_STRVAR(posix_confstr__doc__,
7547 "confstr(name) -> string\n\n\
7548 Return a string-valued system configuration variable.");
7550 static PyObject *
7551 posix_confstr(PyObject *self, PyObject *args)
7553 PyObject *result = NULL;
7554 int name;
7555 char buffer[256];
7557 if (PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name)) {
7558 int len;
7560 errno = 0;
7561 len = confstr(name, buffer, sizeof(buffer));
7562 if (len == 0) {
7563 if (errno) {
7564 posix_error();
7566 else {
7567 result = Py_None;
7568 Py_INCREF(Py_None);
7571 else {
7572 if ((unsigned int)len >= sizeof(buffer)) {
7573 result = PyString_FromStringAndSize(NULL, len-1);
7574 if (result != NULL)
7575 confstr(name, PyString_AS_STRING(result), len);
7577 else
7578 result = PyString_FromStringAndSize(buffer, len-1);
7581 return result;
7583 #endif
7586 #ifdef HAVE_SYSCONF
7587 static struct constdef posix_constants_sysconf[] = {
7588 #ifdef _SC_2_CHAR_TERM
7589 {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM},
7590 #endif
7591 #ifdef _SC_2_C_BIND
7592 {"SC_2_C_BIND", _SC_2_C_BIND},
7593 #endif
7594 #ifdef _SC_2_C_DEV
7595 {"SC_2_C_DEV", _SC_2_C_DEV},
7596 #endif
7597 #ifdef _SC_2_C_VERSION
7598 {"SC_2_C_VERSION", _SC_2_C_VERSION},
7599 #endif
7600 #ifdef _SC_2_FORT_DEV
7601 {"SC_2_FORT_DEV", _SC_2_FORT_DEV},
7602 #endif
7603 #ifdef _SC_2_FORT_RUN
7604 {"SC_2_FORT_RUN", _SC_2_FORT_RUN},
7605 #endif
7606 #ifdef _SC_2_LOCALEDEF
7607 {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF},
7608 #endif
7609 #ifdef _SC_2_SW_DEV
7610 {"SC_2_SW_DEV", _SC_2_SW_DEV},
7611 #endif
7612 #ifdef _SC_2_UPE
7613 {"SC_2_UPE", _SC_2_UPE},
7614 #endif
7615 #ifdef _SC_2_VERSION
7616 {"SC_2_VERSION", _SC_2_VERSION},
7617 #endif
7618 #ifdef _SC_ABI_ASYNCHRONOUS_IO
7619 {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO},
7620 #endif
7621 #ifdef _SC_ACL
7622 {"SC_ACL", _SC_ACL},
7623 #endif
7624 #ifdef _SC_AIO_LISTIO_MAX
7625 {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX},
7626 #endif
7627 #ifdef _SC_AIO_MAX
7628 {"SC_AIO_MAX", _SC_AIO_MAX},
7629 #endif
7630 #ifdef _SC_AIO_PRIO_DELTA_MAX
7631 {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX},
7632 #endif
7633 #ifdef _SC_ARG_MAX
7634 {"SC_ARG_MAX", _SC_ARG_MAX},
7635 #endif
7636 #ifdef _SC_ASYNCHRONOUS_IO
7637 {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO},
7638 #endif
7639 #ifdef _SC_ATEXIT_MAX
7640 {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX},
7641 #endif
7642 #ifdef _SC_AUDIT
7643 {"SC_AUDIT", _SC_AUDIT},
7644 #endif
7645 #ifdef _SC_AVPHYS_PAGES
7646 {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
7647 #endif
7648 #ifdef _SC_BC_BASE_MAX
7649 {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX},
7650 #endif
7651 #ifdef _SC_BC_DIM_MAX
7652 {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX},
7653 #endif
7654 #ifdef _SC_BC_SCALE_MAX
7655 {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
7656 #endif
7657 #ifdef _SC_BC_STRING_MAX
7658 {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX},
7659 #endif
7660 #ifdef _SC_CAP
7661 {"SC_CAP", _SC_CAP},
7662 #endif
7663 #ifdef _SC_CHARCLASS_NAME_MAX
7664 {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX},
7665 #endif
7666 #ifdef _SC_CHAR_BIT
7667 {"SC_CHAR_BIT", _SC_CHAR_BIT},
7668 #endif
7669 #ifdef _SC_CHAR_MAX
7670 {"SC_CHAR_MAX", _SC_CHAR_MAX},
7671 #endif
7672 #ifdef _SC_CHAR_MIN
7673 {"SC_CHAR_MIN", _SC_CHAR_MIN},
7674 #endif
7675 #ifdef _SC_CHILD_MAX
7676 {"SC_CHILD_MAX", _SC_CHILD_MAX},
7677 #endif
7678 #ifdef _SC_CLK_TCK
7679 {"SC_CLK_TCK", _SC_CLK_TCK},
7680 #endif
7681 #ifdef _SC_COHER_BLKSZ
7682 {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ},
7683 #endif
7684 #ifdef _SC_COLL_WEIGHTS_MAX
7685 {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX},
7686 #endif
7687 #ifdef _SC_DCACHE_ASSOC
7688 {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
7689 #endif
7690 #ifdef _SC_DCACHE_BLKSZ
7691 {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
7692 #endif
7693 #ifdef _SC_DCACHE_LINESZ
7694 {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ},
7695 #endif
7696 #ifdef _SC_DCACHE_SZ
7697 {"SC_DCACHE_SZ", _SC_DCACHE_SZ},
7698 #endif
7699 #ifdef _SC_DCACHE_TBLKSZ
7700 {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ},
7701 #endif
7702 #ifdef _SC_DELAYTIMER_MAX
7703 {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX},
7704 #endif
7705 #ifdef _SC_EQUIV_CLASS_MAX
7706 {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX},
7707 #endif
7708 #ifdef _SC_EXPR_NEST_MAX
7709 {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX},
7710 #endif
7711 #ifdef _SC_FSYNC
7712 {"SC_FSYNC", _SC_FSYNC},
7713 #endif
7714 #ifdef _SC_GETGR_R_SIZE_MAX
7715 {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX},
7716 #endif
7717 #ifdef _SC_GETPW_R_SIZE_MAX
7718 {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX},
7719 #endif
7720 #ifdef _SC_ICACHE_ASSOC
7721 {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
7722 #endif
7723 #ifdef _SC_ICACHE_BLKSZ
7724 {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
7725 #endif
7726 #ifdef _SC_ICACHE_LINESZ
7727 {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ},
7728 #endif
7729 #ifdef _SC_ICACHE_SZ
7730 {"SC_ICACHE_SZ", _SC_ICACHE_SZ},
7731 #endif
7732 #ifdef _SC_INF
7733 {"SC_INF", _SC_INF},
7734 #endif
7735 #ifdef _SC_INT_MAX
7736 {"SC_INT_MAX", _SC_INT_MAX},
7737 #endif
7738 #ifdef _SC_INT_MIN
7739 {"SC_INT_MIN", _SC_INT_MIN},
7740 #endif
7741 #ifdef _SC_IOV_MAX
7742 {"SC_IOV_MAX", _SC_IOV_MAX},
7743 #endif
7744 #ifdef _SC_IP_SECOPTS
7745 {"SC_IP_SECOPTS", _SC_IP_SECOPTS},
7746 #endif
7747 #ifdef _SC_JOB_CONTROL
7748 {"SC_JOB_CONTROL", _SC_JOB_CONTROL},
7749 #endif
7750 #ifdef _SC_KERN_POINTERS
7751 {"SC_KERN_POINTERS", _SC_KERN_POINTERS},
7752 #endif
7753 #ifdef _SC_KERN_SIM
7754 {"SC_KERN_SIM", _SC_KERN_SIM},
7755 #endif
7756 #ifdef _SC_LINE_MAX
7757 {"SC_LINE_MAX", _SC_LINE_MAX},
7758 #endif
7759 #ifdef _SC_LOGIN_NAME_MAX
7760 {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX},
7761 #endif
7762 #ifdef _SC_LOGNAME_MAX
7763 {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX},
7764 #endif
7765 #ifdef _SC_LONG_BIT
7766 {"SC_LONG_BIT", _SC_LONG_BIT},
7767 #endif
7768 #ifdef _SC_MAC
7769 {"SC_MAC", _SC_MAC},
7770 #endif
7771 #ifdef _SC_MAPPED_FILES
7772 {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
7773 #endif
7774 #ifdef _SC_MAXPID
7775 {"SC_MAXPID", _SC_MAXPID},
7776 #endif
7777 #ifdef _SC_MB_LEN_MAX
7778 {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX},
7779 #endif
7780 #ifdef _SC_MEMLOCK
7781 {"SC_MEMLOCK", _SC_MEMLOCK},
7782 #endif
7783 #ifdef _SC_MEMLOCK_RANGE
7784 {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE},
7785 #endif
7786 #ifdef _SC_MEMORY_PROTECTION
7787 {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION},
7788 #endif
7789 #ifdef _SC_MESSAGE_PASSING
7790 {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING},
7791 #endif
7792 #ifdef _SC_MMAP_FIXED_ALIGNMENT
7793 {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
7794 #endif
7795 #ifdef _SC_MQ_OPEN_MAX
7796 {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX},
7797 #endif
7798 #ifdef _SC_MQ_PRIO_MAX
7799 {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX},
7800 #endif
7801 #ifdef _SC_NACLS_MAX
7802 {"SC_NACLS_MAX", _SC_NACLS_MAX},
7803 #endif
7804 #ifdef _SC_NGROUPS_MAX
7805 {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX},
7806 #endif
7807 #ifdef _SC_NL_ARGMAX
7808 {"SC_NL_ARGMAX", _SC_NL_ARGMAX},
7809 #endif
7810 #ifdef _SC_NL_LANGMAX
7811 {"SC_NL_LANGMAX", _SC_NL_LANGMAX},
7812 #endif
7813 #ifdef _SC_NL_MSGMAX
7814 {"SC_NL_MSGMAX", _SC_NL_MSGMAX},
7815 #endif
7816 #ifdef _SC_NL_NMAX
7817 {"SC_NL_NMAX", _SC_NL_NMAX},
7818 #endif
7819 #ifdef _SC_NL_SETMAX
7820 {"SC_NL_SETMAX", _SC_NL_SETMAX},
7821 #endif
7822 #ifdef _SC_NL_TEXTMAX
7823 {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX},
7824 #endif
7825 #ifdef _SC_NPROCESSORS_CONF
7826 {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF},
7827 #endif
7828 #ifdef _SC_NPROCESSORS_ONLN
7829 {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN},
7830 #endif
7831 #ifdef _SC_NPROC_CONF
7832 {"SC_NPROC_CONF", _SC_NPROC_CONF},
7833 #endif
7834 #ifdef _SC_NPROC_ONLN
7835 {"SC_NPROC_ONLN", _SC_NPROC_ONLN},
7836 #endif
7837 #ifdef _SC_NZERO
7838 {"SC_NZERO", _SC_NZERO},
7839 #endif
7840 #ifdef _SC_OPEN_MAX
7841 {"SC_OPEN_MAX", _SC_OPEN_MAX},
7842 #endif
7843 #ifdef _SC_PAGESIZE
7844 {"SC_PAGESIZE", _SC_PAGESIZE},
7845 #endif
7846 #ifdef _SC_PAGE_SIZE
7847 {"SC_PAGE_SIZE", _SC_PAGE_SIZE},
7848 #endif
7849 #ifdef _SC_PASS_MAX
7850 {"SC_PASS_MAX", _SC_PASS_MAX},
7851 #endif
7852 #ifdef _SC_PHYS_PAGES
7853 {"SC_PHYS_PAGES", _SC_PHYS_PAGES},
7854 #endif
7855 #ifdef _SC_PII
7856 {"SC_PII", _SC_PII},
7857 #endif
7858 #ifdef _SC_PII_INTERNET
7859 {"SC_PII_INTERNET", _SC_PII_INTERNET},
7860 #endif
7861 #ifdef _SC_PII_INTERNET_DGRAM
7862 {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM},
7863 #endif
7864 #ifdef _SC_PII_INTERNET_STREAM
7865 {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM},
7866 #endif
7867 #ifdef _SC_PII_OSI
7868 {"SC_PII_OSI", _SC_PII_OSI},
7869 #endif
7870 #ifdef _SC_PII_OSI_CLTS
7871 {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
7872 #endif
7873 #ifdef _SC_PII_OSI_COTS
7874 {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
7875 #endif
7876 #ifdef _SC_PII_OSI_M
7877 {"SC_PII_OSI_M", _SC_PII_OSI_M},
7878 #endif
7879 #ifdef _SC_PII_SOCKET
7880 {"SC_PII_SOCKET", _SC_PII_SOCKET},
7881 #endif
7882 #ifdef _SC_PII_XTI
7883 {"SC_PII_XTI", _SC_PII_XTI},
7884 #endif
7885 #ifdef _SC_POLL
7886 {"SC_POLL", _SC_POLL},
7887 #endif
7888 #ifdef _SC_PRIORITIZED_IO
7889 {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO},
7890 #endif
7891 #ifdef _SC_PRIORITY_SCHEDULING
7892 {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING},
7893 #endif
7894 #ifdef _SC_REALTIME_SIGNALS
7895 {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS},
7896 #endif
7897 #ifdef _SC_RE_DUP_MAX
7898 {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX},
7899 #endif
7900 #ifdef _SC_RTSIG_MAX
7901 {"SC_RTSIG_MAX", _SC_RTSIG_MAX},
7902 #endif
7903 #ifdef _SC_SAVED_IDS
7904 {"SC_SAVED_IDS", _SC_SAVED_IDS},
7905 #endif
7906 #ifdef _SC_SCHAR_MAX
7907 {"SC_SCHAR_MAX", _SC_SCHAR_MAX},
7908 #endif
7909 #ifdef _SC_SCHAR_MIN
7910 {"SC_SCHAR_MIN", _SC_SCHAR_MIN},
7911 #endif
7912 #ifdef _SC_SELECT
7913 {"SC_SELECT", _SC_SELECT},
7914 #endif
7915 #ifdef _SC_SEMAPHORES
7916 {"SC_SEMAPHORES", _SC_SEMAPHORES},
7917 #endif
7918 #ifdef _SC_SEM_NSEMS_MAX
7919 {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX},
7920 #endif
7921 #ifdef _SC_SEM_VALUE_MAX
7922 {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX},
7923 #endif
7924 #ifdef _SC_SHARED_MEMORY_OBJECTS
7925 {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS},
7926 #endif
7927 #ifdef _SC_SHRT_MAX
7928 {"SC_SHRT_MAX", _SC_SHRT_MAX},
7929 #endif
7930 #ifdef _SC_SHRT_MIN
7931 {"SC_SHRT_MIN", _SC_SHRT_MIN},
7932 #endif
7933 #ifdef _SC_SIGQUEUE_MAX
7934 {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
7935 #endif
7936 #ifdef _SC_SIGRT_MAX
7937 {"SC_SIGRT_MAX", _SC_SIGRT_MAX},
7938 #endif
7939 #ifdef _SC_SIGRT_MIN
7940 {"SC_SIGRT_MIN", _SC_SIGRT_MIN},
7941 #endif
7942 #ifdef _SC_SOFTPOWER
7943 {"SC_SOFTPOWER", _SC_SOFTPOWER},
7944 #endif
7945 #ifdef _SC_SPLIT_CACHE
7946 {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE},
7947 #endif
7948 #ifdef _SC_SSIZE_MAX
7949 {"SC_SSIZE_MAX", _SC_SSIZE_MAX},
7950 #endif
7951 #ifdef _SC_STACK_PROT
7952 {"SC_STACK_PROT", _SC_STACK_PROT},
7953 #endif
7954 #ifdef _SC_STREAM_MAX
7955 {"SC_STREAM_MAX", _SC_STREAM_MAX},
7956 #endif
7957 #ifdef _SC_SYNCHRONIZED_IO
7958 {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO},
7959 #endif
7960 #ifdef _SC_THREADS
7961 {"SC_THREADS", _SC_THREADS},
7962 #endif
7963 #ifdef _SC_THREAD_ATTR_STACKADDR
7964 {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR},
7965 #endif
7966 #ifdef _SC_THREAD_ATTR_STACKSIZE
7967 {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE},
7968 #endif
7969 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
7970 {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
7971 #endif
7972 #ifdef _SC_THREAD_KEYS_MAX
7973 {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX},
7974 #endif
7975 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
7976 {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING},
7977 #endif
7978 #ifdef _SC_THREAD_PRIO_INHERIT
7979 {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT},
7980 #endif
7981 #ifdef _SC_THREAD_PRIO_PROTECT
7982 {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT},
7983 #endif
7984 #ifdef _SC_THREAD_PROCESS_SHARED
7985 {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED},
7986 #endif
7987 #ifdef _SC_THREAD_SAFE_FUNCTIONS
7988 {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS},
7989 #endif
7990 #ifdef _SC_THREAD_STACK_MIN
7991 {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN},
7992 #endif
7993 #ifdef _SC_THREAD_THREADS_MAX
7994 {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX},
7995 #endif
7996 #ifdef _SC_TIMERS
7997 {"SC_TIMERS", _SC_TIMERS},
7998 #endif
7999 #ifdef _SC_TIMER_MAX
8000 {"SC_TIMER_MAX", _SC_TIMER_MAX},
8001 #endif
8002 #ifdef _SC_TTY_NAME_MAX
8003 {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
8004 #endif
8005 #ifdef _SC_TZNAME_MAX
8006 {"SC_TZNAME_MAX", _SC_TZNAME_MAX},
8007 #endif
8008 #ifdef _SC_T_IOV_MAX
8009 {"SC_T_IOV_MAX", _SC_T_IOV_MAX},
8010 #endif
8011 #ifdef _SC_UCHAR_MAX
8012 {"SC_UCHAR_MAX", _SC_UCHAR_MAX},
8013 #endif
8014 #ifdef _SC_UINT_MAX
8015 {"SC_UINT_MAX", _SC_UINT_MAX},
8016 #endif
8017 #ifdef _SC_UIO_MAXIOV
8018 {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV},
8019 #endif
8020 #ifdef _SC_ULONG_MAX
8021 {"SC_ULONG_MAX", _SC_ULONG_MAX},
8022 #endif
8023 #ifdef _SC_USHRT_MAX
8024 {"SC_USHRT_MAX", _SC_USHRT_MAX},
8025 #endif
8026 #ifdef _SC_VERSION
8027 {"SC_VERSION", _SC_VERSION},
8028 #endif
8029 #ifdef _SC_WORD_BIT
8030 {"SC_WORD_BIT", _SC_WORD_BIT},
8031 #endif
8032 #ifdef _SC_XBS5_ILP32_OFF32
8033 {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32},
8034 #endif
8035 #ifdef _SC_XBS5_ILP32_OFFBIG
8036 {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG},
8037 #endif
8038 #ifdef _SC_XBS5_LP64_OFF64
8039 {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64},
8040 #endif
8041 #ifdef _SC_XBS5_LPBIG_OFFBIG
8042 {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG},
8043 #endif
8044 #ifdef _SC_XOPEN_CRYPT
8045 {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT},
8046 #endif
8047 #ifdef _SC_XOPEN_ENH_I18N
8048 {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N},
8049 #endif
8050 #ifdef _SC_XOPEN_LEGACY
8051 {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
8052 #endif
8053 #ifdef _SC_XOPEN_REALTIME
8054 {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME},
8055 #endif
8056 #ifdef _SC_XOPEN_REALTIME_THREADS
8057 {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS},
8058 #endif
8059 #ifdef _SC_XOPEN_SHM
8060 {"SC_XOPEN_SHM", _SC_XOPEN_SHM},
8061 #endif
8062 #ifdef _SC_XOPEN_UNIX
8063 {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX},
8064 #endif
8065 #ifdef _SC_XOPEN_VERSION
8066 {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION},
8067 #endif
8068 #ifdef _SC_XOPEN_XCU_VERSION
8069 {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION},
8070 #endif
8071 #ifdef _SC_XOPEN_XPG2
8072 {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2},
8073 #endif
8074 #ifdef _SC_XOPEN_XPG3
8075 {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3},
8076 #endif
8077 #ifdef _SC_XOPEN_XPG4
8078 {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4},
8079 #endif
8082 static int
8083 conv_sysconf_confname(PyObject *arg, int *valuep)
8085 return conv_confname(arg, valuep, posix_constants_sysconf,
8086 sizeof(posix_constants_sysconf)
8087 / sizeof(struct constdef));
8090 PyDoc_STRVAR(posix_sysconf__doc__,
8091 "sysconf(name) -> integer\n\n\
8092 Return an integer-valued system configuration variable.");
8094 static PyObject *
8095 posix_sysconf(PyObject *self, PyObject *args)
8097 PyObject *result = NULL;
8098 int name;
8100 if (PyArg_ParseTuple(args, "O&:sysconf", conv_sysconf_confname, &name)) {
8101 int value;
8103 errno = 0;
8104 value = sysconf(name);
8105 if (value == -1 && errno != 0)
8106 posix_error();
8107 else
8108 result = PyInt_FromLong(value);
8110 return result;
8112 #endif
8115 /* This code is used to ensure that the tables of configuration value names
8116 * are in sorted order as required by conv_confname(), and also to build the
8117 * the exported dictionaries that are used to publish information about the
8118 * names available on the host platform.
8120 * Sorting the table at runtime ensures that the table is properly ordered
8121 * when used, even for platforms we're not able to test on. It also makes
8122 * it easier to add additional entries to the tables.
8125 static int
8126 cmp_constdefs(const void *v1, const void *v2)
8128 const struct constdef *c1 =
8129 (const struct constdef *) v1;
8130 const struct constdef *c2 =
8131 (const struct constdef *) v2;
8133 return strcmp(c1->name, c2->name);
8136 static int
8137 setup_confname_table(struct constdef *table, size_t tablesize,
8138 char *tablename, PyObject *module)
8140 PyObject *d = NULL;
8141 size_t i;
8143 qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
8144 d = PyDict_New();
8145 if (d == NULL)
8146 return -1;
8148 for (i=0; i < tablesize; ++i) {
8149 PyObject *o = PyInt_FromLong(table[i].value);
8150 if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
8151 Py_XDECREF(o);
8152 Py_DECREF(d);
8153 return -1;
8155 Py_DECREF(o);
8157 return PyModule_AddObject(module, tablename, d);
8160 /* Return -1 on failure, 0 on success. */
8161 static int
8162 setup_confname_tables(PyObject *module)
8164 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
8165 if (setup_confname_table(posix_constants_pathconf,
8166 sizeof(posix_constants_pathconf)
8167 / sizeof(struct constdef),
8168 "pathconf_names", module))
8169 return -1;
8170 #endif
8171 #ifdef HAVE_CONFSTR
8172 if (setup_confname_table(posix_constants_confstr,
8173 sizeof(posix_constants_confstr)
8174 / sizeof(struct constdef),
8175 "confstr_names", module))
8176 return -1;
8177 #endif
8178 #ifdef HAVE_SYSCONF
8179 if (setup_confname_table(posix_constants_sysconf,
8180 sizeof(posix_constants_sysconf)
8181 / sizeof(struct constdef),
8182 "sysconf_names", module))
8183 return -1;
8184 #endif
8185 return 0;
8189 PyDoc_STRVAR(posix_abort__doc__,
8190 "abort() -> does not return!\n\n\
8191 Abort the interpreter immediately. This 'dumps core' or otherwise fails\n\
8192 in the hardest way possible on the hosting operating system.");
8194 static PyObject *
8195 posix_abort(PyObject *self, PyObject *noargs)
8197 abort();
8198 /*NOTREACHED*/
8199 Py_FatalError("abort() called from Python code didn't abort!");
8200 return NULL;
8203 #ifdef MS_WINDOWS
8204 PyDoc_STRVAR(win32_startfile__doc__,
8205 "startfile(filepath [, operation]) - Start a file with its associated\n\
8206 application.\n\
8208 When \"operation\" is not specified or \"open\", this acts like\n\
8209 double-clicking the file in Explorer, or giving the file name as an\n\
8210 argument to the DOS \"start\" command: the file is opened with whatever\n\
8211 application (if any) its extension is associated.\n\
8212 When another \"operation\" is given, it specifies what should be done with\n\
8213 the file. A typical operation is \"print\".\n\
8215 startfile returns as soon as the associated application is launched.\n\
8216 There is no option to wait for the application to close, and no way\n\
8217 to retrieve the application's exit status.\n\
8219 The filepath is relative to the current directory. If you want to use\n\
8220 an absolute path, make sure the first character is not a slash (\"/\");\n\
8221 the underlying Win32 ShellExecute function doesn't work if it is.");
8223 static PyObject *
8224 win32_startfile(PyObject *self, PyObject *args)
8226 char *filepath;
8227 char *operation = NULL;
8228 HINSTANCE rc;
8230 PyObject *unipath, *woperation = NULL;
8231 if (!PyArg_ParseTuple(args, "U|s:startfile",
8232 &unipath, &operation)) {
8233 PyErr_Clear();
8234 goto normal;
8237 if (operation) {
8238 woperation = PyUnicode_DecodeASCII(operation,
8239 strlen(operation), NULL);
8240 if (!woperation) {
8241 PyErr_Clear();
8242 operation = NULL;
8243 goto normal;
8247 Py_BEGIN_ALLOW_THREADS
8248 rc = ShellExecuteW((HWND)0, woperation ? PyUnicode_AS_UNICODE(woperation) : 0,
8249 PyUnicode_AS_UNICODE(unipath),
8250 NULL, NULL, SW_SHOWNORMAL);
8251 Py_END_ALLOW_THREADS
8253 Py_XDECREF(woperation);
8254 if (rc <= (HINSTANCE)32) {
8255 PyObject *errval = win32_error_unicode("startfile",
8256 PyUnicode_AS_UNICODE(unipath));
8257 return errval;
8259 Py_INCREF(Py_None);
8260 return Py_None;
8262 normal:
8263 if (!PyArg_ParseTuple(args, "et|s:startfile",
8264 Py_FileSystemDefaultEncoding, &filepath,
8265 &operation))
8266 return NULL;
8267 Py_BEGIN_ALLOW_THREADS
8268 rc = ShellExecute((HWND)0, operation, filepath,
8269 NULL, NULL, SW_SHOWNORMAL);
8270 Py_END_ALLOW_THREADS
8271 if (rc <= (HINSTANCE)32) {
8272 PyObject *errval = win32_error("startfile", filepath);
8273 PyMem_Free(filepath);
8274 return errval;
8276 PyMem_Free(filepath);
8277 Py_INCREF(Py_None);
8278 return Py_None;
8280 #endif /* MS_WINDOWS */
8282 #ifdef HAVE_GETLOADAVG
8283 PyDoc_STRVAR(posix_getloadavg__doc__,
8284 "getloadavg() -> (float, float, float)\n\n\
8285 Return the number of processes in the system run queue averaged over\n\
8286 the last 1, 5, and 15 minutes or raises OSError if the load average\n\
8287 was unobtainable");
8289 static PyObject *
8290 posix_getloadavg(PyObject *self, PyObject *noargs)
8292 double loadavg[3];
8293 if (getloadavg(loadavg, 3)!=3) {
8294 PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
8295 return NULL;
8296 } else
8297 return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
8299 #endif
8301 #ifdef MS_WINDOWS
8303 PyDoc_STRVAR(win32_urandom__doc__,
8304 "urandom(n) -> str\n\n\
8305 Return a string of n random bytes suitable for cryptographic use.");
8307 typedef BOOL (WINAPI *CRYPTACQUIRECONTEXTA)(HCRYPTPROV *phProv,\
8308 LPCSTR pszContainer, LPCSTR pszProvider, DWORD dwProvType,\
8309 DWORD dwFlags );
8310 typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen,\
8311 BYTE *pbBuffer );
8313 static CRYPTGENRANDOM pCryptGenRandom = NULL;
8314 /* This handle is never explicitly released. Instead, the operating
8315 system will release it when the process terminates. */
8316 static HCRYPTPROV hCryptProv = 0;
8318 static PyObject*
8319 win32_urandom(PyObject *self, PyObject *args)
8321 int howMany;
8322 PyObject* result;
8324 /* Read arguments */
8325 if (! PyArg_ParseTuple(args, "i:urandom", &howMany))
8326 return NULL;
8327 if (howMany < 0)
8328 return PyErr_Format(PyExc_ValueError,
8329 "negative argument not allowed");
8331 if (hCryptProv == 0) {
8332 HINSTANCE hAdvAPI32 = NULL;
8333 CRYPTACQUIRECONTEXTA pCryptAcquireContext = NULL;
8335 /* Obtain handle to the DLL containing CryptoAPI
8336 This should not fail */
8337 hAdvAPI32 = GetModuleHandle("advapi32.dll");
8338 if(hAdvAPI32 == NULL)
8339 return win32_error("GetModuleHandle", NULL);
8341 /* Obtain pointers to the CryptoAPI functions
8342 This will fail on some early versions of Win95 */
8343 pCryptAcquireContext = (CRYPTACQUIRECONTEXTA)GetProcAddress(
8344 hAdvAPI32,
8345 "CryptAcquireContextA");
8346 if (pCryptAcquireContext == NULL)
8347 return PyErr_Format(PyExc_NotImplementedError,
8348 "CryptAcquireContextA not found");
8350 pCryptGenRandom = (CRYPTGENRANDOM)GetProcAddress(
8351 hAdvAPI32, "CryptGenRandom");
8352 if (pCryptGenRandom == NULL)
8353 return PyErr_Format(PyExc_NotImplementedError,
8354 "CryptGenRandom not found");
8356 /* Acquire context */
8357 if (! pCryptAcquireContext(&hCryptProv, NULL, NULL,
8358 PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
8359 return win32_error("CryptAcquireContext", NULL);
8362 /* Allocate bytes */
8363 result = PyString_FromStringAndSize(NULL, howMany);
8364 if (result != NULL) {
8365 /* Get random data */
8366 memset(PyString_AS_STRING(result), 0, howMany); /* zero seed */
8367 if (! pCryptGenRandom(hCryptProv, howMany, (unsigned char*)
8368 PyString_AS_STRING(result))) {
8369 Py_DECREF(result);
8370 return win32_error("CryptGenRandom", NULL);
8373 return result;
8375 #endif
8377 #ifdef __VMS
8378 /* Use openssl random routine */
8379 #include <openssl/rand.h>
8380 PyDoc_STRVAR(vms_urandom__doc__,
8381 "urandom(n) -> str\n\n\
8382 Return a string of n random bytes suitable for cryptographic use.");
8384 static PyObject*
8385 vms_urandom(PyObject *self, PyObject *args)
8387 int howMany;
8388 PyObject* result;
8390 /* Read arguments */
8391 if (! PyArg_ParseTuple(args, "i:urandom", &howMany))
8392 return NULL;
8393 if (howMany < 0)
8394 return PyErr_Format(PyExc_ValueError,
8395 "negative argument not allowed");
8397 /* Allocate bytes */
8398 result = PyString_FromStringAndSize(NULL, howMany);
8399 if (result != NULL) {
8400 /* Get random data */
8401 if (RAND_pseudo_bytes((unsigned char*)
8402 PyString_AS_STRING(result),
8403 howMany) < 0) {
8404 Py_DECREF(result);
8405 return PyErr_Format(PyExc_ValueError,
8406 "RAND_pseudo_bytes");
8409 return result;
8411 #endif
8413 #ifdef HAVE_SETRESUID
8414 PyDoc_STRVAR(posix_setresuid__doc__,
8415 "setresuid(ruid, euid, suid)\n\n\
8416 Set the current process's real, effective, and saved user ids.");
8418 static PyObject*
8419 posix_setresuid (PyObject *self, PyObject *args)
8421 /* We assume uid_t is no larger than a long. */
8422 long ruid, euid, suid;
8423 if (!PyArg_ParseTuple(args, "lll", &ruid, &euid, &suid))
8424 return NULL;
8425 if (setresuid(ruid, euid, suid) < 0)
8426 return posix_error();
8427 Py_RETURN_NONE;
8429 #endif
8431 #ifdef HAVE_SETRESGID
8432 PyDoc_STRVAR(posix_setresgid__doc__,
8433 "setresgid(rgid, egid, sgid)\n\n\
8434 Set the current process's real, effective, and saved group ids.");
8436 static PyObject*
8437 posix_setresgid (PyObject *self, PyObject *args)
8439 /* We assume uid_t is no larger than a long. */
8440 long rgid, egid, sgid;
8441 if (!PyArg_ParseTuple(args, "lll", &rgid, &egid, &sgid))
8442 return NULL;
8443 if (setresgid(rgid, egid, sgid) < 0)
8444 return posix_error();
8445 Py_RETURN_NONE;
8447 #endif
8449 #ifdef HAVE_GETRESUID
8450 PyDoc_STRVAR(posix_getresuid__doc__,
8451 "getresuid() -> (ruid, euid, suid)\n\n\
8452 Get tuple of the current process's real, effective, and saved user ids.");
8454 static PyObject*
8455 posix_getresuid (PyObject *self, PyObject *noargs)
8457 uid_t ruid, euid, suid;
8458 long l_ruid, l_euid, l_suid;
8459 if (getresuid(&ruid, &euid, &suid) < 0)
8460 return posix_error();
8461 /* Force the values into long's as we don't know the size of uid_t. */
8462 l_ruid = ruid;
8463 l_euid = euid;
8464 l_suid = suid;
8465 return Py_BuildValue("(lll)", l_ruid, l_euid, l_suid);
8467 #endif
8469 #ifdef HAVE_GETRESGID
8470 PyDoc_STRVAR(posix_getresgid__doc__,
8471 "getresgid() -> (rgid, egid, sgid)\n\n\
8472 Get tuple of the current process's real, effective, and saved user ids.");
8474 static PyObject*
8475 posix_getresgid (PyObject *self, PyObject *noargs)
8477 uid_t rgid, egid, sgid;
8478 long l_rgid, l_egid, l_sgid;
8479 if (getresgid(&rgid, &egid, &sgid) < 0)
8480 return posix_error();
8481 /* Force the values into long's as we don't know the size of uid_t. */
8482 l_rgid = rgid;
8483 l_egid = egid;
8484 l_sgid = sgid;
8485 return Py_BuildValue("(lll)", l_rgid, l_egid, l_sgid);
8487 #endif
8489 static PyMethodDef posix_methods[] = {
8490 {"access", posix_access, METH_VARARGS, posix_access__doc__},
8491 #ifdef HAVE_TTYNAME
8492 {"ttyname", posix_ttyname, METH_VARARGS, posix_ttyname__doc__},
8493 #endif
8494 {"chdir", posix_chdir, METH_VARARGS, posix_chdir__doc__},
8495 #ifdef HAVE_CHFLAGS
8496 {"chflags", posix_chflags, METH_VARARGS, posix_chflags__doc__},
8497 #endif /* HAVE_CHFLAGS */
8498 {"chmod", posix_chmod, METH_VARARGS, posix_chmod__doc__},
8499 #ifdef HAVE_FCHMOD
8500 {"fchmod", posix_fchmod, METH_VARARGS, posix_fchmod__doc__},
8501 #endif /* HAVE_FCHMOD */
8502 #ifdef HAVE_CHOWN
8503 {"chown", posix_chown, METH_VARARGS, posix_chown__doc__},
8504 #endif /* HAVE_CHOWN */
8505 #ifdef HAVE_LCHMOD
8506 {"lchmod", posix_lchmod, METH_VARARGS, posix_lchmod__doc__},
8507 #endif /* HAVE_LCHMOD */
8508 #ifdef HAVE_FCHOWN
8509 {"fchown", posix_fchown, METH_VARARGS, posix_fchown__doc__},
8510 #endif /* HAVE_FCHOWN */
8511 #ifdef HAVE_LCHFLAGS
8512 {"lchflags", posix_lchflags, METH_VARARGS, posix_lchflags__doc__},
8513 #endif /* HAVE_LCHFLAGS */
8514 #ifdef HAVE_LCHOWN
8515 {"lchown", posix_lchown, METH_VARARGS, posix_lchown__doc__},
8516 #endif /* HAVE_LCHOWN */
8517 #ifdef HAVE_CHROOT
8518 {"chroot", posix_chroot, METH_VARARGS, posix_chroot__doc__},
8519 #endif
8520 #ifdef HAVE_CTERMID
8521 {"ctermid", posix_ctermid, METH_NOARGS, posix_ctermid__doc__},
8522 #endif
8523 #ifdef HAVE_GETCWD
8524 {"getcwd", posix_getcwd, METH_NOARGS, posix_getcwd__doc__},
8525 #ifdef Py_USING_UNICODE
8526 {"getcwdu", posix_getcwdu, METH_NOARGS, posix_getcwdu__doc__},
8527 #endif
8528 #endif
8529 #ifdef HAVE_LINK
8530 {"link", posix_link, METH_VARARGS, posix_link__doc__},
8531 #endif /* HAVE_LINK */
8532 {"listdir", posix_listdir, METH_VARARGS, posix_listdir__doc__},
8533 {"lstat", posix_lstat, METH_VARARGS, posix_lstat__doc__},
8534 {"mkdir", posix_mkdir, METH_VARARGS, posix_mkdir__doc__},
8535 #ifdef HAVE_NICE
8536 {"nice", posix_nice, METH_VARARGS, posix_nice__doc__},
8537 #endif /* HAVE_NICE */
8538 #ifdef HAVE_READLINK
8539 {"readlink", posix_readlink, METH_VARARGS, posix_readlink__doc__},
8540 #endif /* HAVE_READLINK */
8541 {"rename", posix_rename, METH_VARARGS, posix_rename__doc__},
8542 {"rmdir", posix_rmdir, METH_VARARGS, posix_rmdir__doc__},
8543 {"stat", posix_stat, METH_VARARGS, posix_stat__doc__},
8544 {"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__},
8545 #ifdef HAVE_SYMLINK
8546 {"symlink", posix_symlink, METH_VARARGS, posix_symlink__doc__},
8547 #endif /* HAVE_SYMLINK */
8548 #ifdef HAVE_SYSTEM
8549 {"system", posix_system, METH_VARARGS, posix_system__doc__},
8550 #endif
8551 {"umask", posix_umask, METH_VARARGS, posix_umask__doc__},
8552 #ifdef HAVE_UNAME
8553 {"uname", posix_uname, METH_NOARGS, posix_uname__doc__},
8554 #endif /* HAVE_UNAME */
8555 {"unlink", posix_unlink, METH_VARARGS, posix_unlink__doc__},
8556 {"remove", posix_unlink, METH_VARARGS, posix_remove__doc__},
8557 {"utime", posix_utime, METH_VARARGS, posix_utime__doc__},
8558 #ifdef HAVE_TIMES
8559 {"times", posix_times, METH_NOARGS, posix_times__doc__},
8560 #endif /* HAVE_TIMES */
8561 {"_exit", posix__exit, METH_VARARGS, posix__exit__doc__},
8562 #ifdef HAVE_EXECV
8563 {"execv", posix_execv, METH_VARARGS, posix_execv__doc__},
8564 {"execve", posix_execve, METH_VARARGS, posix_execve__doc__},
8565 #endif /* HAVE_EXECV */
8566 #ifdef HAVE_SPAWNV
8567 {"spawnv", posix_spawnv, METH_VARARGS, posix_spawnv__doc__},
8568 {"spawnve", posix_spawnve, METH_VARARGS, posix_spawnve__doc__},
8569 #if defined(PYOS_OS2)
8570 {"spawnvp", posix_spawnvp, METH_VARARGS, posix_spawnvp__doc__},
8571 {"spawnvpe", posix_spawnvpe, METH_VARARGS, posix_spawnvpe__doc__},
8572 #endif /* PYOS_OS2 */
8573 #endif /* HAVE_SPAWNV */
8574 #ifdef HAVE_FORK1
8575 {"fork1", posix_fork1, METH_NOARGS, posix_fork1__doc__},
8576 #endif /* HAVE_FORK1 */
8577 #ifdef HAVE_FORK
8578 {"fork", posix_fork, METH_NOARGS, posix_fork__doc__},
8579 #endif /* HAVE_FORK */
8580 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
8581 {"openpty", posix_openpty, METH_NOARGS, posix_openpty__doc__},
8582 #endif /* HAVE_OPENPTY || HAVE__GETPTY || HAVE_DEV_PTMX */
8583 #ifdef HAVE_FORKPTY
8584 {"forkpty", posix_forkpty, METH_NOARGS, posix_forkpty__doc__},
8585 #endif /* HAVE_FORKPTY */
8586 #ifdef HAVE_GETEGID
8587 {"getegid", posix_getegid, METH_NOARGS, posix_getegid__doc__},
8588 #endif /* HAVE_GETEGID */
8589 #ifdef HAVE_GETEUID
8590 {"geteuid", posix_geteuid, METH_NOARGS, posix_geteuid__doc__},
8591 #endif /* HAVE_GETEUID */
8592 #ifdef HAVE_GETGID
8593 {"getgid", posix_getgid, METH_NOARGS, posix_getgid__doc__},
8594 #endif /* HAVE_GETGID */
8595 #ifdef HAVE_GETGROUPS
8596 {"getgroups", posix_getgroups, METH_NOARGS, posix_getgroups__doc__},
8597 #endif
8598 {"getpid", posix_getpid, METH_NOARGS, posix_getpid__doc__},
8599 #ifdef HAVE_GETPGRP
8600 {"getpgrp", posix_getpgrp, METH_NOARGS, posix_getpgrp__doc__},
8601 #endif /* HAVE_GETPGRP */
8602 #ifdef HAVE_GETPPID
8603 {"getppid", posix_getppid, METH_NOARGS, posix_getppid__doc__},
8604 #endif /* HAVE_GETPPID */
8605 #ifdef HAVE_GETUID
8606 {"getuid", posix_getuid, METH_NOARGS, posix_getuid__doc__},
8607 #endif /* HAVE_GETUID */
8608 #ifdef HAVE_GETLOGIN
8609 {"getlogin", posix_getlogin, METH_NOARGS, posix_getlogin__doc__},
8610 #endif
8611 #ifdef HAVE_KILL
8612 {"kill", posix_kill, METH_VARARGS, posix_kill__doc__},
8613 #endif /* HAVE_KILL */
8614 #ifdef HAVE_KILLPG
8615 {"killpg", posix_killpg, METH_VARARGS, posix_killpg__doc__},
8616 #endif /* HAVE_KILLPG */
8617 #ifdef HAVE_PLOCK
8618 {"plock", posix_plock, METH_VARARGS, posix_plock__doc__},
8619 #endif /* HAVE_PLOCK */
8620 #ifdef HAVE_POPEN
8621 {"popen", posix_popen, METH_VARARGS, posix_popen__doc__},
8622 #ifdef MS_WINDOWS
8623 {"popen2", win32_popen2, METH_VARARGS},
8624 {"popen3", win32_popen3, METH_VARARGS},
8625 {"popen4", win32_popen4, METH_VARARGS},
8626 {"startfile", win32_startfile, METH_VARARGS, win32_startfile__doc__},
8627 #else
8628 #if defined(PYOS_OS2) && defined(PYCC_GCC)
8629 {"popen2", os2emx_popen2, METH_VARARGS},
8630 {"popen3", os2emx_popen3, METH_VARARGS},
8631 {"popen4", os2emx_popen4, METH_VARARGS},
8632 #endif
8633 #endif
8634 #endif /* HAVE_POPEN */
8635 #ifdef HAVE_SETUID
8636 {"setuid", posix_setuid, METH_VARARGS, posix_setuid__doc__},
8637 #endif /* HAVE_SETUID */
8638 #ifdef HAVE_SETEUID
8639 {"seteuid", posix_seteuid, METH_VARARGS, posix_seteuid__doc__},
8640 #endif /* HAVE_SETEUID */
8641 #ifdef HAVE_SETEGID
8642 {"setegid", posix_setegid, METH_VARARGS, posix_setegid__doc__},
8643 #endif /* HAVE_SETEGID */
8644 #ifdef HAVE_SETREUID
8645 {"setreuid", posix_setreuid, METH_VARARGS, posix_setreuid__doc__},
8646 #endif /* HAVE_SETREUID */
8647 #ifdef HAVE_SETREGID
8648 {"setregid", posix_setregid, METH_VARARGS, posix_setregid__doc__},
8649 #endif /* HAVE_SETREGID */
8650 #ifdef HAVE_SETGID
8651 {"setgid", posix_setgid, METH_VARARGS, posix_setgid__doc__},
8652 #endif /* HAVE_SETGID */
8653 #ifdef HAVE_SETGROUPS
8654 {"setgroups", posix_setgroups, METH_O, posix_setgroups__doc__},
8655 #endif /* HAVE_SETGROUPS */
8656 #ifdef HAVE_INITGROUPS
8657 {"initgroups", posix_initgroups, METH_VARARGS, posix_initgroups__doc__},
8658 #endif /* HAVE_INITGROUPS */
8659 #ifdef HAVE_GETPGID
8660 {"getpgid", posix_getpgid, METH_VARARGS, posix_getpgid__doc__},
8661 #endif /* HAVE_GETPGID */
8662 #ifdef HAVE_SETPGRP
8663 {"setpgrp", posix_setpgrp, METH_NOARGS, posix_setpgrp__doc__},
8664 #endif /* HAVE_SETPGRP */
8665 #ifdef HAVE_WAIT
8666 {"wait", posix_wait, METH_NOARGS, posix_wait__doc__},
8667 #endif /* HAVE_WAIT */
8668 #ifdef HAVE_WAIT3
8669 {"wait3", posix_wait3, METH_VARARGS, posix_wait3__doc__},
8670 #endif /* HAVE_WAIT3 */
8671 #ifdef HAVE_WAIT4
8672 {"wait4", posix_wait4, METH_VARARGS, posix_wait4__doc__},
8673 #endif /* HAVE_WAIT4 */
8674 #if defined(HAVE_WAITPID) || defined(HAVE_CWAIT)
8675 {"waitpid", posix_waitpid, METH_VARARGS, posix_waitpid__doc__},
8676 #endif /* HAVE_WAITPID */
8677 #ifdef HAVE_GETSID
8678 {"getsid", posix_getsid, METH_VARARGS, posix_getsid__doc__},
8679 #endif /* HAVE_GETSID */
8680 #ifdef HAVE_SETSID
8681 {"setsid", posix_setsid, METH_NOARGS, posix_setsid__doc__},
8682 #endif /* HAVE_SETSID */
8683 #ifdef HAVE_SETPGID
8684 {"setpgid", posix_setpgid, METH_VARARGS, posix_setpgid__doc__},
8685 #endif /* HAVE_SETPGID */
8686 #ifdef HAVE_TCGETPGRP
8687 {"tcgetpgrp", posix_tcgetpgrp, METH_VARARGS, posix_tcgetpgrp__doc__},
8688 #endif /* HAVE_TCGETPGRP */
8689 #ifdef HAVE_TCSETPGRP
8690 {"tcsetpgrp", posix_tcsetpgrp, METH_VARARGS, posix_tcsetpgrp__doc__},
8691 #endif /* HAVE_TCSETPGRP */
8692 {"open", posix_open, METH_VARARGS, posix_open__doc__},
8693 {"close", posix_close, METH_VARARGS, posix_close__doc__},
8694 {"closerange", posix_closerange, METH_VARARGS, posix_closerange__doc__},
8695 {"dup", posix_dup, METH_VARARGS, posix_dup__doc__},
8696 {"dup2", posix_dup2, METH_VARARGS, posix_dup2__doc__},
8697 {"lseek", posix_lseek, METH_VARARGS, posix_lseek__doc__},
8698 {"read", posix_read, METH_VARARGS, posix_read__doc__},
8699 {"write", posix_write, METH_VARARGS, posix_write__doc__},
8700 {"fstat", posix_fstat, METH_VARARGS, posix_fstat__doc__},
8701 {"fdopen", posix_fdopen, METH_VARARGS, posix_fdopen__doc__},
8702 {"isatty", posix_isatty, METH_VARARGS, posix_isatty__doc__},
8703 #ifdef HAVE_PIPE
8704 {"pipe", posix_pipe, METH_NOARGS, posix_pipe__doc__},
8705 #endif
8706 #ifdef HAVE_MKFIFO
8707 {"mkfifo", posix_mkfifo, METH_VARARGS, posix_mkfifo__doc__},
8708 #endif
8709 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
8710 {"mknod", posix_mknod, METH_VARARGS, posix_mknod__doc__},
8711 #endif
8712 #ifdef HAVE_DEVICE_MACROS
8713 {"major", posix_major, METH_VARARGS, posix_major__doc__},
8714 {"minor", posix_minor, METH_VARARGS, posix_minor__doc__},
8715 {"makedev", posix_makedev, METH_VARARGS, posix_makedev__doc__},
8716 #endif
8717 #ifdef HAVE_FTRUNCATE
8718 {"ftruncate", posix_ftruncate, METH_VARARGS, posix_ftruncate__doc__},
8719 #endif
8720 #ifdef HAVE_PUTENV
8721 {"putenv", posix_putenv, METH_VARARGS, posix_putenv__doc__},
8722 #endif
8723 #ifdef HAVE_UNSETENV
8724 {"unsetenv", posix_unsetenv, METH_VARARGS, posix_unsetenv__doc__},
8725 #endif
8726 {"strerror", posix_strerror, METH_VARARGS, posix_strerror__doc__},
8727 #ifdef HAVE_FCHDIR
8728 {"fchdir", posix_fchdir, METH_O, posix_fchdir__doc__},
8729 #endif
8730 #ifdef HAVE_FSYNC
8731 {"fsync", posix_fsync, METH_O, posix_fsync__doc__},
8732 #endif
8733 #ifdef HAVE_FDATASYNC
8734 {"fdatasync", posix_fdatasync, METH_O, posix_fdatasync__doc__},
8735 #endif
8736 #ifdef HAVE_SYS_WAIT_H
8737 #ifdef WCOREDUMP
8738 {"WCOREDUMP", posix_WCOREDUMP, METH_VARARGS, posix_WCOREDUMP__doc__},
8739 #endif /* WCOREDUMP */
8740 #ifdef WIFCONTINUED
8741 {"WIFCONTINUED",posix_WIFCONTINUED, METH_VARARGS, posix_WIFCONTINUED__doc__},
8742 #endif /* WIFCONTINUED */
8743 #ifdef WIFSTOPPED
8744 {"WIFSTOPPED", posix_WIFSTOPPED, METH_VARARGS, posix_WIFSTOPPED__doc__},
8745 #endif /* WIFSTOPPED */
8746 #ifdef WIFSIGNALED
8747 {"WIFSIGNALED", posix_WIFSIGNALED, METH_VARARGS, posix_WIFSIGNALED__doc__},
8748 #endif /* WIFSIGNALED */
8749 #ifdef WIFEXITED
8750 {"WIFEXITED", posix_WIFEXITED, METH_VARARGS, posix_WIFEXITED__doc__},
8751 #endif /* WIFEXITED */
8752 #ifdef WEXITSTATUS
8753 {"WEXITSTATUS", posix_WEXITSTATUS, METH_VARARGS, posix_WEXITSTATUS__doc__},
8754 #endif /* WEXITSTATUS */
8755 #ifdef WTERMSIG
8756 {"WTERMSIG", posix_WTERMSIG, METH_VARARGS, posix_WTERMSIG__doc__},
8757 #endif /* WTERMSIG */
8758 #ifdef WSTOPSIG
8759 {"WSTOPSIG", posix_WSTOPSIG, METH_VARARGS, posix_WSTOPSIG__doc__},
8760 #endif /* WSTOPSIG */
8761 #endif /* HAVE_SYS_WAIT_H */
8762 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
8763 {"fstatvfs", posix_fstatvfs, METH_VARARGS, posix_fstatvfs__doc__},
8764 #endif
8765 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
8766 {"statvfs", posix_statvfs, METH_VARARGS, posix_statvfs__doc__},
8767 #endif
8768 #ifdef HAVE_TMPFILE
8769 {"tmpfile", posix_tmpfile, METH_NOARGS, posix_tmpfile__doc__},
8770 #endif
8771 #ifdef HAVE_TEMPNAM
8772 {"tempnam", posix_tempnam, METH_VARARGS, posix_tempnam__doc__},
8773 #endif
8774 #ifdef HAVE_TMPNAM
8775 {"tmpnam", posix_tmpnam, METH_NOARGS, posix_tmpnam__doc__},
8776 #endif
8777 #ifdef HAVE_CONFSTR
8778 {"confstr", posix_confstr, METH_VARARGS, posix_confstr__doc__},
8779 #endif
8780 #ifdef HAVE_SYSCONF
8781 {"sysconf", posix_sysconf, METH_VARARGS, posix_sysconf__doc__},
8782 #endif
8783 #ifdef HAVE_FPATHCONF
8784 {"fpathconf", posix_fpathconf, METH_VARARGS, posix_fpathconf__doc__},
8785 #endif
8786 #ifdef HAVE_PATHCONF
8787 {"pathconf", posix_pathconf, METH_VARARGS, posix_pathconf__doc__},
8788 #endif
8789 {"abort", posix_abort, METH_NOARGS, posix_abort__doc__},
8790 #ifdef MS_WINDOWS
8791 {"_getfullpathname", posix__getfullpathname, METH_VARARGS, NULL},
8792 #endif
8793 #ifdef HAVE_GETLOADAVG
8794 {"getloadavg", posix_getloadavg, METH_NOARGS, posix_getloadavg__doc__},
8795 #endif
8796 #ifdef MS_WINDOWS
8797 {"urandom", win32_urandom, METH_VARARGS, win32_urandom__doc__},
8798 #endif
8799 #ifdef __VMS
8800 {"urandom", vms_urandom, METH_VARARGS, vms_urandom__doc__},
8801 #endif
8802 #ifdef HAVE_SETRESUID
8803 {"setresuid", posix_setresuid, METH_VARARGS, posix_setresuid__doc__},
8804 #endif
8805 #ifdef HAVE_SETRESGID
8806 {"setresgid", posix_setresgid, METH_VARARGS, posix_setresgid__doc__},
8807 #endif
8808 #ifdef HAVE_GETRESUID
8809 {"getresuid", posix_getresuid, METH_NOARGS, posix_getresuid__doc__},
8810 #endif
8811 #ifdef HAVE_GETRESGID
8812 {"getresgid", posix_getresgid, METH_NOARGS, posix_getresgid__doc__},
8813 #endif
8815 {NULL, NULL} /* Sentinel */
8819 static int
8820 ins(PyObject *module, char *symbol, long value)
8822 return PyModule_AddIntConstant(module, symbol, value);
8825 #if defined(PYOS_OS2)
8826 /* Insert Platform-Specific Constant Values (Strings & Numbers) of Common Use */
8827 static int insertvalues(PyObject *module)
8829 APIRET rc;
8830 ULONG values[QSV_MAX+1];
8831 PyObject *v;
8832 char *ver, tmp[50];
8834 Py_BEGIN_ALLOW_THREADS
8835 rc = DosQuerySysInfo(1L, QSV_MAX, &values[1], sizeof(ULONG) * QSV_MAX);
8836 Py_END_ALLOW_THREADS
8838 if (rc != NO_ERROR) {
8839 os2_error(rc);
8840 return -1;
8843 if (ins(module, "meminstalled", values[QSV_TOTPHYSMEM])) return -1;
8844 if (ins(module, "memkernel", values[QSV_TOTRESMEM])) return -1;
8845 if (ins(module, "memvirtual", values[QSV_TOTAVAILMEM])) return -1;
8846 if (ins(module, "maxpathlen", values[QSV_MAX_PATH_LENGTH])) return -1;
8847 if (ins(module, "maxnamelen", values[QSV_MAX_COMP_LENGTH])) return -1;
8848 if (ins(module, "revision", values[QSV_VERSION_REVISION])) return -1;
8849 if (ins(module, "timeslice", values[QSV_MIN_SLICE])) return -1;
8851 switch (values[QSV_VERSION_MINOR]) {
8852 case 0: ver = "2.00"; break;
8853 case 10: ver = "2.10"; break;
8854 case 11: ver = "2.11"; break;
8855 case 30: ver = "3.00"; break;
8856 case 40: ver = "4.00"; break;
8857 case 50: ver = "5.00"; break;
8858 default:
8859 PyOS_snprintf(tmp, sizeof(tmp),
8860 "%d-%d", values[QSV_VERSION_MAJOR],
8861 values[QSV_VERSION_MINOR]);
8862 ver = &tmp[0];
8865 /* Add Indicator of the Version of the Operating System */
8866 if (PyModule_AddStringConstant(module, "version", tmp) < 0)
8867 return -1;
8869 /* Add Indicator of Which Drive was Used to Boot the System */
8870 tmp[0] = 'A' + values[QSV_BOOT_DRIVE] - 1;
8871 tmp[1] = ':';
8872 tmp[2] = '\0';
8874 return PyModule_AddStringConstant(module, "bootdrive", tmp);
8876 #endif
8878 static int
8879 all_ins(PyObject *d)
8881 #ifdef F_OK
8882 if (ins(d, "F_OK", (long)F_OK)) return -1;
8883 #endif
8884 #ifdef R_OK
8885 if (ins(d, "R_OK", (long)R_OK)) return -1;
8886 #endif
8887 #ifdef W_OK
8888 if (ins(d, "W_OK", (long)W_OK)) return -1;
8889 #endif
8890 #ifdef X_OK
8891 if (ins(d, "X_OK", (long)X_OK)) return -1;
8892 #endif
8893 #ifdef NGROUPS_MAX
8894 if (ins(d, "NGROUPS_MAX", (long)NGROUPS_MAX)) return -1;
8895 #endif
8896 #ifdef TMP_MAX
8897 if (ins(d, "TMP_MAX", (long)TMP_MAX)) return -1;
8898 #endif
8899 #ifdef WCONTINUED
8900 if (ins(d, "WCONTINUED", (long)WCONTINUED)) return -1;
8901 #endif
8902 #ifdef WNOHANG
8903 if (ins(d, "WNOHANG", (long)WNOHANG)) return -1;
8904 #endif
8905 #ifdef WUNTRACED
8906 if (ins(d, "WUNTRACED", (long)WUNTRACED)) return -1;
8907 #endif
8908 #ifdef O_RDONLY
8909 if (ins(d, "O_RDONLY", (long)O_RDONLY)) return -1;
8910 #endif
8911 #ifdef O_WRONLY
8912 if (ins(d, "O_WRONLY", (long)O_WRONLY)) return -1;
8913 #endif
8914 #ifdef O_RDWR
8915 if (ins(d, "O_RDWR", (long)O_RDWR)) return -1;
8916 #endif
8917 #ifdef O_NDELAY
8918 if (ins(d, "O_NDELAY", (long)O_NDELAY)) return -1;
8919 #endif
8920 #ifdef O_NONBLOCK
8921 if (ins(d, "O_NONBLOCK", (long)O_NONBLOCK)) return -1;
8922 #endif
8923 #ifdef O_APPEND
8924 if (ins(d, "O_APPEND", (long)O_APPEND)) return -1;
8925 #endif
8926 #ifdef O_DSYNC
8927 if (ins(d, "O_DSYNC", (long)O_DSYNC)) return -1;
8928 #endif
8929 #ifdef O_RSYNC
8930 if (ins(d, "O_RSYNC", (long)O_RSYNC)) return -1;
8931 #endif
8932 #ifdef O_SYNC
8933 if (ins(d, "O_SYNC", (long)O_SYNC)) return -1;
8934 #endif
8935 #ifdef O_NOCTTY
8936 if (ins(d, "O_NOCTTY", (long)O_NOCTTY)) return -1;
8937 #endif
8938 #ifdef O_CREAT
8939 if (ins(d, "O_CREAT", (long)O_CREAT)) return -1;
8940 #endif
8941 #ifdef O_EXCL
8942 if (ins(d, "O_EXCL", (long)O_EXCL)) return -1;
8943 #endif
8944 #ifdef O_TRUNC
8945 if (ins(d, "O_TRUNC", (long)O_TRUNC)) return -1;
8946 #endif
8947 #ifdef O_BINARY
8948 if (ins(d, "O_BINARY", (long)O_BINARY)) return -1;
8949 #endif
8950 #ifdef O_TEXT
8951 if (ins(d, "O_TEXT", (long)O_TEXT)) return -1;
8952 #endif
8953 #ifdef O_LARGEFILE
8954 if (ins(d, "O_LARGEFILE", (long)O_LARGEFILE)) return -1;
8955 #endif
8956 #ifdef O_SHLOCK
8957 if (ins(d, "O_SHLOCK", (long)O_SHLOCK)) return -1;
8958 #endif
8959 #ifdef O_EXLOCK
8960 if (ins(d, "O_EXLOCK", (long)O_EXLOCK)) return -1;
8961 #endif
8963 /* MS Windows */
8964 #ifdef O_NOINHERIT
8965 /* Don't inherit in child processes. */
8966 if (ins(d, "O_NOINHERIT", (long)O_NOINHERIT)) return -1;
8967 #endif
8968 #ifdef _O_SHORT_LIVED
8969 /* Optimize for short life (keep in memory). */
8970 /* MS forgot to define this one with a non-underscore form too. */
8971 if (ins(d, "O_SHORT_LIVED", (long)_O_SHORT_LIVED)) return -1;
8972 #endif
8973 #ifdef O_TEMPORARY
8974 /* Automatically delete when last handle is closed. */
8975 if (ins(d, "O_TEMPORARY", (long)O_TEMPORARY)) return -1;
8976 #endif
8977 #ifdef O_RANDOM
8978 /* Optimize for random access. */
8979 if (ins(d, "O_RANDOM", (long)O_RANDOM)) return -1;
8980 #endif
8981 #ifdef O_SEQUENTIAL
8982 /* Optimize for sequential access. */
8983 if (ins(d, "O_SEQUENTIAL", (long)O_SEQUENTIAL)) return -1;
8984 #endif
8986 /* GNU extensions. */
8987 #ifdef O_ASYNC
8988 /* Send a SIGIO signal whenever input or output
8989 becomes available on file descriptor */
8990 if (ins(d, "O_ASYNC", (long)O_ASYNC)) return -1;
8991 #endif
8992 #ifdef O_DIRECT
8993 /* Direct disk access. */
8994 if (ins(d, "O_DIRECT", (long)O_DIRECT)) return -1;
8995 #endif
8996 #ifdef O_DIRECTORY
8997 /* Must be a directory. */
8998 if (ins(d, "O_DIRECTORY", (long)O_DIRECTORY)) return -1;
8999 #endif
9000 #ifdef O_NOFOLLOW
9001 /* Do not follow links. */
9002 if (ins(d, "O_NOFOLLOW", (long)O_NOFOLLOW)) return -1;
9003 #endif
9004 #ifdef O_NOATIME
9005 /* Do not update the access time. */
9006 if (ins(d, "O_NOATIME", (long)O_NOATIME)) return -1;
9007 #endif
9009 /* These come from sysexits.h */
9010 #ifdef EX_OK
9011 if (ins(d, "EX_OK", (long)EX_OK)) return -1;
9012 #endif /* EX_OK */
9013 #ifdef EX_USAGE
9014 if (ins(d, "EX_USAGE", (long)EX_USAGE)) return -1;
9015 #endif /* EX_USAGE */
9016 #ifdef EX_DATAERR
9017 if (ins(d, "EX_DATAERR", (long)EX_DATAERR)) return -1;
9018 #endif /* EX_DATAERR */
9019 #ifdef EX_NOINPUT
9020 if (ins(d, "EX_NOINPUT", (long)EX_NOINPUT)) return -1;
9021 #endif /* EX_NOINPUT */
9022 #ifdef EX_NOUSER
9023 if (ins(d, "EX_NOUSER", (long)EX_NOUSER)) return -1;
9024 #endif /* EX_NOUSER */
9025 #ifdef EX_NOHOST
9026 if (ins(d, "EX_NOHOST", (long)EX_NOHOST)) return -1;
9027 #endif /* EX_NOHOST */
9028 #ifdef EX_UNAVAILABLE
9029 if (ins(d, "EX_UNAVAILABLE", (long)EX_UNAVAILABLE)) return -1;
9030 #endif /* EX_UNAVAILABLE */
9031 #ifdef EX_SOFTWARE
9032 if (ins(d, "EX_SOFTWARE", (long)EX_SOFTWARE)) return -1;
9033 #endif /* EX_SOFTWARE */
9034 #ifdef EX_OSERR
9035 if (ins(d, "EX_OSERR", (long)EX_OSERR)) return -1;
9036 #endif /* EX_OSERR */
9037 #ifdef EX_OSFILE
9038 if (ins(d, "EX_OSFILE", (long)EX_OSFILE)) return -1;
9039 #endif /* EX_OSFILE */
9040 #ifdef EX_CANTCREAT
9041 if (ins(d, "EX_CANTCREAT", (long)EX_CANTCREAT)) return -1;
9042 #endif /* EX_CANTCREAT */
9043 #ifdef EX_IOERR
9044 if (ins(d, "EX_IOERR", (long)EX_IOERR)) return -1;
9045 #endif /* EX_IOERR */
9046 #ifdef EX_TEMPFAIL
9047 if (ins(d, "EX_TEMPFAIL", (long)EX_TEMPFAIL)) return -1;
9048 #endif /* EX_TEMPFAIL */
9049 #ifdef EX_PROTOCOL
9050 if (ins(d, "EX_PROTOCOL", (long)EX_PROTOCOL)) return -1;
9051 #endif /* EX_PROTOCOL */
9052 #ifdef EX_NOPERM
9053 if (ins(d, "EX_NOPERM", (long)EX_NOPERM)) return -1;
9054 #endif /* EX_NOPERM */
9055 #ifdef EX_CONFIG
9056 if (ins(d, "EX_CONFIG", (long)EX_CONFIG)) return -1;
9057 #endif /* EX_CONFIG */
9058 #ifdef EX_NOTFOUND
9059 if (ins(d, "EX_NOTFOUND", (long)EX_NOTFOUND)) return -1;
9060 #endif /* EX_NOTFOUND */
9062 #ifdef HAVE_SPAWNV
9063 #if defined(PYOS_OS2) && defined(PYCC_GCC)
9064 if (ins(d, "P_WAIT", (long)P_WAIT)) return -1;
9065 if (ins(d, "P_NOWAIT", (long)P_NOWAIT)) return -1;
9066 if (ins(d, "P_OVERLAY", (long)P_OVERLAY)) return -1;
9067 if (ins(d, "P_DEBUG", (long)P_DEBUG)) return -1;
9068 if (ins(d, "P_SESSION", (long)P_SESSION)) return -1;
9069 if (ins(d, "P_DETACH", (long)P_DETACH)) return -1;
9070 if (ins(d, "P_PM", (long)P_PM)) return -1;
9071 if (ins(d, "P_DEFAULT", (long)P_DEFAULT)) return -1;
9072 if (ins(d, "P_MINIMIZE", (long)P_MINIMIZE)) return -1;
9073 if (ins(d, "P_MAXIMIZE", (long)P_MAXIMIZE)) return -1;
9074 if (ins(d, "P_FULLSCREEN", (long)P_FULLSCREEN)) return -1;
9075 if (ins(d, "P_WINDOWED", (long)P_WINDOWED)) return -1;
9076 if (ins(d, "P_FOREGROUND", (long)P_FOREGROUND)) return -1;
9077 if (ins(d, "P_BACKGROUND", (long)P_BACKGROUND)) return -1;
9078 if (ins(d, "P_NOCLOSE", (long)P_NOCLOSE)) return -1;
9079 if (ins(d, "P_NOSESSION", (long)P_NOSESSION)) return -1;
9080 if (ins(d, "P_QUOTE", (long)P_QUOTE)) return -1;
9081 if (ins(d, "P_TILDE", (long)P_TILDE)) return -1;
9082 if (ins(d, "P_UNRELATED", (long)P_UNRELATED)) return -1;
9083 if (ins(d, "P_DEBUGDESC", (long)P_DEBUGDESC)) return -1;
9084 #else
9085 if (ins(d, "P_WAIT", (long)_P_WAIT)) return -1;
9086 if (ins(d, "P_NOWAIT", (long)_P_NOWAIT)) return -1;
9087 if (ins(d, "P_OVERLAY", (long)_OLD_P_OVERLAY)) return -1;
9088 if (ins(d, "P_NOWAITO", (long)_P_NOWAITO)) return -1;
9089 if (ins(d, "P_DETACH", (long)_P_DETACH)) return -1;
9090 #endif
9091 #endif
9093 #if defined(PYOS_OS2)
9094 if (insertvalues(d)) return -1;
9095 #endif
9096 return 0;
9100 #if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__)) && !defined(__QNX__)
9101 #define INITFUNC initnt
9102 #define MODNAME "nt"
9104 #elif defined(PYOS_OS2)
9105 #define INITFUNC initos2
9106 #define MODNAME "os2"
9108 #else
9109 #define INITFUNC initposix
9110 #define MODNAME "posix"
9111 #endif
9113 PyMODINIT_FUNC
9114 INITFUNC(void)
9116 PyObject *m, *v;
9118 m = Py_InitModule3(MODNAME,
9119 posix_methods,
9120 posix__doc__);
9121 if (m == NULL)
9122 return;
9124 /* Initialize environ dictionary */
9125 v = convertenviron();
9126 Py_XINCREF(v);
9127 if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
9128 return;
9129 Py_DECREF(v);
9131 if (all_ins(m))
9132 return;
9134 if (setup_confname_tables(m))
9135 return;
9137 Py_INCREF(PyExc_OSError);
9138 PyModule_AddObject(m, "error", PyExc_OSError);
9140 #ifdef HAVE_PUTENV
9141 if (posix_putenv_garbage == NULL)
9142 posix_putenv_garbage = PyDict_New();
9143 #endif
9145 if (!initialized) {
9146 stat_result_desc.name = MODNAME ".stat_result";
9147 stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
9148 stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
9149 stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
9150 PyStructSequence_InitType(&StatResultType, &stat_result_desc);
9151 structseq_new = StatResultType.tp_new;
9152 StatResultType.tp_new = statresult_new;
9154 statvfs_result_desc.name = MODNAME ".statvfs_result";
9155 PyStructSequence_InitType(&StatVFSResultType, &statvfs_result_desc);
9156 #ifdef NEED_TICKS_PER_SECOND
9157 # if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
9158 ticks_per_second = sysconf(_SC_CLK_TCK);
9159 # elif defined(HZ)
9160 ticks_per_second = HZ;
9161 # else
9162 ticks_per_second = 60; /* magic fallback value; may be bogus */
9163 # endif
9164 #endif
9166 Py_INCREF((PyObject*) &StatResultType);
9167 PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType);
9168 Py_INCREF((PyObject*) &StatVFSResultType);
9169 PyModule_AddObject(m, "statvfs_result",
9170 (PyObject*) &StatVFSResultType);
9171 initialized = 1;
9173 #ifdef __APPLE__
9175 * Step 2 of weak-linking support on Mac OS X.
9177 * The code below removes functions that are not available on the
9178 * currently active platform.
9180 * This block allow one to use a python binary that was build on
9181 * OSX 10.4 on OSX 10.3, without loosing access to new APIs on
9182 * OSX 10.4.
9184 #ifdef HAVE_FSTATVFS
9185 if (fstatvfs == NULL) {
9186 if (PyObject_DelAttrString(m, "fstatvfs") == -1) {
9187 return;
9190 #endif /* HAVE_FSTATVFS */
9192 #ifdef HAVE_STATVFS
9193 if (statvfs == NULL) {
9194 if (PyObject_DelAttrString(m, "statvfs") == -1) {
9195 return;
9198 #endif /* HAVE_STATVFS */
9200 # ifdef HAVE_LCHOWN
9201 if (lchown == NULL) {
9202 if (PyObject_DelAttrString(m, "lchown") == -1) {
9203 return;
9206 #endif /* HAVE_LCHOWN */
9209 #endif /* __APPLE__ */
9213 #ifdef __cplusplus
9215 #endif