diff options
Diffstat (limited to 'Modules/posixmodule.c')
-rw-r--r-- | Modules/posixmodule.c | 424 |
1 files changed, 268 insertions, 156 deletions
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 1fbc353008..b51ba5dc54 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -22,6 +22,10 @@ # include <unixio.h> #endif /* defined(__VMS) */ +#ifdef __cplusplus +extern "C" { +#endif + PyDoc_STRVAR(posix__doc__, "This module provides access to operating system functionality that is\n\ standardized by the C Standard and the POSIX standard (a thinly\n\ @@ -264,6 +268,12 @@ extern int lstat(const char *, struct stat *); #define WTERMSIG(u_wait) ((u_wait).w_termsig) #endif +#define WAIT_TYPE union wait +#define WAIT_STATUS_INT(s) (s.w_status) + +#else /* !UNION_WAIT */ +#define WAIT_TYPE int +#define WAIT_STATUS_INT(s) (s) #endif /* UNION_WAIT */ /* Don't use the "_r" form if we don't need it (also, won't have a @@ -971,6 +981,7 @@ static PyStructSequence_Desc statvfs_result_desc = { 10 }; +static int initialized; static PyTypeObject StatResultType; static PyTypeObject StatVFSResultType; static newfunc structseq_new; @@ -1839,6 +1850,7 @@ posix_listdir(PyObject *self, PyObject *args) struct dirent *ep; int arg_is_unicode = 1; + errno = 0; if (!PyArg_ParseTuple(args, "U:listdir", &v)) { arg_is_unicode = 0; PyErr_Clear(); @@ -1895,6 +1907,12 @@ posix_listdir(PyObject *self, PyObject *args) } Py_DECREF(v); } + if (errno != 0 && d != NULL) { + /* readdir() returned NULL and set errno */ + closedir(dirp); + Py_DECREF(d); + return posix_error_with_allocated_filename(name); + } closedir(dirp); PyMem_Free(name); @@ -1995,13 +2013,13 @@ posix_mkdir(PyObject *self, PyObject *args) } -#ifdef HAVE_NICE -#if defined(HAVE_BROKEN_NICE) && defined(HAVE_SYS_RESOURCE_H) -#if defined(HAVE_GETPRIORITY) && !defined(PRIO_PROCESS) +/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */ +#if defined(HAVE_SYS_RESOURCE_H) #include <sys/resource.h> #endif -#endif + +#ifdef HAVE_NICE PyDoc_STRVAR(posix_nice__doc__, "nice(inc) -> new_priority\n\n\ Decrease the priority of process by inc and return the new priority."); @@ -3088,7 +3106,7 @@ posix_openpty(PyObject *self, PyObject *noargs) #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY) PyOS_sighandler_t sig_saved; #ifdef sun - extern char *ptsname(); + extern char *ptsname(int fildes); #endif #endif @@ -5091,6 +5109,114 @@ posix_setgroups(PyObject *self, PyObject *args) } #endif /* HAVE_SETGROUPS */ +#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) +static PyObject * +wait_helper(int pid, int status, struct rusage *ru) +{ + PyObject *result; + static PyObject *struct_rusage; + + if (pid == -1) + return posix_error(); + + if (struct_rusage == NULL) { + PyObject *m = PyImport_ImportModule("resource"); + if (m == NULL) + return NULL; + struct_rusage = PyObject_GetAttrString(m, "struct_rusage"); + Py_DECREF(m); + if (struct_rusage == NULL) + return NULL; + } + + /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */ + result = PyStructSequence_New((PyTypeObject*) struct_rusage); + if (!result) + return NULL; + +#ifndef doubletime +#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001) +#endif + + PyStructSequence_SET_ITEM(result, 0, + PyFloat_FromDouble(doubletime(ru->ru_utime))); + PyStructSequence_SET_ITEM(result, 1, + PyFloat_FromDouble(doubletime(ru->ru_stime))); +#define SET_INT(result, index, value)\ + PyStructSequence_SET_ITEM(result, index, PyInt_FromLong(value)) + SET_INT(result, 2, ru->ru_maxrss); + SET_INT(result, 3, ru->ru_ixrss); + SET_INT(result, 4, ru->ru_idrss); + SET_INT(result, 5, ru->ru_isrss); + SET_INT(result, 6, ru->ru_minflt); + SET_INT(result, 7, ru->ru_majflt); + SET_INT(result, 8, ru->ru_nswap); + SET_INT(result, 9, ru->ru_inblock); + SET_INT(result, 10, ru->ru_oublock); + SET_INT(result, 11, ru->ru_msgsnd); + SET_INT(result, 12, ru->ru_msgrcv); + SET_INT(result, 13, ru->ru_nsignals); + SET_INT(result, 14, ru->ru_nvcsw); + SET_INT(result, 15, ru->ru_nivcsw); +#undef SET_INT + + if (PyErr_Occurred()) { + Py_DECREF(result); + return NULL; + } + + return Py_BuildValue("iiN", pid, status, result); +} +#endif /* HAVE_WAIT3 || HAVE_WAIT4 */ + +#ifdef HAVE_WAIT3 +PyDoc_STRVAR(posix_wait3__doc__, +"wait3(options) -> (pid, status, rusage)\n\n\ +Wait for completion of a child process."); + +static PyObject * +posix_wait3(PyObject *self, PyObject *args) +{ + int pid, options; + struct rusage ru; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "i:wait3", &options)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + pid = wait3(&status, options, &ru); + Py_END_ALLOW_THREADS + + return wait_helper(pid, WAIT_STATUS_INT(status), &ru); +} +#endif /* HAVE_WAIT3 */ + +#ifdef HAVE_WAIT4 +PyDoc_STRVAR(posix_wait4__doc__, +"wait4(pid, options) -> (pid, status, rusage)\n\n\ +Wait for completion of a given child process."); + +static PyObject * +posix_wait4(PyObject *self, PyObject *args) +{ + int pid, options; + struct rusage ru; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "ii:wait4", &pid, &options)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + pid = wait4(pid, &status, options, &ru); + Py_END_ALLOW_THREADS + + return wait_helper(pid, WAIT_STATUS_INT(status), &ru); +} +#endif /* HAVE_WAIT4 */ + #ifdef HAVE_WAITPID PyDoc_STRVAR(posix_waitpid__doc__, "waitpid(pid, options) -> (pid, status)\n\n\ @@ -5100,14 +5226,8 @@ static PyObject * posix_waitpid(PyObject *self, PyObject *args) { int pid, options; -#ifdef UNION_WAIT - union wait status; -#define status_i (status.w_status) -#else - int status; -#define status_i status -#endif - status_i = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; if (!PyArg_ParseTuple(args, "ii:waitpid", &pid, &options)) return NULL; @@ -5116,8 +5236,8 @@ posix_waitpid(PyObject *self, PyObject *args) Py_END_ALLOW_THREADS if (pid == -1) return posix_error(); - else - return Py_BuildValue("ii", pid, status_i); + + return Py_BuildValue("ii", pid, WAIT_STATUS_INT(status)); } #elif defined(HAVE_CWAIT) @@ -5140,10 +5260,9 @@ posix_waitpid(PyObject *self, PyObject *args) Py_END_ALLOW_THREADS if (pid == -1) return posix_error(); - else - /* shift the status left a byte so this is more like the - POSIX waitpid */ - return Py_BuildValue("ii", pid, status << 8); + + /* shift the status left a byte so this is more like the POSIX waitpid */ + return Py_BuildValue("ii", pid, status << 8); } #endif /* HAVE_WAITPID || HAVE_CWAIT */ @@ -5156,23 +5275,16 @@ static PyObject * posix_wait(PyObject *self, PyObject *noargs) { int pid; -#ifdef UNION_WAIT - union wait status; -#define status_i (status.w_status) -#else - int status; -#define status_i status -#endif + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; - status_i = 0; Py_BEGIN_ALLOW_THREADS pid = wait(&status); Py_END_ALLOW_THREADS if (pid == -1) return posix_error(); - else - return Py_BuildValue("ii", pid, status_i); -#undef status_i + + return Py_BuildValue("ii", pid, WAIT_STATUS_INT(status)); } #endif @@ -5668,9 +5780,24 @@ posix_fdopen(PyObject *self, PyObject *args) "invalid file mode '%s'", mode); return NULL; } - Py_BEGIN_ALLOW_THREADS +#if !defined(MS_WINDOWS) && defined(HAVE_FCNTL_H) + if (mode[0] == 'a') { + /* try to make sure the O_APPEND flag is set */ + int flags; + flags = fcntl(fd, F_GETFL); + if (flags != -1) + fcntl(fd, F_SETFL, flags | O_APPEND); + fp = fdopen(fd, mode); + if (fp == NULL && flags != -1) + /* restore old mode if fdopen failed */ + fcntl(fd, F_SETFL, flags); + } else { + fp = fdopen(fd, mode); + } +#else fp = fdopen(fd, mode); +#endif Py_END_ALLOW_THREADS if (fp == NULL) return posix_error(); @@ -5887,7 +6014,7 @@ static PyObject * posix_putenv(PyObject *self, PyObject *args) { char *s1, *s2; - char *new; + char *newenv; PyObject *newstr; size_t len; @@ -5918,9 +6045,9 @@ posix_putenv(PyObject *self, PyObject *args) newstr = PyString_FromStringAndSize(NULL, (int)len - 1); if (newstr == NULL) return PyErr_NoMemory(); - new = PyString_AS_STRING(newstr); - PyOS_snprintf(new, len, "%s=%s", s1, s2); - if (putenv(new)) { + newenv = PyString_AS_STRING(newstr); + PyOS_snprintf(newenv, len, "%s=%s", s1, s2); + if (putenv(newenv)) { Py_DECREF(newstr); posix_error(); return NULL; @@ -6010,22 +6137,13 @@ Return True if the process returning 'status' was dumped to a core file."); static PyObject * posix_WCOREDUMP(PyObject *self, PyObject *args) { -#ifdef UNION_WAIT - union wait status; -#define status_i (status.w_status) -#else - int status; -#define status_i status -#endif - status_i = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; - if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &status_i)) - { + if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status))) return NULL; - } return PyBool_FromLong(WCOREDUMP(status)); -#undef status_i } #endif /* WCOREDUMP */ @@ -6038,22 +6156,13 @@ job control stop."); static PyObject * posix_WIFCONTINUED(PyObject *self, PyObject *args) { -#ifdef UNION_WAIT - union wait status; -#define status_i (status.w_status) -#else - int status; -#define status_i status -#endif - status_i = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; - if (!PyArg_ParseTuple(args, "i:WCONTINUED", &status_i)) - { + if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status))) return NULL; - } return PyBool_FromLong(WIFCONTINUED(status)); -#undef status_i } #endif /* WIFCONTINUED */ @@ -6065,22 +6174,13 @@ Return True if the process returning 'status' was stopped."); static PyObject * posix_WIFSTOPPED(PyObject *self, PyObject *args) { -#ifdef UNION_WAIT - union wait status; -#define status_i (status.w_status) -#else - int status; -#define status_i status -#endif - status_i = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; - if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &status_i)) - { + if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status))) return NULL; - } return PyBool_FromLong(WIFSTOPPED(status)); -#undef status_i } #endif /* WIFSTOPPED */ @@ -6092,22 +6192,13 @@ Return True if the process returning 'status' was terminated by a signal."); static PyObject * posix_WIFSIGNALED(PyObject *self, PyObject *args) { -#ifdef UNION_WAIT - union wait status; -#define status_i (status.w_status) -#else - int status; -#define status_i status -#endif - status_i = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; - if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &status_i)) - { + if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status))) return NULL; - } return PyBool_FromLong(WIFSIGNALED(status)); -#undef status_i } #endif /* WIFSIGNALED */ @@ -6120,22 +6211,13 @@ system call."); static PyObject * posix_WIFEXITED(PyObject *self, PyObject *args) { -#ifdef UNION_WAIT - union wait status; -#define status_i (status.w_status) -#else - int status; -#define status_i status -#endif - status_i = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; - if (!PyArg_ParseTuple(args, "i:WIFEXITED", &status_i)) - { + if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status))) return NULL; - } return PyBool_FromLong(WIFEXITED(status)); -#undef status_i } #endif /* WIFEXITED */ @@ -6147,22 +6229,13 @@ Return the process return code from 'status'."); static PyObject * posix_WEXITSTATUS(PyObject *self, PyObject *args) { -#ifdef UNION_WAIT - union wait status; -#define status_i (status.w_status) -#else - int status; -#define status_i status -#endif - status_i = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; - if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &status_i)) - { + if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status))) return NULL; - } return Py_BuildValue("i", WEXITSTATUS(status)); -#undef status_i } #endif /* WEXITSTATUS */ @@ -6175,22 +6248,13 @@ value."); static PyObject * posix_WTERMSIG(PyObject *self, PyObject *args) { -#ifdef UNION_WAIT - union wait status; -#define status_i (status.w_status) -#else - int status; -#define status_i status -#endif - status_i = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; - if (!PyArg_ParseTuple(args, "i:WTERMSIG", &status_i)) - { + if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status))) return NULL; - } return Py_BuildValue("i", WTERMSIG(status)); -#undef status_i } #endif /* WTERMSIG */ @@ -6203,22 +6267,13 @@ the 'status' value."); static PyObject * posix_WSTOPSIG(PyObject *self, PyObject *args) { -#ifdef UNION_WAIT - union wait status; -#define status_i (status.w_status) -#else - int status; -#define status_i status -#endif - status_i = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; - if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &status_i)) - { + if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status))) return NULL; - } return Py_BuildValue("i", WSTOPSIG(status)); -#undef status_i } #endif /* WSTOPSIG */ @@ -6396,15 +6451,16 @@ posix_tmpnam(PyObject *self, PyObject *noargs) name = tmpnam(buffer); #endif if (name == NULL) { - PyErr_SetObject(PyExc_OSError, - Py_BuildValue("is", 0, + PyObject *err = Py_BuildValue("is", 0, #ifdef USE_TMPNAM_R "unexpected NULL from tmpnam_r" #else "unexpected NULL from tmpnam" #endif - )); - return NULL; + ); + PyErr_SetObject(PyExc_OSError, err); + Py_XDECREF(err); + return NULL; } return PyString_FromString(buffer); } @@ -6753,26 +6809,30 @@ posix_confstr(PyObject *self, PyObject *args) { PyObject *result = NULL; int name; - char buffer[64]; + char buffer[256]; if (PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name)) { - int len = confstr(name, buffer, sizeof(buffer)); + int len; errno = 0; - if (len == 0) { - if (errno != 0) - posix_error(); - else - result = PyString_FromString(""); + len = confstr(name, buffer, sizeof(buffer)); + if (len == 0) { + if (errno) { + posix_error(); + } + else { + result = Py_None; + Py_INCREF(Py_None); + } } else { - if (len >= sizeof(buffer)) { - result = PyString_FromStringAndSize(NULL, len); + if ((unsigned int)len >= sizeof(buffer)) { + result = PyString_FromStringAndSize(NULL, len-1); if (result != NULL) - confstr(name, PyString_AS_STRING(result), len+1); + confstr(name, PyString_AS_STRING(result), len); } else - result = PyString_FromString(buffer); + result = PyString_FromStringAndSize(buffer, len-1); } } return result; @@ -7423,6 +7483,44 @@ win32_startfile(PyObject *self, PyObject *args) char *filepath; char *operation = NULL; HINSTANCE rc; +#ifdef Py_WIN_WIDE_FILENAMES + if (unicode_file_names()) { + PyObject *unipath, *woperation = NULL; + if (!PyArg_ParseTuple(args, "U|s:startfile", + &unipath, &operation)) { + PyErr_Clear(); + goto normal; + } + + + if (operation) { + woperation = PyUnicode_DecodeASCII(operation, + strlen(operation), NULL); + if (!woperation) { + PyErr_Clear(); + operation = NULL; + goto normal; + } + } + + Py_BEGIN_ALLOW_THREADS + rc = ShellExecuteW((HWND)0, woperation ? PyUnicode_AS_UNICODE(woperation) : 0, + PyUnicode_AS_UNICODE(unipath), + NULL, NULL, SW_SHOWNORMAL); + Py_END_ALLOW_THREADS + + Py_XDECREF(woperation); + if (rc <= (HINSTANCE)32) { + PyObject *errval = win32_error_unicode("startfile", + PyUnicode_AS_UNICODE(unipath)); + return errval; + } + Py_INCREF(Py_None); + return Py_None; + } +#endif + +normal: if (!PyArg_ParseTuple(args, "et|s:startfile", Py_FileSystemDefaultEncoding, &filepath, &operation)) @@ -7695,6 +7793,12 @@ static PyMethodDef posix_methods[] = { #ifdef HAVE_WAIT {"wait", posix_wait, METH_NOARGS, posix_wait__doc__}, #endif /* HAVE_WAIT */ +#ifdef HAVE_WAIT3 + {"wait3", posix_wait3, METH_VARARGS, posix_wait3__doc__}, +#endif /* HAVE_WAIT3 */ +#ifdef HAVE_WAIT4 + {"wait4", posix_wait4, METH_VARARGS, posix_wait4__doc__}, +#endif /* HAVE_WAIT4 */ #if defined(HAVE_WAITPID) || defined(HAVE_CWAIT) {"waitpid", posix_waitpid, METH_VARARGS, posix_waitpid__doc__}, #endif /* HAVE_WAITPID */ @@ -8142,19 +8246,27 @@ INITFUNC(void) posix_putenv_garbage = PyDict_New(); #endif - stat_result_desc.name = MODNAME ".stat_result"; - stat_result_desc.fields[7].name = PyStructSequence_UnnamedField; - stat_result_desc.fields[8].name = PyStructSequence_UnnamedField; - stat_result_desc.fields[9].name = PyStructSequence_UnnamedField; - PyStructSequence_InitType(&StatResultType, &stat_result_desc); - structseq_new = StatResultType.tp_new; - StatResultType.tp_new = statresult_new; + if (!initialized) { + stat_result_desc.name = MODNAME ".stat_result"; + stat_result_desc.fields[7].name = PyStructSequence_UnnamedField; + stat_result_desc.fields[8].name = PyStructSequence_UnnamedField; + stat_result_desc.fields[9].name = PyStructSequence_UnnamedField; + PyStructSequence_InitType(&StatResultType, &stat_result_desc); + structseq_new = StatResultType.tp_new; + StatResultType.tp_new = statresult_new; + + statvfs_result_desc.name = MODNAME ".statvfs_result"; + PyStructSequence_InitType(&StatVFSResultType, &statvfs_result_desc); + } Py_INCREF((PyObject*) &StatResultType); PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType); - - statvfs_result_desc.name = MODNAME ".statvfs_result"; - PyStructSequence_InitType(&StatVFSResultType, &statvfs_result_desc); Py_INCREF((PyObject*) &StatVFSResultType); PyModule_AddObject(m, "statvfs_result", (PyObject*) &StatVFSResultType); + initialized = 1; } + +#ifdef __cplusplus +} +#endif + |