OILS / pyext / posixmodule.c View on Github | oilshell.org

2710 lines, 2000 significant
1
2/* OVM_MAIN: POSIX module implementation stripped down for Oil */
3
4#define PY_SSIZE_T_CLEAN
5
6#include "Python.h"
7#include "structseq.h"
8
9#ifdef __cplusplus
10extern "C" {
11#endif
12
13/* OVM_MAIN: For getting unused variable warnings while still keeping
14 * "comments" */
15
16#define PyDoc_STRVAR_remove(name,str)
17
18PyDoc_STRVAR(posix__doc__,
19"This module provides access to operating system functionality that is\n\
20standardized by the C Standard and the POSIX standard (a thinly\n\
21disguised Unix interface). Refer to the library manual and\n\
22corresponding Unix manual entries for more information on calls.");
23
24/* OVM_MAIN: Turning off Unicode in build/setup_posix.py didn't work.
25 *
26 * If we don't turn it off we get build errors.
27 * */
28#undef Py_USING_UNICODE
29
30#ifndef Py_USING_UNICODE
31/* This is used in signatures of functions. */
32#define Py_UNICODE void
33#endif
34
35#ifdef HAVE_SYS_TYPES_H
36#include <sys/types.h>
37#endif /* HAVE_SYS_TYPES_H */
38
39#ifdef HAVE_SYS_STAT_H
40#include <sys/stat.h>
41#endif /* HAVE_SYS_STAT_H */
42
43#ifdef HAVE_SYS_WAIT_H
44#include <sys/wait.h> /* For WNOHANG */
45#endif
46
47#ifdef HAVE_SIGNAL_H
48#include <signal.h>
49#endif
50
51#ifdef HAVE_FCNTL_H
52#include <fcntl.h>
53#endif /* HAVE_FCNTL_H */
54
55/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
56#if defined(HAVE_SYS_RESOURCE_H)
57#include <sys/resource.h>
58#endif
59
60/* Unix functions that the configure script doesn't check for */
61#define HAVE_EXECV 1
62#define HAVE_FORK 1
63#define HAVE_GETCWD 1
64#define HAVE_GETEGID 1
65#define HAVE_GETEUID 1
66#define HAVE_GETGID 1
67#define HAVE_GETPPID 1
68#define HAVE_GETUID 1
69#define HAVE_KILL 1
70#define HAVE_PIPE 1
71#define HAVE_WAIT 1
72
73#ifndef HAVE_UNISTD_H
74extern int mkdir(const char *, mode_t);
75extern int chdir(const char *);
76extern int rmdir(const char *);
77extern int chmod(const char *, mode_t);
78extern int chown(const char *, uid_t, gid_t);
79extern char *getcwd(char *, int);
80extern char *strerror(int);
81extern int link(const char *, const char *);
82extern int rename(const char *, const char *);
83extern int stat(const char *, struct stat *);
84extern int unlink(const char *);
85extern int pclose(FILE *);
86#ifdef HAVE_SYMLINK
87extern int symlink(const char *, const char *);
88#endif /* HAVE_SYMLINK */
89#ifdef HAVE_LSTAT
90extern int lstat(const char *, struct stat *);
91#endif /* HAVE_LSTAT */
92#endif /* !HAVE_UNISTD_H */
93
94#ifdef HAVE_UTIME_H
95#include <utime.h>
96#endif /* HAVE_UTIME_H */
97
98#ifdef HAVE_SYS_UTIME_H
99#include <sys/utime.h>
100#define HAVE_UTIME_H /* pretend we do for the rest of this file */
101#endif /* HAVE_SYS_UTIME_H */
102
103#ifdef HAVE_SYS_TIMES_H
104#include <sys/times.h>
105#endif /* HAVE_SYS_TIMES_H */
106
107#ifdef HAVE_SYS_PARAM_H
108#include <sys/param.h>
109#endif /* HAVE_SYS_PARAM_H */
110
111#ifdef HAVE_SYS_UTSNAME_H
112#include <sys/utsname.h>
113#endif /* HAVE_SYS_UTSNAME_H */
114
115#ifdef HAVE_DIRENT_H
116#include <dirent.h>
117#define NAMLEN(dirent) strlen((dirent)->d_name)
118#else
119#if defined(__WATCOMC__) && !defined(__QNX__)
120#include <direct.h>
121#define NAMLEN(dirent) strlen((dirent)->d_name)
122#else
123#define dirent direct
124#define NAMLEN(dirent) (dirent)->d_namlen
125#endif
126#ifdef HAVE_SYS_NDIR_H
127#include <sys/ndir.h>
128#endif
129#ifdef HAVE_SYS_DIR_H
130#include <sys/dir.h>
131#endif
132#ifdef HAVE_NDIR_H
133#include <ndir.h>
134#endif
135#endif
136
137#ifndef MAXPATHLEN
138#if defined(PATH_MAX) && PATH_MAX > 1024
139#define MAXPATHLEN PATH_MAX
140#else
141#define MAXPATHLEN 1024
142#endif
143#endif /* MAXPATHLEN */
144
145#define WAIT_TYPE int
146#define WAIT_STATUS_INT(s) (s)
147
148/* Issue #1983: pid_t can be longer than a C long on some systems */
149#if !defined(SIZEOF_PID_T) || SIZEOF_PID_T == SIZEOF_INT
150#define PARSE_PID "i"
151#define PyLong_FromPid PyInt_FromLong
152#define PyLong_AsPid PyInt_AsLong
153#elif SIZEOF_PID_T == SIZEOF_LONG
154#define PARSE_PID "l"
155#define PyLong_FromPid PyInt_FromLong
156#define PyLong_AsPid PyInt_AsLong
157#elif defined(SIZEOF_LONG_LONG) && SIZEOF_PID_T == SIZEOF_LONG_LONG
158#define PARSE_PID "L"
159#define PyLong_FromPid PyLong_FromLongLong
160#define PyLong_AsPid PyInt_AsLongLong
161#else
162#error "sizeof(pid_t) is neither sizeof(int), sizeof(long) or sizeof(long long)"
163#endif /* SIZEOF_PID_T */
164
165/* Don't use the "_r" form if we don't need it (also, won't have a
166 prototype for it, at least on Solaris -- maybe others as well?). */
167#if defined(HAVE_CTERMID_R) && defined(WITH_THREAD)
168#define USE_CTERMID_R
169#endif
170
171#if defined(HAVE_TMPNAM_R) && defined(WITH_THREAD)
172#define USE_TMPNAM_R
173#endif
174
175#if defined(MAJOR_IN_MKDEV)
176#include <sys/mkdev.h>
177#else
178#if defined(MAJOR_IN_SYSMACROS)
179#include <sys/sysmacros.h>
180#endif
181#if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
182#include <sys/mkdev.h>
183#endif
184#endif
185
186
187PyObject *
188_PyInt_FromUid(uid_t uid)
189{
190 if (uid <= LONG_MAX)
191 return PyInt_FromLong(uid);
192 return PyLong_FromUnsignedLong(uid);
193}
194
195PyObject *
196_PyInt_FromGid(gid_t gid)
197{
198 if (gid <= LONG_MAX)
199 return PyInt_FromLong(gid);
200 return PyLong_FromUnsignedLong(gid);
201}
202
203int
204_Py_Uid_Converter(PyObject *obj, void *p)
205{
206 int overflow;
207 long result;
208 if (PyFloat_Check(obj)) {
209 PyErr_SetString(PyExc_TypeError,
210 "integer argument expected, got float");
211 return 0;
212 }
213 result = PyLong_AsLongAndOverflow(obj, &overflow);
214 if (overflow < 0)
215 goto OverflowDown;
216 if (!overflow && result == -1) {
217 /* error or -1 */
218 if (PyErr_Occurred())
219 return 0;
220 *(uid_t *)p = (uid_t)-1;
221 }
222 else {
223 /* unsigned uid_t */
224 unsigned long uresult;
225 if (overflow > 0) {
226 uresult = PyLong_AsUnsignedLong(obj);
227 if (PyErr_Occurred()) {
228 if (PyErr_ExceptionMatches(PyExc_OverflowError))
229 goto OverflowUp;
230 return 0;
231 }
232 } else {
233 if (result < 0)
234 goto OverflowDown;
235 uresult = result;
236 }
237 if (sizeof(uid_t) < sizeof(long) &&
238 (unsigned long)(uid_t)uresult != uresult)
239 goto OverflowUp;
240 *(uid_t *)p = (uid_t)uresult;
241 }
242 return 1;
243
244OverflowDown:
245 PyErr_SetString(PyExc_OverflowError,
246 "user id is less than minimum");
247 return 0;
248
249OverflowUp:
250 PyErr_SetString(PyExc_OverflowError,
251 "user id is greater than maximum");
252 return 0;
253}
254
255int
256_Py_Gid_Converter(PyObject *obj, void *p)
257{
258 int overflow;
259 long result;
260 if (PyFloat_Check(obj)) {
261 PyErr_SetString(PyExc_TypeError,
262 "integer argument expected, got float");
263 return 0;
264 }
265 result = PyLong_AsLongAndOverflow(obj, &overflow);
266 if (overflow < 0)
267 goto OverflowDown;
268 if (!overflow && result == -1) {
269 /* error or -1 */
270 if (PyErr_Occurred())
271 return 0;
272 *(gid_t *)p = (gid_t)-1;
273 }
274 else {
275 /* unsigned gid_t */
276 unsigned long uresult;
277 if (overflow > 0) {
278 uresult = PyLong_AsUnsignedLong(obj);
279 if (PyErr_Occurred()) {
280 if (PyErr_ExceptionMatches(PyExc_OverflowError))
281 goto OverflowUp;
282 return 0;
283 }
284 } else {
285 if (result < 0)
286 goto OverflowDown;
287 uresult = result;
288 }
289 if (sizeof(gid_t) < sizeof(long) &&
290 (unsigned long)(gid_t)uresult != uresult)
291 goto OverflowUp;
292 *(gid_t *)p = (gid_t)uresult;
293 }
294 return 1;
295
296OverflowDown:
297 PyErr_SetString(PyExc_OverflowError,
298 "group id is less than minimum");
299 return 0;
300
301OverflowUp:
302 PyErr_SetString(PyExc_OverflowError,
303 "group id is greater than maximum");
304 return 0;
305}
306
307
308#ifdef HAVE_LONG_LONG
309static PyObject *
310_PyInt_FromDev(PY_LONG_LONG v)
311{
312 if (LONG_MIN <= v && v <= LONG_MAX)
313 return PyInt_FromLong((long)v);
314 else
315 return PyLong_FromLongLong(v);
316}
317#else
318# define _PyInt_FromDev PyInt_FromLong
319#endif
320
321#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
322/* On Darwin/MacOSX a shared library or framework has no access to
323** environ directly, we must obtain it with _NSGetEnviron(). See also
324** man environ(7).
325*/
326#include <crt_externs.h>
327static char **environ;
328#elif !defined(_MSC_VER) && ( !defined(__WATCOMC__) || defined(__QNX__) )
329extern char **environ;
330#endif /* !_MSC_VER */
331
332static PyObject *
333convertenviron(void)
334{
335 PyObject *d;
336 char **e;
337 d = PyDict_New();
338 if (d == NULL)
339 return NULL;
340#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
341 if (environ == NULL)
342 environ = *_NSGetEnviron();
343#endif
344 if (environ == NULL)
345 return d;
346 /* This part ignores errors */
347 for (e = environ; *e != NULL; e++) {
348 PyObject *k;
349 PyObject *v;
350 char *p = strchr(*e, '=');
351 if (p == NULL)
352 continue;
353 k = PyString_FromStringAndSize(*e, (int)(p-*e));
354 if (k == NULL) {
355 PyErr_Clear();
356 continue;
357 }
358 v = PyString_FromString(p+1);
359 if (v == NULL) {
360 PyErr_Clear();
361 Py_DECREF(k);
362 continue;
363 }
364 if (PyDict_GetItem(d, k) == NULL) {
365 if (PyDict_SetItem(d, k, v) != 0)
366 PyErr_Clear();
367 }
368 Py_DECREF(k);
369 Py_DECREF(v);
370 }
371 return d;
372}
373
374
375/* Set a POSIX-specific error from errno, and return NULL */
376
377static PyObject *
378posix_error(void)
379{
380 return PyErr_SetFromErrno(PyExc_OSError);
381}
382static PyObject *
383posix_error_with_filename(char* name)
384{
385 return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
386}
387
388static PyObject *
389posix_error_with_allocated_filename(char* name)
390{
391 PyObject *rc = PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
392 PyMem_Free(name);
393 return rc;
394}
395
396/* POSIX generic methods */
397
398static PyObject *
399posix_1str(PyObject *args, char *format, int (*func)(const char*))
400{
401 char *path1 = NULL;
402 int res;
403 if (!PyArg_ParseTuple(args, format,
404 Py_FileSystemDefaultEncoding, &path1))
405 return NULL;
406 Py_BEGIN_ALLOW_THREADS
407 res = (*func)(path1);
408 Py_END_ALLOW_THREADS
409 if (res < 0)
410 return posix_error_with_allocated_filename(path1);
411 PyMem_Free(path1);
412 Py_INCREF(Py_None);
413 return Py_None;
414}
415
416static PyObject *
417posix_2str(PyObject *args,
418 char *format,
419 int (*func)(const char *, const char *))
420{
421 char *path1 = NULL, *path2 = NULL;
422 int res;
423 if (!PyArg_ParseTuple(args, format,
424 Py_FileSystemDefaultEncoding, &path1,
425 Py_FileSystemDefaultEncoding, &path2))
426 return NULL;
427 Py_BEGIN_ALLOW_THREADS
428 res = (*func)(path1, path2);
429 Py_END_ALLOW_THREADS
430 PyMem_Free(path1);
431 PyMem_Free(path2);
432 if (res != 0)
433 /* XXX how to report both path1 and path2??? */
434 return posix_error();
435 Py_INCREF(Py_None);
436 return Py_None;
437}
438
439/* choose the appropriate stat and fstat functions and return structs */
440# define STAT stat
441# define FSTAT fstat
442# define STRUCT_STAT struct stat
443
444PyDoc_STRVAR(stat_result__doc__,
445"stat_result: Result from stat or lstat.\n\n\
446This object may be accessed either as a tuple of\n\
447 (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
448or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
449\n\
450Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
451or st_flags, they are available as attributes only.\n\
452\n\
453See os.stat for more information.");
454
455static PyStructSequence_Field stat_result_fields[] = {
456 {"st_mode", "protection bits"},
457 {"st_ino", "inode"},
458 {"st_dev", "device"},
459 {"st_nlink", "number of hard links"},
460 {"st_uid", "user ID of owner"},
461 {"st_gid", "group ID of owner"},
462 {"st_size", "total size, in bytes"},
463 /* The NULL is replaced with PyStructSequence_UnnamedField later. */
464 {NULL, "integer time of last access"},
465 {NULL, "integer time of last modification"},
466 {NULL, "integer time of last change"},
467 {"st_atime", "time of last access"},
468 {"st_mtime", "time of last modification"},
469 {"st_ctime", "time of last change"},
470#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
471 {"st_blksize", "blocksize for filesystem I/O"},
472#endif
473#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
474 {"st_blocks", "number of blocks allocated"},
475#endif
476#ifdef HAVE_STRUCT_STAT_ST_RDEV
477 {"st_rdev", "device type (if inode device)"},
478#endif
479#ifdef HAVE_STRUCT_STAT_ST_FLAGS
480 {"st_flags", "user defined flags for file"},
481#endif
482#ifdef HAVE_STRUCT_STAT_ST_GEN
483 {"st_gen", "generation number"},
484#endif
485#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
486 {"st_birthtime", "time of creation"},
487#endif
488 {0}
489};
490
491#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
492#define ST_BLKSIZE_IDX 13
493#else
494#define ST_BLKSIZE_IDX 12
495#endif
496
497#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
498#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
499#else
500#define ST_BLOCKS_IDX ST_BLKSIZE_IDX
501#endif
502
503#ifdef HAVE_STRUCT_STAT_ST_RDEV
504#define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
505#else
506#define ST_RDEV_IDX ST_BLOCKS_IDX
507#endif
508
509#ifdef HAVE_STRUCT_STAT_ST_FLAGS
510#define ST_FLAGS_IDX (ST_RDEV_IDX+1)
511#else
512#define ST_FLAGS_IDX ST_RDEV_IDX
513#endif
514
515#ifdef HAVE_STRUCT_STAT_ST_GEN
516#define ST_GEN_IDX (ST_FLAGS_IDX+1)
517#else
518#define ST_GEN_IDX ST_FLAGS_IDX
519#endif
520
521#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
522#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
523#else
524#define ST_BIRTHTIME_IDX ST_GEN_IDX
525#endif
526
527static PyStructSequence_Desc stat_result_desc = {
528 "stat_result", /* name */
529 stat_result__doc__, /* doc */
530 stat_result_fields,
531 10
532};
533
534static int initialized;
535static PyTypeObject StatResultType;
536static newfunc structseq_new;
537
538static PyObject *
539statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
540{
541 PyStructSequence *result;
542 int i;
543
544 result = (PyStructSequence*)structseq_new(type, args, kwds);
545 if (!result)
546 return NULL;
547 /* If we have been initialized from a tuple,
548 st_?time might be set to None. Initialize it
549 from the int slots. */
550 for (i = 7; i <= 9; i++) {
551 if (result->ob_item[i+3] == Py_None) {
552 Py_DECREF(Py_None);
553 Py_INCREF(result->ob_item[i]);
554 result->ob_item[i+3] = result->ob_item[i];
555 }
556 }
557 return (PyObject*)result;
558}
559
560
561
562/* If true, st_?time is float. */
563static int _stat_float_times = 1;
564
565PyDoc_STRVAR_remove(stat_float_times__doc__,
566"stat_float_times([newval]) -> oldval\n\n\
567Determine whether os.[lf]stat represents time stamps as float objects.\n\
568If newval is True, future calls to stat() return floats, if it is False,\n\
569future calls return ints. \n\
570If newval is omitted, return the current setting.\n");
571
572static PyObject*
573stat_float_times(PyObject* self, PyObject *args)
574{
575 int newval = -1;
576 if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval))
577 return NULL;
578 if (newval == -1)
579 /* Return old value */
580 return PyBool_FromLong(_stat_float_times);
581 _stat_float_times = newval;
582 Py_INCREF(Py_None);
583 return Py_None;
584}
585
586static void
587fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
588{
589 PyObject *fval,*ival;
590#if SIZEOF_TIME_T > SIZEOF_LONG
591 ival = PyLong_FromLongLong((PY_LONG_LONG)sec);
592#else
593 ival = PyInt_FromLong((long)sec);
594#endif
595 if (!ival)
596 return;
597 if (_stat_float_times) {
598 fval = PyFloat_FromDouble(sec + 1e-9*nsec);
599 } else {
600 fval = ival;
601 Py_INCREF(fval);
602 }
603 PyStructSequence_SET_ITEM(v, index, ival);
604 PyStructSequence_SET_ITEM(v, index+3, fval);
605}
606
607/* pack a system stat C structure into the Python stat tuple
608 (used by posix_stat() and posix_fstat()) */
609static PyObject*
610_pystat_fromstructstat(STRUCT_STAT *st)
611{
612 unsigned long ansec, mnsec, cnsec;
613 PyObject *v = PyStructSequence_New(&StatResultType);
614 if (v == NULL)
615 return NULL;
616
617 PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long)st->st_mode));
618#ifdef HAVE_LARGEFILE_SUPPORT
619 PyStructSequence_SET_ITEM(v, 1,
620 PyLong_FromLongLong((PY_LONG_LONG)st->st_ino));
621#else
622 PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long)st->st_ino));
623#endif
624#ifdef MS_WINDOWS
625 PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));
626#else
627 PyStructSequence_SET_ITEM(v, 2, _PyInt_FromDev(st->st_dev));
628#endif
629 PyStructSequence_SET_ITEM(v, 3, PyInt_FromLong((long)st->st_nlink));
630#if defined(MS_WINDOWS)
631 PyStructSequence_SET_ITEM(v, 4, PyInt_FromLong(0));
632 PyStructSequence_SET_ITEM(v, 5, PyInt_FromLong(0));
633#else
634 PyStructSequence_SET_ITEM(v, 4, _PyInt_FromUid(st->st_uid));
635 PyStructSequence_SET_ITEM(v, 5, _PyInt_FromGid(st->st_gid));
636#endif
637#ifdef HAVE_LARGEFILE_SUPPORT
638 PyStructSequence_SET_ITEM(v, 6,
639 PyLong_FromLongLong((PY_LONG_LONG)st->st_size));
640#else
641 PyStructSequence_SET_ITEM(v, 6, PyInt_FromLong(st->st_size));
642#endif
643
644#if defined(HAVE_STAT_TV_NSEC)
645 ansec = st->st_atim.tv_nsec;
646 mnsec = st->st_mtim.tv_nsec;
647 cnsec = st->st_ctim.tv_nsec;
648#elif defined(HAVE_STAT_TV_NSEC2)
649 ansec = st->st_atimespec.tv_nsec;
650 mnsec = st->st_mtimespec.tv_nsec;
651 cnsec = st->st_ctimespec.tv_nsec;
652#elif defined(HAVE_STAT_NSEC)
653 ansec = st->st_atime_nsec;
654 mnsec = st->st_mtime_nsec;
655 cnsec = st->st_ctime_nsec;
656#else
657 ansec = mnsec = cnsec = 0;
658#endif
659 fill_time(v, 7, st->st_atime, ansec);
660 fill_time(v, 8, st->st_mtime, mnsec);
661 fill_time(v, 9, st->st_ctime, cnsec);
662
663#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
664 PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
665 PyInt_FromLong((long)st->st_blksize));
666#endif
667#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
668 PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
669 PyInt_FromLong((long)st->st_blocks));
670#endif
671#ifdef HAVE_STRUCT_STAT_ST_RDEV
672 PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
673 PyInt_FromLong((long)st->st_rdev));
674#endif
675#ifdef HAVE_STRUCT_STAT_ST_GEN
676 PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
677 PyInt_FromLong((long)st->st_gen));
678#endif
679#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
680 {
681 PyObject *val;
682 unsigned long bsec,bnsec;
683 bsec = (long)st->st_birthtime;
684#ifdef HAVE_STAT_TV_NSEC2
685 bnsec = st->st_birthtimespec.tv_nsec;
686#else
687 bnsec = 0;
688#endif
689 if (_stat_float_times) {
690 val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
691 } else {
692 val = PyInt_FromLong((long)bsec);
693 }
694 PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
695 val);
696 }
697#endif
698#ifdef HAVE_STRUCT_STAT_ST_FLAGS
699 PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
700 PyInt_FromLong((long)st->st_flags));
701#endif
702
703 if (PyErr_Occurred()) {
704 Py_DECREF(v);
705 return NULL;
706 }
707
708 return v;
709}
710
711static PyObject *
712posix_do_stat(PyObject *self, PyObject *args,
713 char *format,
714 int (*statfunc)(const char *, STRUCT_STAT *),
715 char *wformat,
716 int (*wstatfunc)(const Py_UNICODE *, STRUCT_STAT *))
717{
718 STRUCT_STAT st;
719 char *path = NULL; /* pass this to stat; do not free() it */
720 char *pathfree = NULL; /* this memory must be free'd */
721 int res;
722 PyObject *result;
723
724 if (!PyArg_ParseTuple(args, format,
725 Py_FileSystemDefaultEncoding, &path))
726 return NULL;
727 pathfree = path;
728
729 Py_BEGIN_ALLOW_THREADS
730 res = (*statfunc)(path, &st);
731 Py_END_ALLOW_THREADS
732
733 if (res != 0) {
734 result = posix_error_with_filename(pathfree);
735 }
736 else
737 result = _pystat_fromstructstat(&st);
738
739 PyMem_Free(pathfree);
740 return result;
741}
742
743/* POSIX methods */
744
745PyDoc_STRVAR_remove(posix_access__doc__,
746"access(path, mode) -> True if granted, False otherwise\n\n\
747Use the real uid/gid to test for access to a path. Note that most\n\
748operations will use the effective uid/gid, therefore this routine can\n\
749be used in a suid/sgid environment to test if the invoking user has the\n\
750specified access to the path. The mode argument can be F_OK to test\n\
751existence, or the inclusive-OR of R_OK, W_OK, and X_OK.");
752
753static PyObject *
754posix_access(PyObject *self, PyObject *args)
755{
756 char *path;
757 int mode;
758
759 int res;
760 if (!PyArg_ParseTuple(args, "eti:access",
761 Py_FileSystemDefaultEncoding, &path, &mode))
762 return NULL;
763 Py_BEGIN_ALLOW_THREADS
764 res = access(path, mode);
765 Py_END_ALLOW_THREADS
766 PyMem_Free(path);
767 return PyBool_FromLong(res == 0);
768}
769
770PyDoc_STRVAR_remove(posix_chdir__doc__,
771"chdir(path)\n\n\
772Change the current working directory to the specified path.");
773
774static PyObject *
775posix_chdir(PyObject *self, PyObject *args)
776{
777 return posix_1str(args, "et:chdir", chdir);
778}
779
780/* OVM_MAIN: Do we need this Solaris workaround??? */
781
782#ifdef HAVE_GETCWD
783PyDoc_STRVAR_remove(posix_getcwd__doc__,
784"getcwd() -> path\n\n\
785Return a string representing the current working directory.");
786
787#if (defined(__sun) && defined(__SVR4)) || \
788 defined(__OpenBSD__) || \
789 defined(__NetBSD__)
790/* Issue 9185: getcwd() returns NULL/ERANGE indefinitely. */
791static PyObject *
792posix_getcwd(PyObject *self, PyObject *noargs)
793{
794 char buf[PATH_MAX+2];
795 char *res;
796
797 Py_BEGIN_ALLOW_THREADS
798 res = getcwd(buf, sizeof buf);
799 Py_END_ALLOW_THREADS
800
801 if (res == NULL)
802 return posix_error();
803
804 return PyString_FromString(buf);
805}
806#else
807static PyObject *
808posix_getcwd(PyObject *self, PyObject *noargs)
809{
810 int bufsize_incr = 1024;
811 int bufsize = 0;
812 char *tmpbuf = NULL;
813 char *res = NULL;
814 PyObject *dynamic_return;
815
816 Py_BEGIN_ALLOW_THREADS
817 do {
818 bufsize = bufsize + bufsize_incr;
819 tmpbuf = malloc(bufsize);
820 if (tmpbuf == NULL) {
821 break;
822 }
823 res = getcwd(tmpbuf, bufsize);
824
825 if (res == NULL) {
826 free(tmpbuf);
827 }
828 } while ((res == NULL) && (errno == ERANGE));
829 Py_END_ALLOW_THREADS
830
831 if (res == NULL)
832 return posix_error();
833
834 dynamic_return = PyString_FromString(tmpbuf);
835 free(tmpbuf);
836
837 return dynamic_return;
838}
839#endif /* getcwd() NULL/ERANGE workaround. */
840#endif /* HAVE_GETCWD */
841
842PyDoc_STRVAR_remove(posix_listdir__doc__,
843"listdir(path) -> list_of_strings\n\n\
844Return a list containing the names of the entries in the directory.\n\
845\n\
846 path: path of directory to list\n\
847\n\
848The list is in arbitrary order. It does not include the special\n\
849entries '.' and '..' even if they are present in the directory.");
850
851static PyObject *
852posix_listdir(PyObject *self, PyObject *args)
853{
854 char *name = NULL;
855 PyObject *d, *v;
856 DIR *dirp;
857 struct dirent *ep;
858
859 errno = 0;
860 if (!PyArg_ParseTuple(args, "et:listdir", Py_FileSystemDefaultEncoding, &name))
861 return NULL;
862 Py_BEGIN_ALLOW_THREADS
863 dirp = opendir(name);
864 Py_END_ALLOW_THREADS
865 if (dirp == NULL) {
866 return posix_error_with_allocated_filename(name);
867 }
868 if ((d = PyList_New(0)) == NULL) {
869 Py_BEGIN_ALLOW_THREADS
870 closedir(dirp);
871 Py_END_ALLOW_THREADS
872 PyMem_Free(name);
873 return NULL;
874 }
875 for (;;) {
876 errno = 0;
877 Py_BEGIN_ALLOW_THREADS
878 ep = readdir(dirp);
879 Py_END_ALLOW_THREADS
880 if (ep == NULL) {
881 if (errno == 0) {
882 break;
883 } else {
884 Py_BEGIN_ALLOW_THREADS
885 closedir(dirp);
886 Py_END_ALLOW_THREADS
887 Py_DECREF(d);
888 return posix_error_with_allocated_filename(name);
889 }
890 }
891 if (ep->d_name[0] == '.' &&
892 (NAMLEN(ep) == 1 ||
893 (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
894 continue;
895 v = PyString_FromStringAndSize(ep->d_name, NAMLEN(ep));
896 if (v == NULL) {
897 Py_DECREF(d);
898 d = NULL;
899 break;
900 }
901 if (PyList_Append(d, v) != 0) {
902 Py_DECREF(v);
903 Py_DECREF(d);
904 d = NULL;
905 break;
906 }
907 Py_DECREF(v);
908 }
909 Py_BEGIN_ALLOW_THREADS
910 closedir(dirp);
911 Py_END_ALLOW_THREADS
912 PyMem_Free(name);
913
914 return d;
915} /* end of posix_listdir */
916
917PyDoc_STRVAR_remove(posix_mkdir__doc__,
918"mkdir(path [, mode=0777])\n\n\
919Create a directory.");
920
921static PyObject *
922posix_mkdir(PyObject *self, PyObject *args)
923{
924 int res;
925 char *path = NULL;
926 int mode = 0777;
927
928 if (!PyArg_ParseTuple(args, "et|i:mkdir",
929 Py_FileSystemDefaultEncoding, &path, &mode))
930 return NULL;
931 Py_BEGIN_ALLOW_THREADS
932 res = mkdir(path, mode);
933 Py_END_ALLOW_THREADS
934 if (res < 0)
935 return posix_error_with_allocated_filename(path);
936 PyMem_Free(path);
937 Py_INCREF(Py_None);
938 return Py_None;
939}
940
941
942PyDoc_STRVAR_remove(posix_rename__doc__,
943"rename(old, new)\n\n\
944Rename a file or directory.");
945
946static PyObject *
947posix_rename(PyObject *self, PyObject *args)
948{
949 return posix_2str(args, "etet:rename", rename);
950}
951
952
953PyDoc_STRVAR_remove(posix_rmdir__doc__,
954"rmdir(path)\n\n\
955Remove a directory.");
956
957static PyObject *
958posix_rmdir(PyObject *self, PyObject *args)
959{
960 return posix_1str(args, "et:rmdir", rmdir);
961}
962
963
964PyDoc_STRVAR_remove(posix_stat__doc__,
965"stat(path) -> stat result\n\n\
966Perform a stat system call on the given path.");
967
968static PyObject *
969posix_stat(PyObject *self, PyObject *args)
970{
971 return posix_do_stat(self, args, "et:stat", STAT, NULL, NULL);
972}
973
974PyDoc_STRVAR_remove(posix_umask__doc__,
975"umask(new_mask) -> old_mask\n\n\
976Set the current numeric umask and return the previous umask.");
977
978static PyObject *
979posix_umask(PyObject *self, PyObject *args)
980{
981 int i;
982 if (!PyArg_ParseTuple(args, "i:umask", &i))
983 return NULL;
984 i = (int)umask(i);
985 if (i < 0)
986 return posix_error();
987 return PyInt_FromLong((long)i);
988}
989
990
991PyDoc_STRVAR_remove(posix_unlink__doc__,
992"unlink(path)\n\n\
993Remove a file (same as remove(path)).");
994
995PyDoc_STRVAR_remove(posix_remove__doc__,
996"remove(path)\n\n\
997Remove a file (same as unlink(path)).");
998
999static PyObject *
1000posix_unlink(PyObject *self, PyObject *args)
1001{
1002 return posix_1str(args, "et:remove", unlink);
1003}
1004
1005
1006#ifdef HAVE_UNAME
1007PyDoc_STRVAR_remove(posix_uname__doc__,
1008"uname() -> (sysname, nodename, release, version, machine)\n\n\
1009Return a tuple identifying the current operating system.");
1010
1011static PyObject *
1012posix_uname(PyObject *self, PyObject *noargs)
1013{
1014 struct utsname u;
1015 int res;
1016
1017 Py_BEGIN_ALLOW_THREADS
1018 res = uname(&u);
1019 Py_END_ALLOW_THREADS
1020 if (res < 0)
1021 return posix_error();
1022 return Py_BuildValue("(sssss)",
1023 u.sysname,
1024 u.nodename,
1025 u.release,
1026 u.version,
1027 u.machine);
1028}
1029#endif /* HAVE_UNAME */
1030
1031/* Process operations */
1032
1033PyDoc_STRVAR_remove(posix__exit__doc__,
1034"_exit(status)\n\n\
1035Exit to the system with specified status, without normal exit processing.");
1036
1037static PyObject *
1038posix__exit(PyObject *self, PyObject *args)
1039{
1040 int sts;
1041 if (!PyArg_ParseTuple(args, "i:_exit", &sts))
1042 return NULL;
1043 _exit(sts);
1044 return NULL; /* Make gcc -Wall happy */
1045}
1046
1047#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV)
1048static void
1049free_string_array(char **array, Py_ssize_t count)
1050{
1051 Py_ssize_t i;
1052 for (i = 0; i < count; i++)
1053 PyMem_Free(array[i]);
1054 PyMem_DEL(array);
1055}
1056#endif
1057
1058
1059#ifdef HAVE_EXECV
1060PyDoc_STRVAR_remove(posix_execv__doc__,
1061"execv(path, args)\n\n\
1062Execute an executable path with arguments, replacing current process.\n\
1063\n\
1064 path: path of executable file\n\
1065 args: tuple or list of strings");
1066
1067static PyObject *
1068posix_execv(PyObject *self, PyObject *args)
1069{
1070 char *path;
1071 PyObject *argv;
1072 char **argvlist;
1073 Py_ssize_t i, argc;
1074 PyObject *(*getitem)(PyObject *, Py_ssize_t);
1075
1076 /* execv has two arguments: (path, argv), where
1077 argv is a list or tuple of strings. */
1078
1079 if (!PyArg_ParseTuple(args, "etO:execv",
1080 Py_FileSystemDefaultEncoding,
1081 &path, &argv))
1082 return NULL;
1083 if (PyList_Check(argv)) {
1084 argc = PyList_Size(argv);
1085 getitem = PyList_GetItem;
1086 }
1087 else if (PyTuple_Check(argv)) {
1088 argc = PyTuple_Size(argv);
1089 getitem = PyTuple_GetItem;
1090 }
1091 else {
1092 PyErr_SetString(PyExc_TypeError, "execv() arg 2 must be a tuple or list");
1093 PyMem_Free(path);
1094 return NULL;
1095 }
1096 if (argc < 1) {
1097 PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
1098 PyMem_Free(path);
1099 return NULL;
1100 }
1101
1102 argvlist = PyMem_NEW(char *, argc+1);
1103 if (argvlist == NULL) {
1104 PyMem_Free(path);
1105 return PyErr_NoMemory();
1106 }
1107 for (i = 0; i < argc; i++) {
1108 if (!PyArg_Parse((*getitem)(argv, i), "et",
1109 Py_FileSystemDefaultEncoding,
1110 &argvlist[i])) {
1111 free_string_array(argvlist, i);
1112 PyErr_SetString(PyExc_TypeError,
1113 "execv() arg 2 must contain only strings");
1114 PyMem_Free(path);
1115 return NULL;
1116
1117 }
1118 }
1119 argvlist[argc] = NULL;
1120
1121 execv(path, argvlist);
1122
1123 /* If we get here it's definitely an error */
1124
1125 free_string_array(argvlist, argc);
1126 PyMem_Free(path);
1127 return posix_error();
1128}
1129
1130
1131PyDoc_STRVAR_remove(posix_execve__doc__,
1132"execve(path, args, env)\n\n\
1133Execute a path with arguments and environment, replacing current process.\n\
1134\n\
1135 path: path of executable file\n\
1136 args: tuple or list of arguments\n\
1137 env: dictionary of strings mapping to strings");
1138
1139static PyObject *
1140posix_execve(PyObject *self, PyObject *args)
1141{
1142 char *path;
1143 PyObject *argv, *env;
1144 char **argvlist;
1145 char **envlist;
1146 PyObject *key, *val, *keys=NULL, *vals=NULL;
1147 Py_ssize_t i, pos, argc, envc;
1148 PyObject *(*getitem)(PyObject *, Py_ssize_t);
1149 Py_ssize_t lastarg = 0;
1150
1151 /* execve has three arguments: (path, argv, env), where
1152 argv is a list or tuple of strings and env is a dictionary
1153 like posix.environ. */
1154
1155 if (!PyArg_ParseTuple(args, "etOO:execve",
1156 Py_FileSystemDefaultEncoding,
1157 &path, &argv, &env))
1158 return NULL;
1159 if (PyList_Check(argv)) {
1160 argc = PyList_Size(argv);
1161 getitem = PyList_GetItem;
1162 }
1163 else if (PyTuple_Check(argv)) {
1164 argc = PyTuple_Size(argv);
1165 getitem = PyTuple_GetItem;
1166 }
1167 else {
1168 PyErr_SetString(PyExc_TypeError,
1169 "execve() arg 2 must be a tuple or list");
1170 goto fail_0;
1171 }
1172 if (!PyMapping_Check(env)) {
1173 PyErr_SetString(PyExc_TypeError,
1174 "execve() arg 3 must be a mapping object");
1175 goto fail_0;
1176 }
1177
1178 argvlist = PyMem_NEW(char *, argc+1);
1179 if (argvlist == NULL) {
1180 PyErr_NoMemory();
1181 goto fail_0;
1182 }
1183 for (i = 0; i < argc; i++) {
1184 if (!PyArg_Parse((*getitem)(argv, i),
1185 "et;execve() arg 2 must contain only strings",
1186 Py_FileSystemDefaultEncoding,
1187 &argvlist[i]))
1188 {
1189 lastarg = i;
1190 goto fail_1;
1191 }
1192 }
1193 lastarg = argc;
1194 argvlist[argc] = NULL;
1195
1196 i = PyMapping_Size(env);
1197 if (i < 0)
1198 goto fail_1;
1199 envlist = PyMem_NEW(char *, i + 1);
1200 if (envlist == NULL) {
1201 PyErr_NoMemory();
1202 goto fail_1;
1203 }
1204 envc = 0;
1205 keys = PyMapping_Keys(env);
1206 vals = PyMapping_Values(env);
1207 if (!keys || !vals)
1208 goto fail_2;
1209 if (!PyList_Check(keys) || !PyList_Check(vals)) {
1210 PyErr_SetString(PyExc_TypeError,
1211 "execve(): env.keys() or env.values() is not a list");
1212 goto fail_2;
1213 }
1214
1215 for (pos = 0; pos < i; pos++) {
1216 char *p, *k, *v;
1217 size_t len;
1218
1219 key = PyList_GetItem(keys, pos);
1220 val = PyList_GetItem(vals, pos);
1221 if (!key || !val)
1222 goto fail_2;
1223
1224 if (!PyArg_Parse(
1225 key,
1226 "s;execve() arg 3 contains a non-string key",
1227 &k) ||
1228 !PyArg_Parse(
1229 val,
1230 "s;execve() arg 3 contains a non-string value",
1231 &v))
1232 {
1233 goto fail_2;
1234 }
1235
1236 len = PyString_Size(key) + PyString_Size(val) + 2;
1237 p = PyMem_NEW(char, len);
1238 if (p == NULL) {
1239 PyErr_NoMemory();
1240 goto fail_2;
1241 }
1242 PyOS_snprintf(p, len, "%s=%s", k, v);
1243 envlist[envc++] = p;
1244 }
1245 envlist[envc] = 0;
1246
1247 execve(path, argvlist, envlist);
1248
1249 /* If we get here it's definitely an error */
1250
1251 (void) posix_error();
1252
1253 fail_2:
1254 while (--envc >= 0)
1255 PyMem_DEL(envlist[envc]);
1256 PyMem_DEL(envlist);
1257 fail_1:
1258 free_string_array(argvlist, lastarg);
1259 Py_XDECREF(vals);
1260 Py_XDECREF(keys);
1261 fail_0:
1262 PyMem_Free(path);
1263 return NULL;
1264}
1265#endif /* HAVE_EXECV */
1266
1267#ifdef HAVE_FORK
1268PyDoc_STRVAR_remove(posix_fork__doc__,
1269"fork() -> pid\n\n\
1270Fork a child process.\n\
1271Return 0 to child process and PID of child to parent process.");
1272
1273static PyObject *
1274posix_fork(PyObject *self, PyObject *noargs)
1275{
1276 pid_t pid;
1277 int result = 0;
1278 _PyImport_AcquireLock();
1279 pid = fork();
1280 if (pid == 0) {
1281 /* child: this clobbers and resets the import lock. */
1282 PyOS_AfterFork();
1283 } else {
1284 /* parent: release the import lock. */
1285 result = _PyImport_ReleaseLock();
1286 }
1287 if (pid == -1)
1288 return posix_error();
1289 if (result < 0) {
1290 /* Don't clobber the OSError if the fork failed. */
1291 PyErr_SetString(PyExc_RuntimeError,
1292 "not holding the import lock");
1293 return NULL;
1294 }
1295 return PyLong_FromPid(pid);
1296}
1297#endif
1298
1299#ifdef HAVE_GETEGID
1300PyDoc_STRVAR_remove(posix_getegid__doc__,
1301"getegid() -> egid\n\n\
1302Return the current process's effective group id.");
1303
1304static PyObject *
1305posix_getegid(PyObject *self, PyObject *noargs)
1306{
1307 return _PyInt_FromGid(getegid());
1308}
1309#endif
1310
1311
1312#ifdef HAVE_GETEUID
1313PyDoc_STRVAR_remove(posix_geteuid__doc__,
1314"geteuid() -> euid\n\n\
1315Return the current process's effective user id.");
1316
1317static PyObject *
1318posix_geteuid(PyObject *self, PyObject *noargs)
1319{
1320 return _PyInt_FromUid(geteuid());
1321}
1322#endif
1323
1324
1325#ifdef HAVE_GETGID
1326PyDoc_STRVAR_remove(posix_getgid__doc__,
1327"getgid() -> gid\n\n\
1328Return the current process's group id.");
1329
1330static PyObject *
1331posix_getgid(PyObject *self, PyObject *noargs)
1332{
1333 return _PyInt_FromGid(getgid());
1334}
1335#endif
1336
1337
1338PyDoc_STRVAR_remove(posix_getpid__doc__,
1339"getpid() -> pid\n\n\
1340Return the current process id");
1341
1342static PyObject *
1343posix_getpid(PyObject *self, PyObject *noargs)
1344{
1345 return PyLong_FromPid(getpid());
1346}
1347
1348#ifdef HAVE_GETPGID
1349PyDoc_STRVAR_remove(posix_getpgid__doc__,
1350"getpgid(pid) -> pgid\n\n\
1351Call the system call getpgid().");
1352
1353static PyObject *
1354posix_getpgid(PyObject *self, PyObject *args)
1355{
1356 pid_t pid, pgid;
1357 if (!PyArg_ParseTuple(args, PARSE_PID ":getpgid", &pid))
1358 return NULL;
1359 pgid = getpgid(pid);
1360 if (pgid < 0)
1361 return posix_error();
1362 return PyLong_FromPid(pgid);
1363}
1364#endif /* HAVE_GETPGID */
1365
1366
1367#ifdef HAVE_GETPPID
1368PyDoc_STRVAR_remove(posix_getppid__doc__,
1369"getppid() -> ppid\n\n\
1370Return the parent's process id.");
1371
1372static PyObject *
1373posix_getppid(PyObject *self, PyObject *noargs)
1374{
1375 return PyLong_FromPid(getppid());
1376}
1377#endif
1378
1379
1380#ifdef HAVE_GETUID
1381PyDoc_STRVAR_remove(posix_getuid__doc__,
1382"getuid() -> uid\n\n\
1383Return the current process's user id.");
1384
1385static PyObject *
1386posix_getuid(PyObject *self, PyObject *noargs)
1387{
1388 return _PyInt_FromUid(getuid());
1389}
1390#endif
1391
1392
1393#ifdef HAVE_KILL
1394PyDoc_STRVAR_remove(posix_kill__doc__,
1395"kill(pid, sig)\n\n\
1396Kill a process with a signal.");
1397
1398static PyObject *
1399posix_kill(PyObject *self, PyObject *args)
1400{
1401 pid_t pid;
1402 int sig;
1403 if (!PyArg_ParseTuple(args, PARSE_PID "i:kill", &pid, &sig))
1404 return NULL;
1405 if (kill(pid, sig) == -1)
1406 return posix_error();
1407 Py_INCREF(Py_None);
1408 return Py_None;
1409}
1410#endif
1411
1412#ifdef HAVE_KILLPG
1413PyDoc_STRVAR_remove(posix_killpg__doc__,
1414"killpg(pgid, sig)\n\n\
1415Kill a process group with a signal.");
1416
1417static PyObject *
1418posix_killpg(PyObject *self, PyObject *args)
1419{
1420 int sig;
1421 pid_t pgid;
1422 /* XXX some man pages make the `pgid` parameter an int, others
1423 a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
1424 take the same type. Moreover, pid_t is always at least as wide as
1425 int (else compilation of this module fails), which is safe. */
1426 if (!PyArg_ParseTuple(args, PARSE_PID "i:killpg", &pgid, &sig))
1427 return NULL;
1428 if (killpg(pgid, sig) == -1)
1429 return posix_error();
1430 Py_INCREF(Py_None);
1431 return Py_None;
1432}
1433#endif
1434
1435#ifdef HAVE_SETUID
1436PyDoc_STRVAR_remove(posix_setuid__doc__,
1437"setuid(uid)\n\n\
1438Set the current process's user id.");
1439
1440static PyObject *
1441posix_setuid(PyObject *self, PyObject *args)
1442{
1443 uid_t uid;
1444 if (!PyArg_ParseTuple(args, "O&:setuid", _Py_Uid_Converter, &uid))
1445 return NULL;
1446 if (setuid(uid) < 0)
1447 return posix_error();
1448 Py_INCREF(Py_None);
1449 return Py_None;
1450}
1451#endif /* HAVE_SETUID */
1452
1453
1454#ifdef HAVE_SETEUID
1455PyDoc_STRVAR_remove(posix_seteuid__doc__,
1456"seteuid(uid)\n\n\
1457Set the current process's effective user id.");
1458
1459static PyObject *
1460posix_seteuid (PyObject *self, PyObject *args)
1461{
1462 uid_t euid;
1463 if (!PyArg_ParseTuple(args, "O&:seteuid", _Py_Uid_Converter, &euid))
1464 return NULL;
1465 if (seteuid(euid) < 0) {
1466 return posix_error();
1467 } else {
1468 Py_INCREF(Py_None);
1469 return Py_None;
1470 }
1471}
1472#endif /* HAVE_SETEUID */
1473
1474#ifdef HAVE_SETEGID
1475PyDoc_STRVAR_remove(posix_setegid__doc__,
1476"setegid(gid)\n\n\
1477Set the current process's effective group id.");
1478
1479static PyObject *
1480posix_setegid (PyObject *self, PyObject *args)
1481{
1482 gid_t egid;
1483 if (!PyArg_ParseTuple(args, "O&:setegid", _Py_Gid_Converter, &egid))
1484 return NULL;
1485 if (setegid(egid) < 0) {
1486 return posix_error();
1487 } else {
1488 Py_INCREF(Py_None);
1489 return Py_None;
1490 }
1491}
1492#endif /* HAVE_SETEGID */
1493
1494#ifdef HAVE_SETREUID
1495PyDoc_STRVAR_remove(posix_setreuid__doc__,
1496"setreuid(ruid, euid)\n\n\
1497Set the current process's real and effective user ids.");
1498
1499static PyObject *
1500posix_setreuid (PyObject *self, PyObject *args)
1501{
1502 uid_t ruid, euid;
1503 if (!PyArg_ParseTuple(args, "O&O&:setreuid",
1504 _Py_Uid_Converter, &ruid,
1505 _Py_Uid_Converter, &euid))
1506 return NULL;
1507 if (setreuid(ruid, euid) < 0) {
1508 return posix_error();
1509 } else {
1510 Py_INCREF(Py_None);
1511 return Py_None;
1512 }
1513}
1514#endif /* HAVE_SETREUID */
1515
1516#ifdef HAVE_SETREGID
1517PyDoc_STRVAR_remove(posix_setregid__doc__,
1518"setregid(rgid, egid)\n\n\
1519Set the current process's real and effective group ids.");
1520
1521static PyObject *
1522posix_setregid (PyObject *self, PyObject *args)
1523{
1524 gid_t rgid, egid;
1525 if (!PyArg_ParseTuple(args, "O&O&:setregid",
1526 _Py_Gid_Converter, &rgid,
1527 _Py_Gid_Converter, &egid))
1528 return NULL;
1529 if (setregid(rgid, egid) < 0) {
1530 return posix_error();
1531 } else {
1532 Py_INCREF(Py_None);
1533 return Py_None;
1534 }
1535}
1536#endif /* HAVE_SETREGID */
1537
1538#ifdef HAVE_SETGID
1539PyDoc_STRVAR_remove(posix_setgid__doc__,
1540"setgid(gid)\n\n\
1541Set the current process's group id.");
1542
1543static PyObject *
1544posix_setgid(PyObject *self, PyObject *args)
1545{
1546 gid_t gid;
1547 if (!PyArg_ParseTuple(args, "O&:setgid", _Py_Gid_Converter, &gid))
1548 return NULL;
1549 if (setgid(gid) < 0)
1550 return posix_error();
1551 Py_INCREF(Py_None);
1552 return Py_None;
1553}
1554#endif /* HAVE_SETGID */
1555
1556#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
1557static PyObject *
1558wait_helper(pid_t pid, int status, struct rusage *ru)
1559{
1560 PyObject *result;
1561 static PyObject *struct_rusage;
1562
1563 if (pid == -1)
1564 return posix_error();
1565
1566 if (struct_rusage == NULL) {
1567 PyObject *m = PyImport_ImportModuleNoBlock("resource");
1568 if (m == NULL)
1569 return NULL;
1570 struct_rusage = PyObject_GetAttrString(m, "struct_rusage");
1571 Py_DECREF(m);
1572 if (struct_rusage == NULL)
1573 return NULL;
1574 }
1575
1576 /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
1577 result = PyStructSequence_New((PyTypeObject*) struct_rusage);
1578 if (!result)
1579 return NULL;
1580
1581#ifndef doubletime
1582#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
1583#endif
1584
1585 PyStructSequence_SET_ITEM(result, 0,
1586 PyFloat_FromDouble(doubletime(ru->ru_utime)));
1587 PyStructSequence_SET_ITEM(result, 1,
1588 PyFloat_FromDouble(doubletime(ru->ru_stime)));
1589#define SET_INT(result, index, value)\
1590 PyStructSequence_SET_ITEM(result, index, PyInt_FromLong(value))
1591 SET_INT(result, 2, ru->ru_maxrss);
1592 SET_INT(result, 3, ru->ru_ixrss);
1593 SET_INT(result, 4, ru->ru_idrss);
1594 SET_INT(result, 5, ru->ru_isrss);
1595 SET_INT(result, 6, ru->ru_minflt);
1596 SET_INT(result, 7, ru->ru_majflt);
1597 SET_INT(result, 8, ru->ru_nswap);
1598 SET_INT(result, 9, ru->ru_inblock);
1599 SET_INT(result, 10, ru->ru_oublock);
1600 SET_INT(result, 11, ru->ru_msgsnd);
1601 SET_INT(result, 12, ru->ru_msgrcv);
1602 SET_INT(result, 13, ru->ru_nsignals);
1603 SET_INT(result, 14, ru->ru_nvcsw);
1604 SET_INT(result, 15, ru->ru_nivcsw);
1605#undef SET_INT
1606
1607 if (PyErr_Occurred()) {
1608 Py_DECREF(result);
1609 return NULL;
1610 }
1611
1612 return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
1613}
1614#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
1615
1616#ifdef HAVE_WAIT3
1617PyDoc_STRVAR_remove(posix_wait3__doc__,
1618"wait3(options) -> (pid, status, rusage)\n\n\
1619Wait for completion of a child process.");
1620
1621static PyObject *
1622posix_wait3(PyObject *self, PyObject *args)
1623{
1624 pid_t pid;
1625 int options;
1626 struct rusage ru;
1627 WAIT_TYPE status;
1628 WAIT_STATUS_INT(status) = 0;
1629
1630 if (!PyArg_ParseTuple(args, "i:wait3", &options))
1631 return NULL;
1632
1633 Py_BEGIN_ALLOW_THREADS
1634 pid = wait3(&status, options, &ru);
1635 Py_END_ALLOW_THREADS
1636
1637 return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
1638}
1639#endif /* HAVE_WAIT3 */
1640
1641#ifdef HAVE_WAIT4
1642PyDoc_STRVAR_remove(posix_wait4__doc__,
1643"wait4(pid, options) -> (pid, status, rusage)\n\n\
1644Wait for completion of a given child process.");
1645
1646static PyObject *
1647posix_wait4(PyObject *self, PyObject *args)
1648{
1649 pid_t pid;
1650 int options;
1651 struct rusage ru;
1652 WAIT_TYPE status;
1653 WAIT_STATUS_INT(status) = 0;
1654
1655 if (!PyArg_ParseTuple(args, PARSE_PID "i:wait4", &pid, &options))
1656 return NULL;
1657
1658 Py_BEGIN_ALLOW_THREADS
1659 pid = wait4(pid, &status, options, &ru);
1660 Py_END_ALLOW_THREADS
1661
1662 return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
1663}
1664#endif /* HAVE_WAIT4 */
1665
1666#ifdef HAVE_WAITPID
1667PyDoc_STRVAR_remove(posix_waitpid__doc__,
1668"waitpid(pid, options) -> (pid, status)\n\n\
1669Wait for completion of a given child process.");
1670
1671// NO PATCH HERE FOR EINTR !!! See core/process.py.
1672static PyObject *
1673posix_waitpid(PyObject *self, PyObject *args)
1674{
1675 pid_t pid;
1676 int options;
1677 WAIT_TYPE status;
1678 WAIT_STATUS_INT(status) = 0;
1679
1680 if (!PyArg_ParseTuple(args, PARSE_PID "i:waitpid", &pid, &options))
1681 return NULL;
1682 Py_BEGIN_ALLOW_THREADS
1683 pid = waitpid(pid, &status, options);
1684 Py_END_ALLOW_THREADS
1685 if (pid == -1)
1686 return posix_error();
1687
1688 return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
1689}
1690#endif /* HAVE_WAITPID */
1691
1692#ifdef HAVE_WAIT
1693PyDoc_STRVAR_remove(posix_wait__doc__,
1694"wait() -> (pid, status)\n\n\
1695Wait for completion of a child process.");
1696
1697static PyObject *
1698posix_wait(PyObject *self, PyObject *noargs)
1699{
1700 pid_t pid;
1701 WAIT_TYPE status;
1702 WAIT_STATUS_INT(status) = 0;
1703
1704 // OVM_MAIN patch: Retry on EINTR.
1705 while (1) {
1706 Py_BEGIN_ALLOW_THREADS
1707 pid = wait(&status);
1708 Py_END_ALLOW_THREADS
1709
1710 if (pid >= 0) { // success
1711 break;
1712 } else {
1713 if (PyErr_CheckSignals()) {
1714 return NULL; // Propagate KeyboardInterrupt
1715 }
1716 if (errno != EINTR) { // e.g. ECHILD
1717 return posix_error();
1718 }
1719 }
1720 // Otherwise, try again on EINTR.
1721 }
1722
1723 return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
1724}
1725#endif
1726
1727
1728PyDoc_STRVAR_remove(posix_lstat__doc__,
1729"lstat(path) -> stat result\n\n\
1730Like stat(path), but do not follow symbolic links.");
1731
1732static PyObject *
1733posix_lstat(PyObject *self, PyObject *args)
1734{
1735#ifdef HAVE_LSTAT
1736 return posix_do_stat(self, args, "et:lstat", lstat, NULL, NULL);
1737#else /* !HAVE_LSTAT */
1738 return posix_do_stat(self, args, "et:lstat", STAT, NULL, NULL);
1739#endif /* !HAVE_LSTAT */
1740}
1741
1742
1743#ifdef HAVE_READLINK
1744PyDoc_STRVAR_remove(posix_readlink__doc__,
1745"readlink(path) -> path\n\n\
1746Return a string representing the path to which the symbolic link points.");
1747
1748static PyObject *
1749posix_readlink(PyObject *self, PyObject *args)
1750{
1751 PyObject* v;
1752 char buf[MAXPATHLEN];
1753 char *path;
1754 int n;
1755#ifdef Py_USING_UNICODE
1756 int arg_is_unicode = 0;
1757#endif
1758
1759 if (!PyArg_ParseTuple(args, "et:readlink",
1760 Py_FileSystemDefaultEncoding, &path))
1761 return NULL;
1762#ifdef Py_USING_UNICODE
1763 v = PySequence_GetItem(args, 0);
1764 if (v == NULL) {
1765 PyMem_Free(path);
1766 return NULL;
1767 }
1768
1769 if (PyUnicode_Check(v)) {
1770 arg_is_unicode = 1;
1771 }
1772 Py_DECREF(v);
1773#endif
1774
1775 Py_BEGIN_ALLOW_THREADS
1776 n = readlink(path, buf, (int) sizeof buf);
1777 Py_END_ALLOW_THREADS
1778 if (n < 0)
1779 return posix_error_with_allocated_filename(path);
1780
1781 PyMem_Free(path);
1782 v = PyString_FromStringAndSize(buf, n);
1783#ifdef Py_USING_UNICODE
1784 if (arg_is_unicode) {
1785 PyObject *w;
1786
1787 w = PyUnicode_FromEncodedObject(v,
1788 Py_FileSystemDefaultEncoding,
1789 "strict");
1790 if (w != NULL) {
1791 Py_DECREF(v);
1792 v = w;
1793 }
1794 else {
1795 /* fall back to the original byte string, as
1796 discussed in patch #683592 */
1797 PyErr_Clear();
1798 }
1799 }
1800#endif
1801 return v;
1802}
1803#endif /* HAVE_READLINK */
1804
1805
1806#ifdef HAVE_SYMLINK
1807PyDoc_STRVAR_remove(posix_symlink__doc__,
1808"symlink(src, dst)\n\n\
1809Create a symbolic link pointing to src named dst.");
1810
1811static PyObject *
1812posix_symlink(PyObject *self, PyObject *args)
1813{
1814 return posix_2str(args, "etet:symlink", symlink);
1815}
1816#endif /* HAVE_SYMLINK */
1817
1818
1819#ifdef HAVE_TIMES
1820#define NEED_TICKS_PER_SECOND
1821static long ticks_per_second = -1;
1822static PyObject *
1823posix_times(PyObject *self, PyObject *noargs)
1824{
1825 struct tms t;
1826 clock_t c;
1827 errno = 0;
1828 c = times(&t);
1829 if (c == (clock_t) -1)
1830 return posix_error();
1831 return Py_BuildValue("ddddd",
1832 (double)t.tms_utime / ticks_per_second,
1833 (double)t.tms_stime / ticks_per_second,
1834 (double)t.tms_cutime / ticks_per_second,
1835 (double)t.tms_cstime / ticks_per_second,
1836 (double)c / ticks_per_second);
1837}
1838#endif /* HAVE_TIMES */
1839
1840
1841#ifdef HAVE_TIMES
1842PyDoc_STRVAR_remove(posix_times__doc__,
1843"times() -> (utime, stime, cutime, cstime, elapsed_time)\n\n\
1844Return a tuple of floating point numbers indicating process times.");
1845#endif
1846
1847
1848#ifdef HAVE_GETSID
1849PyDoc_STRVAR_remove(posix_getsid__doc__,
1850"getsid(pid) -> sid\n\n\
1851Call the system call getsid().");
1852
1853static PyObject *
1854posix_getsid(PyObject *self, PyObject *args)
1855{
1856 pid_t pid;
1857 int sid;
1858 if (!PyArg_ParseTuple(args, PARSE_PID ":getsid", &pid))
1859 return NULL;
1860 sid = getsid(pid);
1861 if (sid < 0)
1862 return posix_error();
1863 return PyInt_FromLong((long)sid);
1864}
1865#endif /* HAVE_GETSID */
1866
1867
1868#ifdef HAVE_SETSID
1869PyDoc_STRVAR_remove(posix_setsid__doc__,
1870"setsid()\n\n\
1871Call the system call setsid().");
1872
1873static PyObject *
1874posix_setsid(PyObject *self, PyObject *noargs)
1875{
1876 if (setsid() < 0)
1877 return posix_error();
1878 Py_INCREF(Py_None);
1879 return Py_None;
1880}
1881#endif /* HAVE_SETSID */
1882
1883#ifdef HAVE_SETPGID
1884PyDoc_STRVAR_remove(posix_setpgid__doc__,
1885"setpgid(pid, pgrp)\n\n\
1886Call the system call setpgid().");
1887
1888static PyObject *
1889posix_setpgid(PyObject *self, PyObject *args)
1890{
1891 pid_t pid;
1892 int pgrp;
1893 if (!PyArg_ParseTuple(args, PARSE_PID "i:setpgid", &pid, &pgrp))
1894 return NULL;
1895 if (setpgid(pid, pgrp) < 0)
1896 return posix_error();
1897 Py_INCREF(Py_None);
1898 return Py_None;
1899}
1900#endif /* HAVE_SETPGID */
1901
1902
1903#ifdef HAVE_TCGETPGRP
1904PyDoc_STRVAR_remove(posix_tcgetpgrp__doc__,
1905"tcgetpgrp(fd) -> pgid\n\n\
1906Return the process group associated with the terminal given by a fd.");
1907
1908static PyObject *
1909posix_tcgetpgrp(PyObject *self, PyObject *args)
1910{
1911 int fd;
1912 pid_t pgid;
1913 if (!PyArg_ParseTuple(args, "i:tcgetpgrp", &fd))
1914 return NULL;
1915 pgid = tcgetpgrp(fd);
1916 if (pgid < 0)
1917 return posix_error();
1918 return PyLong_FromPid(pgid);
1919}
1920#endif /* HAVE_TCGETPGRP */
1921
1922
1923#ifdef HAVE_TCSETPGRP
1924PyDoc_STRVAR_remove(posix_tcsetpgrp__doc__,
1925"tcsetpgrp(fd, pgid)\n\n\
1926Set the process group associated with the terminal given by a fd.");
1927
1928static PyObject *
1929posix_tcsetpgrp(PyObject *self, PyObject *args)
1930{
1931 int fd;
1932 pid_t pgid;
1933 if (!PyArg_ParseTuple(args, "i" PARSE_PID ":tcsetpgrp", &fd, &pgid))
1934 return NULL;
1935 if (tcsetpgrp(fd, pgid) < 0)
1936 return posix_error();
1937 Py_INCREF(Py_None);
1938 return Py_None;
1939}
1940#endif /* HAVE_TCSETPGRP */
1941
1942/* Functions acting on file descriptors */
1943
1944PyDoc_STRVAR_remove(posix_open__doc__,
1945"open(filename, flag [, mode=0777]) -> fd\n\n\
1946Open a file (for low level IO).");
1947
1948static PyObject *
1949posix_open(PyObject *self, PyObject *args)
1950{
1951 char *file = NULL;
1952 int flag;
1953 int mode = 0777;
1954 int fd;
1955
1956 if (!PyArg_ParseTuple(args, "eti|i",
1957 Py_FileSystemDefaultEncoding, &file,
1958 &flag, &mode))
1959 return NULL;
1960
1961 Py_BEGIN_ALLOW_THREADS
1962 fd = open(file, flag, mode);
1963 Py_END_ALLOW_THREADS
1964 if (fd < 0)
1965 return posix_error_with_allocated_filename(file);
1966 PyMem_Free(file);
1967 return PyInt_FromLong((long)fd);
1968}
1969
1970
1971PyDoc_STRVAR_remove(posix_close__doc__,
1972"close(fd)\n\n\
1973Close a file descriptor (for low level IO).");
1974
1975/*
1976The underscore at end of function name avoids a name clash with the libc
1977function posix_close.
1978*/
1979static PyObject *
1980posix_close_(PyObject *self, PyObject *args)
1981{
1982 int fd, res;
1983 if (!PyArg_ParseTuple(args, "i:close", &fd))
1984 return NULL;
1985 if (!_PyVerify_fd(fd))
1986 return posix_error();
1987 Py_BEGIN_ALLOW_THREADS
1988 res = close(fd);
1989 Py_END_ALLOW_THREADS
1990 if (res < 0)
1991 return posix_error();
1992 Py_INCREF(Py_None);
1993 return Py_None;
1994}
1995
1996PyDoc_STRVAR_remove(posix_dup__doc__,
1997"dup(fd) -> fd2\n\n\
1998Return a duplicate of a file descriptor.");
1999
2000static PyObject *
2001posix_dup(PyObject *self, PyObject *args)
2002{
2003 int fd;
2004 if (!PyArg_ParseTuple(args, "i:dup", &fd))
2005 return NULL;
2006 if (!_PyVerify_fd(fd))
2007 return posix_error();
2008 Py_BEGIN_ALLOW_THREADS
2009 fd = dup(fd);
2010 Py_END_ALLOW_THREADS
2011 if (fd < 0)
2012 return posix_error();
2013 return PyInt_FromLong((long)fd);
2014}
2015
2016
2017PyDoc_STRVAR_remove(posix_dup2__doc__,
2018"dup2(old_fd, new_fd)\n\n\
2019Duplicate file descriptor.");
2020
2021static PyObject *
2022posix_dup2(PyObject *self, PyObject *args)
2023{
2024 int fd, fd2, res;
2025 if (!PyArg_ParseTuple(args, "ii:dup2", &fd, &fd2))
2026 return NULL;
2027 Py_BEGIN_ALLOW_THREADS
2028 res = dup2(fd, fd2);
2029 Py_END_ALLOW_THREADS
2030 if (res < 0)
2031 return posix_error();
2032 Py_INCREF(Py_None);
2033 return Py_None;
2034}
2035
2036
2037PyDoc_STRVAR_remove(posix_read__doc__,
2038"read(fd, buffersize) -> string\n\n\
2039Read a file descriptor.");
2040
2041static PyObject *
2042posix_read(PyObject *self, PyObject *args)
2043{
2044 int fd, size, n;
2045 PyObject *buffer;
2046 if (!PyArg_ParseTuple(args, "ii:read", &fd, &size))
2047 return NULL;
2048 if (size < 0) {
2049 errno = EINVAL;
2050 return posix_error();
2051 }
2052 buffer = PyString_FromStringAndSize((char *)NULL, size);
2053 if (buffer == NULL)
2054 return NULL;
2055 if (!_PyVerify_fd(fd)) {
2056 Py_DECREF(buffer);
2057 return posix_error();
2058 }
2059 // NOTE: Unlike write(), not retrying on EINTR, because shell's 'read' builtin
2060 // must handle it explicitly, run pending traps, and retry.
2061 Py_BEGIN_ALLOW_THREADS
2062 n = read(fd, PyString_AsString(buffer), size);
2063 Py_END_ALLOW_THREADS
2064 if (n < 0) {
2065 Py_DECREF(buffer);
2066 return posix_error();
2067 }
2068 if (n != size)
2069 _PyString_Resize(&buffer, n);
2070 return buffer;
2071}
2072
2073
2074PyDoc_STRVAR_remove(posix_write__doc__,
2075"write(fd, string) -> byteswritten\n\n\
2076Write a string to a file descriptor.");
2077
2078static PyObject *
2079posix_write(PyObject *self, PyObject *args)
2080{
2081 Py_buffer pbuf;
2082 int fd;
2083 Py_ssize_t size, len;
2084
2085 if (!PyArg_ParseTuple(args, "is*:write", &fd, &pbuf))
2086 return NULL;
2087 if (!_PyVerify_fd(fd)) {
2088 PyBuffer_Release(&pbuf);
2089 return posix_error();
2090 }
2091 len = pbuf.len;
2092
2093 // OVM_MAIN patch: Retry on EINTR.
2094 while (1) {
2095 Py_BEGIN_ALLOW_THREADS
2096 size = write(fd, pbuf.buf, len);
2097 Py_END_ALLOW_THREADS
2098
2099 if (size >= 0) { // success
2100 break;
2101 } else {
2102 if (PyErr_CheckSignals()) {
2103 return NULL; // Propagate KeyboardInterrupt
2104 }
2105 if (errno != EINTR) {
2106 return posix_error();
2107 }
2108 }
2109 }
2110 PyBuffer_Release(&pbuf);
2111 return PyInt_FromSsize_t(size);
2112}
2113
2114
2115PyDoc_STRVAR_remove(posix_fstat__doc__,
2116"fstat(fd) -> stat result\n\n\
2117Like stat(), but for an open file descriptor.");
2118
2119static PyObject *
2120posix_fstat(PyObject *self, PyObject *args)
2121{
2122 int fd;
2123 STRUCT_STAT st;
2124 int res;
2125 if (!PyArg_ParseTuple(args, "i:fstat", &fd))
2126 return NULL;
2127#ifdef __VMS
2128 /* on OpenVMS we must ensure that all bytes are written to the file */
2129 fsync(fd);
2130#endif
2131 if (!_PyVerify_fd(fd))
2132 return posix_error();
2133 Py_BEGIN_ALLOW_THREADS
2134 res = FSTAT(fd, &st);
2135 Py_END_ALLOW_THREADS
2136 if (res != 0) {
2137 return posix_error();
2138 }
2139
2140 return _pystat_fromstructstat(&st);
2141}
2142
2143
2144PyDoc_STRVAR_remove(posix_fdopen__doc__,
2145"fdopen(fd [, mode='r' [, bufsize]]) -> file_object\n\n\
2146Return an open file object connected to a file descriptor.");
2147
2148static PyObject *
2149posix_fdopen(PyObject *self, PyObject *args)
2150{
2151 int fd;
2152 char *orgmode = "r";
2153 int bufsize = -1;
2154 FILE *fp;
2155 PyObject *f;
2156 char *mode;
2157 if (!PyArg_ParseTuple(args, "i|si", &fd, &orgmode, &bufsize))
2158 return NULL;
2159
2160 /* Sanitize mode. See fileobject.c */
2161 mode = PyMem_MALLOC(strlen(orgmode)+3);
2162 if (!mode) {
2163 PyErr_NoMemory();
2164 return NULL;
2165 }
2166 strcpy(mode, orgmode);
2167 if (_PyFile_SanitizeMode(mode)) {
2168 PyMem_FREE(mode);
2169 return NULL;
2170 }
2171 if (!_PyVerify_fd(fd)) {
2172 PyMem_FREE(mode);
2173 return posix_error();
2174 }
2175#if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR)
2176 {
2177 struct stat buf;
2178 const char *msg;
2179 PyObject *exc;
2180 if (fstat(fd, &buf) == 0 && S_ISDIR(buf.st_mode)) {
2181 PyMem_FREE(mode);
2182 msg = strerror(EISDIR);
2183 exc = PyObject_CallFunction(PyExc_IOError, "(iss)",
2184 EISDIR, msg, "<fdopen>");
2185 if (exc) {
2186 PyErr_SetObject(PyExc_IOError, exc);
2187 Py_DECREF(exc);
2188 }
2189 return NULL;
2190 }
2191 }
2192#endif
2193 /* The dummy filename used here must be kept in sync with the value
2194 tested against in gzip.GzipFile.__init__() - see issue #13781. */
2195 f = PyFile_FromFile(NULL, "<fdopen>", orgmode, fclose);
2196 if (f == NULL) {
2197 PyMem_FREE(mode);
2198 return NULL;
2199 }
2200 Py_BEGIN_ALLOW_THREADS
2201#if !defined(MS_WINDOWS) && defined(HAVE_FCNTL_H)
2202 if (mode[0] == 'a') {
2203 /* try to make sure the O_APPEND flag is set */
2204 int flags;
2205 flags = fcntl(fd, F_GETFL);
2206 if (flags != -1)
2207 fcntl(fd, F_SETFL, flags | O_APPEND);
2208 fp = fdopen(fd, mode);
2209 if (fp == NULL && flags != -1)
2210 /* restore old mode if fdopen failed */
2211 fcntl(fd, F_SETFL, flags);
2212 } else {
2213 fp = fdopen(fd, mode);
2214 }
2215#else
2216 fp = fdopen(fd, mode);
2217#endif
2218 Py_END_ALLOW_THREADS
2219 PyMem_FREE(mode);
2220 if (fp == NULL) {
2221 Py_DECREF(f);
2222 return posix_error();
2223 }
2224 /* We now know we will succeed, so initialize the file object. */
2225 ((PyFileObject *)f)->f_fp = fp;
2226 PyFile_SetBufSize(f, bufsize);
2227 return f;
2228}
2229
2230PyDoc_STRVAR_remove(posix_isatty__doc__,
2231"isatty(fd) -> bool\n\n\
2232Return True if the file descriptor 'fd' is an open file descriptor\n\
2233connected to the slave end of a terminal.");
2234
2235static PyObject *
2236posix_isatty(PyObject *self, PyObject *args)
2237{
2238 int fd;
2239 if (!PyArg_ParseTuple(args, "i:isatty", &fd))
2240 return NULL;
2241 if (!_PyVerify_fd(fd))
2242 return PyBool_FromLong(0);
2243 return PyBool_FromLong(isatty(fd));
2244}
2245
2246#ifdef HAVE_PIPE
2247PyDoc_STRVAR_remove(posix_pipe__doc__,
2248"pipe() -> (read_end, write_end)\n\n\
2249Create a pipe.");
2250
2251static PyObject *
2252posix_pipe(PyObject *self, PyObject *noargs)
2253{
2254 int fds[2];
2255 int res;
2256 Py_BEGIN_ALLOW_THREADS
2257 res = pipe(fds);
2258 Py_END_ALLOW_THREADS
2259 if (res != 0)
2260 return posix_error();
2261 return Py_BuildValue("(ii)", fds[0], fds[1]);
2262}
2263#endif /* HAVE_PIPE */
2264
2265
2266#ifdef HAVE_MKFIFO
2267PyDoc_STRVAR_remove(posix_mkfifo__doc__,
2268"mkfifo(filename [, mode=0666])\n\n\
2269Create a FIFO (a POSIX named pipe).");
2270
2271static PyObject *
2272posix_mkfifo(PyObject *self, PyObject *args)
2273{
2274 char *filename;
2275 int mode = 0666;
2276 int res;
2277 if (!PyArg_ParseTuple(args, "s|i:mkfifo", &filename, &mode))
2278 return NULL;
2279 Py_BEGIN_ALLOW_THREADS
2280 res = mkfifo(filename, mode);
2281 Py_END_ALLOW_THREADS
2282 if (res < 0)
2283 return posix_error();
2284 Py_INCREF(Py_None);
2285 return Py_None;
2286}
2287#endif
2288
2289#ifdef HAVE_PUTENV
2290PyDoc_STRVAR_remove(posix_putenv__doc__,
2291"putenv(key, value)\n\n\
2292Change or add an environment variable.");
2293
2294/* Save putenv() parameters as values here, so we can collect them when they
2295 * get re-set with another call for the same key. */
2296static PyObject *posix_putenv_garbage;
2297
2298static PyObject *
2299posix_putenv(PyObject *self, PyObject *args)
2300{
2301 char *s1, *s2;
2302 char *newenv;
2303 PyObject *newstr;
2304 size_t len;
2305
2306 if (!PyArg_ParseTuple(args, "ss:putenv", &s1, &s2))
2307 return NULL;
2308
2309 /* XXX This can leak memory -- not easy to fix :-( */
2310 len = strlen(s1) + strlen(s2) + 2;
2311 /* len includes space for a trailing \0; the size arg to
2312 PyString_FromStringAndSize does not count that */
2313 newstr = PyString_FromStringAndSize(NULL, (int)len - 1);
2314 if (newstr == NULL)
2315 return PyErr_NoMemory();
2316 newenv = PyString_AS_STRING(newstr);
2317 PyOS_snprintf(newenv, len, "%s=%s", s1, s2);
2318 if (putenv(newenv)) {
2319 Py_DECREF(newstr);
2320 posix_error();
2321 return NULL;
2322 }
2323 /* Install the first arg and newstr in posix_putenv_garbage;
2324 * this will cause previous value to be collected. This has to
2325 * happen after the real putenv() call because the old value
2326 * was still accessible until then. */
2327 if (PyDict_SetItem(posix_putenv_garbage,
2328 PyTuple_GET_ITEM(args, 0), newstr)) {
2329 /* really not much we can do; just leak */
2330 PyErr_Clear();
2331 }
2332 else {
2333 Py_DECREF(newstr);
2334 }
2335
2336 Py_INCREF(Py_None);
2337 return Py_None;
2338}
2339#endif /* putenv */
2340
2341#ifdef HAVE_UNSETENV
2342PyDoc_STRVAR_remove(posix_unsetenv__doc__,
2343"unsetenv(key)\n\n\
2344Delete an environment variable.");
2345
2346static PyObject *
2347posix_unsetenv(PyObject *self, PyObject *args)
2348{
2349 char *s1;
2350#ifndef HAVE_BROKEN_UNSETENV
2351 int err;
2352#endif
2353
2354 if (!PyArg_ParseTuple(args, "s:unsetenv", &s1))
2355 return NULL;
2356
2357#ifdef HAVE_BROKEN_UNSETENV
2358 unsetenv(s1);
2359#else
2360 err = unsetenv(s1);
2361 if (err)
2362 return posix_error();
2363#endif
2364
2365 /* Remove the key from posix_putenv_garbage;
2366 * this will cause it to be collected. This has to
2367 * happen after the real unsetenv() call because the
2368 * old value was still accessible until then.
2369 */
2370 if (PyDict_DelItem(posix_putenv_garbage,
2371 PyTuple_GET_ITEM(args, 0))) {
2372 /* really not much we can do; just leak */
2373 PyErr_Clear();
2374 }
2375
2376 Py_INCREF(Py_None);
2377 return Py_None;
2378}
2379#endif /* unsetenv */
2380
2381PyDoc_STRVAR_remove(posix_strerror__doc__,
2382"strerror(code) -> string\n\n\
2383Translate an error code to a message string.");
2384
2385static PyObject *
2386posix_strerror(PyObject *self, PyObject *args)
2387{
2388 int code;
2389 char *message;
2390 if (!PyArg_ParseTuple(args, "i:strerror", &code))
2391 return NULL;
2392 message = strerror(code);
2393 if (message == NULL) {
2394 PyErr_SetString(PyExc_ValueError,
2395 "strerror() argument out of range");
2396 return NULL;
2397 }
2398 return PyString_FromString(message);
2399}
2400
2401
2402#ifdef HAVE_SYS_WAIT_H
2403
2404#ifdef WCOREDUMP
2405PyDoc_STRVAR_remove(posix_WCOREDUMP__doc__,
2406"WCOREDUMP(status) -> bool\n\n\
2407Return True if the process returning 'status' was dumped to a core file.");
2408
2409static PyObject *
2410posix_WCOREDUMP(PyObject *self, PyObject *args)
2411{
2412 WAIT_TYPE status;
2413 WAIT_STATUS_INT(status) = 0;
2414
2415 if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status)))
2416 return NULL;
2417
2418 return PyBool_FromLong(WCOREDUMP(status));
2419}
2420#endif /* WCOREDUMP */
2421
2422#ifdef WIFCONTINUED
2423PyDoc_STRVAR_remove(posix_WIFCONTINUED__doc__,
2424"WIFCONTINUED(status) -> bool\n\n\
2425Return True if the process returning 'status' was continued from a\n\
2426job control stop.");
2427
2428static PyObject *
2429posix_WIFCONTINUED(PyObject *self, PyObject *args)
2430{
2431 WAIT_TYPE status;
2432 WAIT_STATUS_INT(status) = 0;
2433
2434 if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status)))
2435 return NULL;
2436
2437 return PyBool_FromLong(WIFCONTINUED(status));
2438}
2439#endif /* WIFCONTINUED */
2440
2441#ifdef WIFSTOPPED
2442PyDoc_STRVAR_remove(posix_WIFSTOPPED__doc__,
2443"WIFSTOPPED(status) -> bool\n\n\
2444Return True if the process returning 'status' was stopped.");
2445
2446static PyObject *
2447posix_WIFSTOPPED(PyObject *self, PyObject *args)
2448{
2449 WAIT_TYPE status;
2450 WAIT_STATUS_INT(status) = 0;
2451
2452 if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status)))
2453 return NULL;
2454
2455 return PyBool_FromLong(WIFSTOPPED(status));
2456}
2457#endif /* WIFSTOPPED */
2458
2459#ifdef WIFSIGNALED
2460PyDoc_STRVAR_remove(posix_WIFSIGNALED__doc__,
2461"WIFSIGNALED(status) -> bool\n\n\
2462Return True if the process returning 'status' was terminated by a signal.");
2463
2464static PyObject *
2465posix_WIFSIGNALED(PyObject *self, PyObject *args)
2466{
2467 WAIT_TYPE status;
2468 WAIT_STATUS_INT(status) = 0;
2469
2470 if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status)))
2471 return NULL;
2472
2473 return PyBool_FromLong(WIFSIGNALED(status));
2474}
2475#endif /* WIFSIGNALED */
2476
2477#ifdef WIFEXITED
2478PyDoc_STRVAR_remove(posix_WIFEXITED__doc__,
2479"WIFEXITED(status) -> bool\n\n\
2480Return true if the process returning 'status' exited using the exit()\n\
2481system call.");
2482
2483static PyObject *
2484posix_WIFEXITED(PyObject *self, PyObject *args)
2485{
2486 WAIT_TYPE status;
2487 WAIT_STATUS_INT(status) = 0;
2488
2489 if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status)))
2490 return NULL;
2491
2492 return PyBool_FromLong(WIFEXITED(status));
2493}
2494#endif /* WIFEXITED */
2495
2496#ifdef WEXITSTATUS
2497PyDoc_STRVAR_remove(posix_WEXITSTATUS__doc__,
2498"WEXITSTATUS(status) -> integer\n\n\
2499Return the process return code from 'status'.");
2500
2501static PyObject *
2502posix_WEXITSTATUS(PyObject *self, PyObject *args)
2503{
2504 WAIT_TYPE status;
2505 WAIT_STATUS_INT(status) = 0;
2506
2507 if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status)))
2508 return NULL;
2509
2510 return Py_BuildValue("i", WEXITSTATUS(status));
2511}
2512#endif /* WEXITSTATUS */
2513
2514#ifdef WTERMSIG
2515PyDoc_STRVAR_remove(posix_WTERMSIG__doc__,
2516"WTERMSIG(status) -> integer\n\n\
2517Return the signal that terminated the process that provided the 'status'\n\
2518value.");
2519
2520static PyObject *
2521posix_WTERMSIG(PyObject *self, PyObject *args)
2522{
2523 WAIT_TYPE status;
2524 WAIT_STATUS_INT(status) = 0;
2525
2526 if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status)))
2527 return NULL;
2528
2529 return Py_BuildValue("i", WTERMSIG(status));
2530}
2531#endif /* WTERMSIG */
2532
2533#ifdef WSTOPSIG
2534PyDoc_STRVAR_remove(posix_WSTOPSIG__doc__,
2535"WSTOPSIG(status) -> integer\n\n\
2536Return the signal that stopped the process that provided\n\
2537the 'status' value.");
2538
2539static PyObject *
2540posix_WSTOPSIG(PyObject *self, PyObject *args)
2541{
2542 WAIT_TYPE status;
2543 WAIT_STATUS_INT(status) = 0;
2544
2545 if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status)))
2546 return NULL;
2547
2548 return Py_BuildValue("i", WSTOPSIG(status));
2549}
2550#endif /* WSTOPSIG */
2551
2552#endif /* HAVE_SYS_WAIT_H */
2553
2554#include "Python-2.7.13/Modules/posixmodule.c/posix_methods.def"
2555
2556static int
2557ins(PyObject *module, char *symbol, long value)
2558{
2559 return PyModule_AddIntConstant(module, symbol, value);
2560}
2561
2562static int
2563all_ins(PyObject *d)
2564{
2565#ifdef F_OK
2566 if (ins(d, "F_OK", (long)F_OK)) return -1;
2567#endif
2568#ifdef R_OK
2569 if (ins(d, "R_OK", (long)R_OK)) return -1;
2570#endif
2571#ifdef W_OK
2572 if (ins(d, "W_OK", (long)W_OK)) return -1;
2573#endif
2574#ifdef X_OK
2575 if (ins(d, "X_OK", (long)X_OK)) return -1;
2576#endif
2577#ifdef NGROUPS_MAX
2578 if (ins(d, "NGROUPS_MAX", (long)NGROUPS_MAX)) return -1;
2579#endif
2580#ifdef TMP_MAX
2581 if (ins(d, "TMP_MAX", (long)TMP_MAX)) return -1;
2582#endif
2583#ifdef WCONTINUED
2584 if (ins(d, "WCONTINUED", (long)WCONTINUED)) return -1;
2585#endif
2586#ifdef WNOHANG
2587 if (ins(d, "WNOHANG", (long)WNOHANG)) return -1;
2588#endif
2589#ifdef WUNTRACED
2590 if (ins(d, "WUNTRACED", (long)WUNTRACED)) return -1;
2591#endif
2592#ifdef O_RDONLY
2593 if (ins(d, "O_RDONLY", (long)O_RDONLY)) return -1;
2594#endif
2595#ifdef O_WRONLY
2596 if (ins(d, "O_WRONLY", (long)O_WRONLY)) return -1;
2597#endif
2598#ifdef O_RDWR
2599 if (ins(d, "O_RDWR", (long)O_RDWR)) return -1;
2600#endif
2601#ifdef O_NDELAY
2602 if (ins(d, "O_NDELAY", (long)O_NDELAY)) return -1;
2603#endif
2604#ifdef O_NONBLOCK
2605 if (ins(d, "O_NONBLOCK", (long)O_NONBLOCK)) return -1;
2606#endif
2607#ifdef O_APPEND
2608 if (ins(d, "O_APPEND", (long)O_APPEND)) return -1;
2609#endif
2610#ifdef O_DSYNC
2611 if (ins(d, "O_DSYNC", (long)O_DSYNC)) return -1;
2612#endif
2613#ifdef O_RSYNC
2614 if (ins(d, "O_RSYNC", (long)O_RSYNC)) return -1;
2615#endif
2616#ifdef O_SYNC
2617 if (ins(d, "O_SYNC", (long)O_SYNC)) return -1;
2618#endif
2619#ifdef O_NOCTTY
2620 if (ins(d, "O_NOCTTY", (long)O_NOCTTY)) return -1;
2621#endif
2622#ifdef O_CREAT
2623 if (ins(d, "O_CREAT", (long)O_CREAT)) return -1;
2624#endif
2625#ifdef O_EXCL
2626 if (ins(d, "O_EXCL", (long)O_EXCL)) return -1;
2627#endif
2628#ifdef O_TRUNC
2629 if (ins(d, "O_TRUNC", (long)O_TRUNC)) return -1;
2630#endif
2631#ifdef O_BINARY
2632 if (ins(d, "O_BINARY", (long)O_BINARY)) return -1;
2633#endif
2634#ifdef O_TEXT
2635 if (ins(d, "O_TEXT", (long)O_TEXT)) return -1;
2636#endif
2637#ifdef O_LARGEFILE
2638 if (ins(d, "O_LARGEFILE", (long)O_LARGEFILE)) return -1;
2639#endif
2640#ifdef O_SHLOCK
2641 if (ins(d, "O_SHLOCK", (long)O_SHLOCK)) return -1;
2642#endif
2643#ifdef O_EXLOCK
2644 if (ins(d, "O_EXLOCK", (long)O_EXLOCK)) return -1;
2645#endif
2646
2647 return 0;
2648}
2649
2650#define INITFUNC initposix_
2651#define MODNAME "posix_"
2652
2653PyMODINIT_FUNC
2654INITFUNC(void)
2655{
2656 PyObject *m, *v;
2657
2658 m = Py_InitModule3(MODNAME,
2659 posix_methods,
2660 posix__doc__);
2661 if (m == NULL)
2662 return;
2663
2664 /* Initialize environ dictionary */
2665 v = convertenviron();
2666 Py_XINCREF(v);
2667 if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
2668 return;
2669 Py_DECREF(v);
2670
2671 if (all_ins(m))
2672 return;
2673
2674 /* OVM_MAIN: We might want to redefine OSError as IOError like Python 3 ?
2675 * */
2676 Py_INCREF(PyExc_OSError);
2677 PyModule_AddObject(m, "error", PyExc_OSError);
2678
2679#ifdef HAVE_PUTENV
2680 if (posix_putenv_garbage == NULL)
2681 posix_putenv_garbage = PyDict_New();
2682#endif
2683
2684 if (!initialized) {
2685 stat_result_desc.name = MODNAME ".stat_result";
2686 stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
2687 stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
2688 stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
2689 PyStructSequence_InitType(&StatResultType, &stat_result_desc);
2690 structseq_new = StatResultType.tp_new;
2691 StatResultType.tp_new = statresult_new;
2692
2693#ifdef NEED_TICKS_PER_SECOND
2694# if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
2695 ticks_per_second = sysconf(_SC_CLK_TCK);
2696# elif defined(HZ)
2697 ticks_per_second = HZ;
2698# else
2699 ticks_per_second = 60; /* magic fallback value; may be bogus */
2700# endif
2701#endif
2702 }
2703 Py_INCREF((PyObject*) &StatResultType);
2704 PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType);
2705 initialized = 1;
2706}
2707
2708#ifdef __cplusplus
2709}
2710#endif