From: Benjamin Peterson Date: Wed, 23 Nov 2011 05:14:47 +0000 (-0600) Subject: merge 3.2 X-Git-Tag: v3.3.0a1~741 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e8eb0e82f314f69dda60530480f3234b73466078;p=python merge 3.2 --- e8eb0e82f314f69dda60530480f3234b73466078 diff --cc Modules/posixmodule.c index 094d071172,2afd5a6097..e42db5ba8d --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@@ -6944,1844 -6901,205 +6944,1848 @@@ posix_lockf(PyObject *self, PyObject *a #endif -#ifdef HAVE_SYSCONF -static struct constdef posix_constants_sysconf[] = { -#ifdef _SC_2_CHAR_TERM - {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM}, -#endif -#ifdef _SC_2_C_BIND - {"SC_2_C_BIND", _SC_2_C_BIND}, +PyDoc_STRVAR(posix_lseek__doc__, +"lseek(fd, pos, how) -> newpos\n\n\ +Set the current position of a file descriptor."); + +static PyObject * +posix_lseek(PyObject *self, PyObject *args) +{ + int fd, how; +#if defined(MS_WIN64) || defined(MS_WINDOWS) + PY_LONG_LONG pos, res; +#else + off_t pos, res; #endif -#ifdef _SC_2_C_DEV - {"SC_2_C_DEV", _SC_2_C_DEV}, -#endif -#ifdef _SC_2_C_VERSION - {"SC_2_C_VERSION", _SC_2_C_VERSION}, -#endif -#ifdef _SC_2_FORT_DEV - {"SC_2_FORT_DEV", _SC_2_FORT_DEV}, + PyObject *posobj; + if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how)) + return NULL; +#ifdef SEEK_SET + /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ + switch (how) { + case 0: how = SEEK_SET; break; + case 1: how = SEEK_CUR; break; + case 2: how = SEEK_END; break; + } +#endif /* SEEK_END */ + +#if !defined(HAVE_LARGEFILE_SUPPORT) + pos = PyLong_AsLong(posobj); +#else + pos = PyLong_AsLongLong(posobj); #endif -#ifdef _SC_2_FORT_RUN - {"SC_2_FORT_RUN", _SC_2_FORT_RUN}, + if (PyErr_Occurred()) + return NULL; + + if (!_PyVerify_fd(fd)) + return posix_error(); + Py_BEGIN_ALLOW_THREADS +#if defined(MS_WIN64) || defined(MS_WINDOWS) + res = _lseeki64(fd, pos, how); +#else + res = lseek(fd, pos, how); #endif -#ifdef _SC_2_LOCALEDEF - {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF}, + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + +#if !defined(HAVE_LARGEFILE_SUPPORT) + return PyLong_FromLong(res); +#else + return PyLong_FromLongLong(res); #endif -#ifdef _SC_2_SW_DEV - {"SC_2_SW_DEV", _SC_2_SW_DEV}, +} + + +PyDoc_STRVAR(posix_read__doc__, +"read(fd, buffersize) -> string\n\n\ +Read a file descriptor."); + +static PyObject * +posix_read(PyObject *self, PyObject *args) +{ + int fd, size; + Py_ssize_t n; + PyObject *buffer; + if (!PyArg_ParseTuple(args, "ii:read", &fd, &size)) + return NULL; + if (size < 0) { + errno = EINVAL; + return posix_error(); + } + buffer = PyBytes_FromStringAndSize((char *)NULL, size); + if (buffer == NULL) + return NULL; + if (!_PyVerify_fd(fd)) { + Py_DECREF(buffer); + return posix_error(); + } + Py_BEGIN_ALLOW_THREADS + n = read(fd, PyBytes_AS_STRING(buffer), size); + Py_END_ALLOW_THREADS + if (n < 0) { + Py_DECREF(buffer); + return posix_error(); + } + if (n != size) + _PyBytes_Resize(&buffer, n); + return buffer; +} + +#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \ + || defined(__APPLE__))) || defined(HAVE_READV) || defined(HAVE_WRITEV) +static Py_ssize_t +iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type) +{ + int i, j; + Py_ssize_t blen, total = 0; + + *iov = PyMem_New(struct iovec, cnt); + if (*iov == NULL) { + PyErr_NoMemory(); + return total; + } + + *buf = PyMem_New(Py_buffer, cnt); + if (*buf == NULL) { + PyMem_Del(*iov); + PyErr_NoMemory(); + return total; + } + + for (i = 0; i < cnt; i++) { + PyObject *item = PySequence_GetItem(seq, i); + if (item == NULL) + goto fail; + if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) { + Py_DECREF(item); + goto fail; + } + Py_DECREF(item); + (*iov)[i].iov_base = (*buf)[i].buf; + blen = (*buf)[i].len; + (*iov)[i].iov_len = blen; + total += blen; + } + return total; + +fail: + PyMem_Del(*iov); + for (j = 0; j < i; j++) { + PyBuffer_Release(&(*buf)[j]); + } + PyMem_Del(*buf); + return 0; +} + +static void +iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt) +{ + int i; + PyMem_Del(iov); + for (i = 0; i < cnt; i++) { + PyBuffer_Release(&buf[i]); + } + PyMem_Del(buf); +} #endif -#ifdef _SC_2_UPE - {"SC_2_UPE", _SC_2_UPE}, + +#ifdef HAVE_READV +PyDoc_STRVAR(posix_readv__doc__, +"readv(fd, buffers) -> bytesread\n\n\ +Read from a file descriptor into a number of writable buffers. buffers\n\ +is an arbitrary sequence of writable buffers.\n\ +Returns the total number of bytes read."); + +static PyObject * +posix_readv(PyObject *self, PyObject *args) +{ + int fd, cnt; + Py_ssize_t n; + PyObject *seq; + struct iovec *iov; + Py_buffer *buf; + + if (!PyArg_ParseTuple(args, "iO:readv", &fd, &seq)) + return NULL; + if (!PySequence_Check(seq)) { + PyErr_SetString(PyExc_TypeError, + "readv() arg 2 must be a sequence"); + return NULL; + } + cnt = PySequence_Size(seq); + + if (!iov_setup(&iov, &buf, seq, cnt, PyBUF_WRITABLE)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + n = readv(fd, iov, cnt); + Py_END_ALLOW_THREADS + + iov_cleanup(iov, buf, cnt); + return PyLong_FromSsize_t(n); +} #endif -#ifdef _SC_2_VERSION - {"SC_2_VERSION", _SC_2_VERSION}, + +#ifdef HAVE_PREAD +PyDoc_STRVAR(posix_pread__doc__, +"pread(fd, buffersize, offset) -> string\n\n\ +Read from a file descriptor, fd, at a position of offset. It will read up\n\ +to buffersize number of bytes. The file offset remains unchanged."); + +static PyObject * +posix_pread(PyObject *self, PyObject *args) +{ + int fd, size; + off_t offset; + Py_ssize_t n; + PyObject *buffer; + if (!PyArg_ParseTuple(args, "iiO&:pread", &fd, &size, _parse_off_t, &offset)) + return NULL; + + if (size < 0) { + errno = EINVAL; + return posix_error(); + } + buffer = PyBytes_FromStringAndSize((char *)NULL, size); + if (buffer == NULL) + return NULL; + if (!_PyVerify_fd(fd)) { + Py_DECREF(buffer); + return posix_error(); + } + Py_BEGIN_ALLOW_THREADS + n = pread(fd, PyBytes_AS_STRING(buffer), size, offset); + Py_END_ALLOW_THREADS + if (n < 0) { + Py_DECREF(buffer); + return posix_error(); + } + if (n != size) + _PyBytes_Resize(&buffer, n); + return buffer; +} #endif -#ifdef _SC_ABI_ASYNCHRONOUS_IO - {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO}, + +PyDoc_STRVAR(posix_write__doc__, +"write(fd, string) -> byteswritten\n\n\ +Write a string to a file descriptor."); + +static PyObject * +posix_write(PyObject *self, PyObject *args) +{ + Py_buffer pbuf; + int fd; + Py_ssize_t size, len; + + if (!PyArg_ParseTuple(args, "iy*:write", &fd, &pbuf)) + return NULL; + if (!_PyVerify_fd(fd)) { + PyBuffer_Release(&pbuf); + return posix_error(); + } + len = pbuf.len; + Py_BEGIN_ALLOW_THREADS +#if defined(MS_WIN64) || defined(MS_WINDOWS) + if (len > INT_MAX) + len = INT_MAX; + size = write(fd, pbuf.buf, (int)len); +#else + size = write(fd, pbuf.buf, len); #endif -#ifdef _SC_ACL - {"SC_ACL", _SC_ACL}, + Py_END_ALLOW_THREADS + PyBuffer_Release(&pbuf); + if (size < 0) + return posix_error(); + return PyLong_FromSsize_t(size); +} + +#ifdef HAVE_SENDFILE +PyDoc_STRVAR(posix_sendfile__doc__, +"sendfile(out, in, offset, nbytes) -> byteswritten\n\ +sendfile(out, in, offset, nbytes, headers=None, trailers=None, flags=0)\n\ + -> byteswritten\n\ +Copy nbytes bytes from file descriptor in to file descriptor out."); + +static PyObject * +posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict) +{ + int in, out; + Py_ssize_t ret; + off_t offset; + +#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) +#ifndef __APPLE__ + Py_ssize_t len; #endif -#ifdef _SC_AIO_LISTIO_MAX - {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX}, + PyObject *headers = NULL, *trailers = NULL; + Py_buffer *hbuf, *tbuf; + off_t sbytes; + struct sf_hdtr sf; + int flags = 0; + sf.headers = NULL; + sf.trailers = NULL; + static char *keywords[] = {"out", "in", + "offset", "count", + "headers", "trailers", "flags", NULL}; + +#ifdef __APPLE__ + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile", + keywords, &out, &in, _parse_off_t, &offset, _parse_off_t, &sbytes, +#else + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&n|OOi:sendfile", + keywords, &out, &in, _parse_off_t, &offset, &len, #endif -#ifdef _SC_AIO_MAX - {"SC_AIO_MAX", _SC_AIO_MAX}, + &headers, &trailers, &flags)) + return NULL; + if (headers != NULL) { + if (!PySequence_Check(headers)) { + PyErr_SetString(PyExc_TypeError, + "sendfile() headers must be a sequence or None"); + return NULL; + } else { + Py_ssize_t i = 0; /* Avoid uninitialized warning */ + sf.hdr_cnt = PySequence_Size(headers); + if (sf.hdr_cnt > 0 && + !(i = iov_setup(&(sf.headers), &hbuf, + headers, sf.hdr_cnt, PyBUF_SIMPLE))) + return NULL; +#ifdef __APPLE__ + sbytes += i; #endif -#ifdef _SC_AIO_PRIO_DELTA_MAX - {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX}, + } + } + if (trailers != NULL) { + if (!PySequence_Check(trailers)) { + PyErr_SetString(PyExc_TypeError, + "sendfile() trailers must be a sequence or None"); + return NULL; + } else { + Py_ssize_t i = 0; /* Avoid uninitialized warning */ + sf.trl_cnt = PySequence_Size(trailers); + if (sf.trl_cnt > 0 && + !(i = iov_setup(&(sf.trailers), &tbuf, + trailers, sf.trl_cnt, PyBUF_SIMPLE))) + return NULL; +#ifdef __APPLE__ + sbytes += i; #endif -#ifdef _SC_ARG_MAX - {"SC_ARG_MAX", _SC_ARG_MAX}, + } + } + + Py_BEGIN_ALLOW_THREADS +#ifdef __APPLE__ + ret = sendfile(in, out, offset, &sbytes, &sf, flags); +#else + ret = sendfile(in, out, offset, len, &sf, &sbytes, flags); #endif -#ifdef _SC_ASYNCHRONOUS_IO - {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO}, + Py_END_ALLOW_THREADS + + if (sf.headers != NULL) + iov_cleanup(sf.headers, hbuf, sf.hdr_cnt); + if (sf.trailers != NULL) + iov_cleanup(sf.trailers, tbuf, sf.trl_cnt); + + if (ret < 0) { + if ((errno == EAGAIN) || (errno == EBUSY)) { + if (sbytes != 0) { + // some data has been sent + goto done; + } + else { + // no data has been sent; upper application is supposed + // to retry on EAGAIN or EBUSY + return posix_error(); + } + } + return posix_error(); + } + goto done; + +done: + #if !defined(HAVE_LARGEFILE_SUPPORT) + return Py_BuildValue("l", sbytes); + #else + return Py_BuildValue("L", sbytes); + #endif + +#else + Py_ssize_t count; + PyObject *offobj; + static char *keywords[] = {"out", "in", + "offset", "count", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile", + keywords, &out, &in, &offobj, &count)) + return NULL; +#ifdef linux + if (offobj == Py_None) { + Py_BEGIN_ALLOW_THREADS + ret = sendfile(out, in, NULL, count); + Py_END_ALLOW_THREADS + if (ret < 0) + return posix_error(); + return Py_BuildValue("n", ret); + } #endif -#ifdef _SC_ATEXIT_MAX - {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX}, + if (!_parse_off_t(offobj, &offset)) + return NULL; + Py_BEGIN_ALLOW_THREADS + ret = sendfile(out, in, &offset, count); + Py_END_ALLOW_THREADS + if (ret < 0) + return posix_error(); + return Py_BuildValue("n", ret); #endif -#ifdef _SC_AUDIT - {"SC_AUDIT", _SC_AUDIT}, +} #endif -#ifdef _SC_AVPHYS_PAGES - {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES}, -#endif -#ifdef _SC_BC_BASE_MAX - {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX}, -#endif -#ifdef _SC_BC_DIM_MAX - {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX}, -#endif -#ifdef _SC_BC_SCALE_MAX - {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX}, -#endif -#ifdef _SC_BC_STRING_MAX - {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX}, -#endif -#ifdef _SC_CAP - {"SC_CAP", _SC_CAP}, -#endif -#ifdef _SC_CHARCLASS_NAME_MAX - {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX}, -#endif -#ifdef _SC_CHAR_BIT - {"SC_CHAR_BIT", _SC_CHAR_BIT}, -#endif -#ifdef _SC_CHAR_MAX - {"SC_CHAR_MAX", _SC_CHAR_MAX}, -#endif -#ifdef _SC_CHAR_MIN - {"SC_CHAR_MIN", _SC_CHAR_MIN}, -#endif -#ifdef _SC_CHILD_MAX - {"SC_CHILD_MAX", _SC_CHILD_MAX}, -#endif -#ifdef _SC_CLK_TCK - {"SC_CLK_TCK", _SC_CLK_TCK}, -#endif -#ifdef _SC_COHER_BLKSZ - {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ}, -#endif -#ifdef _SC_COLL_WEIGHTS_MAX - {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX}, -#endif -#ifdef _SC_DCACHE_ASSOC - {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC}, -#endif -#ifdef _SC_DCACHE_BLKSZ - {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ}, -#endif -#ifdef _SC_DCACHE_LINESZ - {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ}, + +PyDoc_STRVAR(posix_fstat__doc__, +"fstat(fd) -> stat result\n\n\ +Like stat(), but for an open file descriptor."); + +static PyObject * +posix_fstat(PyObject *self, PyObject *args) +{ + int fd; + STRUCT_STAT st; + int res; + if (!PyArg_ParseTuple(args, "i:fstat", &fd)) + return NULL; +#ifdef __VMS + /* on OpenVMS we must ensure that all bytes are written to the file */ + fsync(fd); #endif -#ifdef _SC_DCACHE_SZ - {"SC_DCACHE_SZ", _SC_DCACHE_SZ}, + if (!_PyVerify_fd(fd)) + return posix_error(); + Py_BEGIN_ALLOW_THREADS + res = FSTAT(fd, &st); + Py_END_ALLOW_THREADS + if (res != 0) { +#ifdef MS_WINDOWS + return win32_error("fstat", NULL); +#else + return posix_error(); #endif -#ifdef _SC_DCACHE_TBLKSZ - {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ}, + } + + return _pystat_fromstructstat(&st); +} + +PyDoc_STRVAR(posix_isatty__doc__, +"isatty(fd) -> bool\n\n\ +Return True if the file descriptor 'fd' is an open file descriptor\n\ +connected to the slave end of a terminal."); + +static PyObject * +posix_isatty(PyObject *self, PyObject *args) +{ + int fd; + if (!PyArg_ParseTuple(args, "i:isatty", &fd)) + return NULL; + if (!_PyVerify_fd(fd)) + return PyBool_FromLong(0); + return PyBool_FromLong(isatty(fd)); +} + +#ifdef HAVE_PIPE +PyDoc_STRVAR(posix_pipe__doc__, +"pipe() -> (read_end, write_end)\n\n\ +Create a pipe."); + +static PyObject * +posix_pipe(PyObject *self, PyObject *noargs) +{ +#if defined(PYOS_OS2) + HFILE read, write; + APIRET rc; + + rc = DosCreatePipe( &read, &write, 4096); + if (rc != NO_ERROR) + return os2_error(rc); + + return Py_BuildValue("(ii)", read, write); +#else +#if !defined(MS_WINDOWS) + int fds[2]; + int res; + res = pipe(fds); + if (res != 0) + return posix_error(); + return Py_BuildValue("(ii)", fds[0], fds[1]); +#else /* MS_WINDOWS */ + HANDLE read, write; + int read_fd, write_fd; + BOOL ok; + ok = CreatePipe(&read, &write, NULL, 0); + if (!ok) + return win32_error("CreatePipe", NULL); + read_fd = _open_osfhandle((Py_intptr_t)read, 0); + write_fd = _open_osfhandle((Py_intptr_t)write, 1); + return Py_BuildValue("(ii)", read_fd, write_fd); +#endif /* MS_WINDOWS */ #endif -#ifdef _SC_DELAYTIMER_MAX - {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX}, +} +#endif /* HAVE_PIPE */ + +#ifdef HAVE_PIPE2 +PyDoc_STRVAR(posix_pipe2__doc__, +"pipe2(flags) -> (read_end, write_end)\n\n\ +Create a pipe with flags set atomically.\n\ +flags can be constructed by ORing together one or more of these values:\n\ +O_NONBLOCK, O_CLOEXEC.\n\ +"); + +static PyObject * +posix_pipe2(PyObject *self, PyObject *arg) +{ + int flags; + int fds[2]; + int res; + + flags = PyLong_AsLong(arg); + if (flags == -1 && PyErr_Occurred()) + return NULL; + + res = pipe2(fds, flags); + if (res != 0) + return posix_error(); + return Py_BuildValue("(ii)", fds[0], fds[1]); +} +#endif /* HAVE_PIPE2 */ + +#ifdef HAVE_WRITEV +PyDoc_STRVAR(posix_writev__doc__, +"writev(fd, buffers) -> byteswritten\n\n\ +Write the contents of buffers to a file descriptor, where buffers is an\n\ +arbitrary sequence of buffers.\n\ +Returns the total bytes written."); + +static PyObject * +posix_writev(PyObject *self, PyObject *args) +{ + int fd, cnt; + Py_ssize_t res; + PyObject *seq; + struct iovec *iov; + Py_buffer *buf; + if (!PyArg_ParseTuple(args, "iO:writev", &fd, &seq)) + return NULL; + if (!PySequence_Check(seq)) { + PyErr_SetString(PyExc_TypeError, + "writev() arg 2 must be a sequence"); + return NULL; + } + cnt = PySequence_Size(seq); + + if (!iov_setup(&iov, &buf, seq, cnt, PyBUF_SIMPLE)) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + res = writev(fd, iov, cnt); + Py_END_ALLOW_THREADS + + iov_cleanup(iov, buf, cnt); + return PyLong_FromSsize_t(res); +} #endif -#ifdef _SC_EQUIV_CLASS_MAX - {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX}, + +#ifdef HAVE_PWRITE +PyDoc_STRVAR(posix_pwrite__doc__, +"pwrite(fd, string, offset) -> byteswritten\n\n\ +Write string to a file descriptor, fd, from offset, leaving the file\n\ +offset unchanged."); + +static PyObject * +posix_pwrite(PyObject *self, PyObject *args) +{ + Py_buffer pbuf; + int fd; + off_t offset; + Py_ssize_t size; + + if (!PyArg_ParseTuple(args, "iy*O&:pwrite", &fd, &pbuf, _parse_off_t, &offset)) + return NULL; + + if (!_PyVerify_fd(fd)) { + PyBuffer_Release(&pbuf); + return posix_error(); + } + Py_BEGIN_ALLOW_THREADS + size = pwrite(fd, pbuf.buf, (size_t)pbuf.len, offset); + Py_END_ALLOW_THREADS + PyBuffer_Release(&pbuf); + if (size < 0) + return posix_error(); + return PyLong_FromSsize_t(size); +} #endif -#ifdef _SC_EXPR_NEST_MAX - {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX}, + +#ifdef HAVE_MKFIFO +PyDoc_STRVAR(posix_mkfifo__doc__, +"mkfifo(filename [, mode=0666])\n\n\ +Create a FIFO (a POSIX named pipe)."); + +static PyObject * +posix_mkfifo(PyObject *self, PyObject *args) +{ + PyObject *opath; + char *filename; + int mode = 0666; + int res; + if (!PyArg_ParseTuple(args, "O&|i:mkfifo", PyUnicode_FSConverter, &opath, + &mode)) + return NULL; + filename = PyBytes_AS_STRING(opath); + Py_BEGIN_ALLOW_THREADS + res = mkfifo(filename, mode); + Py_END_ALLOW_THREADS + Py_DECREF(opath); + if (res < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} #endif -#ifdef _SC_FSYNC - {"SC_FSYNC", _SC_FSYNC}, + + +#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) +PyDoc_STRVAR(posix_mknod__doc__, +"mknod(filename [, mode=0600, device])\n\n\ +Create a filesystem node (file, device special file or named pipe)\n\ +named filename. mode specifies both the permissions to use and the\n\ +type of node to be created, being combined (bitwise OR) with one of\n\ +S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\ +device defines the newly created device special file (probably using\n\ +os.makedev()), otherwise it is ignored."); + + +static PyObject * +posix_mknod(PyObject *self, PyObject *args) +{ + PyObject *opath; + char *filename; + int mode = 0600; + int device = 0; + int res; + if (!PyArg_ParseTuple(args, "O&|ii:mknod", PyUnicode_FSConverter, &opath, + &mode, &device)) + return NULL; + filename = PyBytes_AS_STRING(opath); + Py_BEGIN_ALLOW_THREADS + res = mknod(filename, mode, device); + Py_END_ALLOW_THREADS + Py_DECREF(opath); + if (res < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} #endif -#ifdef _SC_GETGR_R_SIZE_MAX - {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX}, -#endif -#ifdef _SC_GETPW_R_SIZE_MAX - {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX}, -#endif -#ifdef _SC_ICACHE_ASSOC - {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC}, -#endif -#ifdef _SC_ICACHE_BLKSZ - {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ}, -#endif -#ifdef _SC_ICACHE_LINESZ - {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ}, -#endif -#ifdef _SC_ICACHE_SZ - {"SC_ICACHE_SZ", _SC_ICACHE_SZ}, -#endif -#ifdef _SC_INF - {"SC_INF", _SC_INF}, -#endif -#ifdef _SC_INT_MAX - {"SC_INT_MAX", _SC_INT_MAX}, -#endif -#ifdef _SC_INT_MIN - {"SC_INT_MIN", _SC_INT_MIN}, -#endif -#ifdef _SC_IOV_MAX - {"SC_IOV_MAX", _SC_IOV_MAX}, -#endif -#ifdef _SC_IP_SECOPTS - {"SC_IP_SECOPTS", _SC_IP_SECOPTS}, -#endif -#ifdef _SC_JOB_CONTROL - {"SC_JOB_CONTROL", _SC_JOB_CONTROL}, -#endif -#ifdef _SC_KERN_POINTERS - {"SC_KERN_POINTERS", _SC_KERN_POINTERS}, -#endif -#ifdef _SC_KERN_SIM - {"SC_KERN_SIM", _SC_KERN_SIM}, -#endif -#ifdef _SC_LINE_MAX - {"SC_LINE_MAX", _SC_LINE_MAX}, -#endif -#ifdef _SC_LOGIN_NAME_MAX - {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX}, -#endif -#ifdef _SC_LOGNAME_MAX - {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX}, + +#ifdef HAVE_DEVICE_MACROS +PyDoc_STRVAR(posix_major__doc__, +"major(device) -> major number\n\ +Extracts a device major number from a raw device number."); + +static PyObject * +posix_major(PyObject *self, PyObject *args) +{ + int device; + if (!PyArg_ParseTuple(args, "i:major", &device)) + return NULL; + return PyLong_FromLong((long)major(device)); +} + +PyDoc_STRVAR(posix_minor__doc__, +"minor(device) -> minor number\n\ +Extracts a device minor number from a raw device number."); + +static PyObject * +posix_minor(PyObject *self, PyObject *args) +{ + int device; + if (!PyArg_ParseTuple(args, "i:minor", &device)) + return NULL; + return PyLong_FromLong((long)minor(device)); +} + +PyDoc_STRVAR(posix_makedev__doc__, +"makedev(major, minor) -> device number\n\ +Composes a raw device number from the major and minor device numbers."); + +static PyObject * +posix_makedev(PyObject *self, PyObject *args) +{ + int major, minor; + if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor)) + return NULL; + return PyLong_FromLong((long)makedev(major, minor)); +} +#endif /* device macros */ + + +#ifdef HAVE_FTRUNCATE +PyDoc_STRVAR(posix_ftruncate__doc__, +"ftruncate(fd, length)\n\n\ +Truncate a file to a specified length."); + +static PyObject * +posix_ftruncate(PyObject *self, PyObject *args) +{ + int fd; + off_t length; + int res; + + if (!PyArg_ParseTuple(args, "iO&:ftruncate", &fd, _parse_off_t, &length)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + res = ftruncate(fd, length); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} #endif -#ifdef _SC_LONG_BIT - {"SC_LONG_BIT", _SC_LONG_BIT}, + +#ifdef HAVE_TRUNCATE +PyDoc_STRVAR(posix_truncate__doc__, +"truncate(path, length)\n\n\ +Truncate the file given by path to length bytes."); + +static PyObject * +posix_truncate(PyObject *self, PyObject *args) +{ + PyObject *opath; + const char *path; + off_t length; + int res; + + if (!PyArg_ParseTuple(args, "O&O&:truncate", + PyUnicode_FSConverter, &opath, _parse_off_t, &length)) + return NULL; + path = PyBytes_AsString(opath); + + Py_BEGIN_ALLOW_THREADS + res = truncate(path, length); + Py_END_ALLOW_THREADS + Py_DECREF(opath); + if (res < 0) + return posix_error(); + Py_RETURN_NONE; +} #endif -#ifdef _SC_MAC - {"SC_MAC", _SC_MAC}, + +#ifdef HAVE_POSIX_FALLOCATE +PyDoc_STRVAR(posix_posix_fallocate__doc__, +"posix_fallocate(fd, offset, len)\n\n\ +Ensures that enough disk space is allocated for the file specified by fd\n\ +starting from offset and continuing for len bytes."); + +static PyObject * +posix_posix_fallocate(PyObject *self, PyObject *args) +{ + off_t len, offset; + int res, fd; + + if (!PyArg_ParseTuple(args, "iO&O&:posix_fallocate", + &fd, _parse_off_t, &offset, _parse_off_t, &len)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + res = posix_fallocate(fd, offset, len); + Py_END_ALLOW_THREADS + if (res != 0) { + errno = res; + return posix_error(); + } + Py_RETURN_NONE; +} #endif -#ifdef _SC_MAPPED_FILES - {"SC_MAPPED_FILES", _SC_MAPPED_FILES}, + +#ifdef HAVE_POSIX_FADVISE +PyDoc_STRVAR(posix_posix_fadvise__doc__, +"posix_fadvise(fd, offset, len, advice)\n\n\ +Announces an intention to access data in a specific pattern thus allowing\n\ +the kernel to make optimizations.\n\ +The advice applies to the region of the file specified by fd starting at\n\ +offset and continuing for len bytes.\n\ +advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,\n\ +POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED or\n\ +POSIX_FADV_DONTNEED."); + +static PyObject * +posix_posix_fadvise(PyObject *self, PyObject *args) +{ + off_t len, offset; + int res, fd, advice; + + if (!PyArg_ParseTuple(args, "iO&O&i:posix_fadvise", + &fd, _parse_off_t, &offset, _parse_off_t, &len, &advice)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + res = posix_fadvise(fd, offset, len, advice); + Py_END_ALLOW_THREADS + if (res != 0) { + errno = res; + return posix_error(); + } + Py_RETURN_NONE; +} #endif -#ifdef _SC_MAXPID - {"SC_MAXPID", _SC_MAXPID}, + +#ifdef HAVE_PUTENV +PyDoc_STRVAR(posix_putenv__doc__, +"putenv(key, value)\n\n\ +Change or add an environment variable."); + +/* Save putenv() parameters as values here, so we can collect them when they + * get re-set with another call for the same key. */ +static PyObject *posix_putenv_garbage; + +static PyObject * +posix_putenv(PyObject *self, PyObject *args) +{ + PyObject *newstr = NULL; +#ifdef MS_WINDOWS + PyObject *os1, *os2; + wchar_t *newenv; + + if (!PyArg_ParseTuple(args, + "UU:putenv", + &os1, &os2)) + return NULL; + + newstr = PyUnicode_FromFormat("%U=%U", os1, os2); + if (newstr == NULL) { + PyErr_NoMemory(); + goto error; + } + if (_MAX_ENV < PyUnicode_GET_LENGTH(newstr)) { + PyErr_Format(PyExc_ValueError, + "the environment variable is longer than %u characters", + _MAX_ENV); + goto error; + } + + newenv = PyUnicode_AsUnicode(newstr); + if (newenv == NULL) + goto error; + if (_wputenv(newenv)) { + posix_error(); + goto error; + } +#else + PyObject *os1, *os2; + char *s1, *s2; + char *newenv; + + if (!PyArg_ParseTuple(args, + "O&O&:putenv", + PyUnicode_FSConverter, &os1, + PyUnicode_FSConverter, &os2)) + return NULL; + s1 = PyBytes_AsString(os1); + s2 = PyBytes_AsString(os2); + + newstr = PyBytes_FromFormat("%s=%s", s1, s2); + if (newstr == NULL) { + PyErr_NoMemory(); + goto error; + } + + newenv = PyBytes_AS_STRING(newstr); + if (putenv(newenv)) { + posix_error(); + goto error; + } #endif -#ifdef _SC_MB_LEN_MAX - {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX}, + + /* Install the first arg and newstr in posix_putenv_garbage; + * this will cause previous value to be collected. This has to + * happen after the real putenv() call because the old value + * was still accessible until then. */ + if (PyDict_SetItem(posix_putenv_garbage, os1, newstr)) { + /* really not much we can do; just leak */ + PyErr_Clear(); + } + else { + Py_DECREF(newstr); + } + +#ifndef MS_WINDOWS + Py_DECREF(os1); + Py_DECREF(os2); #endif -#ifdef _SC_MEMLOCK - {"SC_MEMLOCK", _SC_MEMLOCK}, + Py_RETURN_NONE; + +error: +#ifndef MS_WINDOWS + Py_DECREF(os1); + Py_DECREF(os2); #endif -#ifdef _SC_MEMLOCK_RANGE - {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE}, + Py_XDECREF(newstr); + return NULL; +} +#endif /* putenv */ + +#ifdef HAVE_UNSETENV +PyDoc_STRVAR(posix_unsetenv__doc__, +"unsetenv(key)\n\n\ +Delete an environment variable."); + +static PyObject * +posix_unsetenv(PyObject *self, PyObject *args) +{ + PyObject *name; + int err; + + if (!PyArg_ParseTuple(args, "O&:unsetenv", ++ + PyUnicode_FSConverter, &name)) + return NULL; + ++ + err = unsetenv(PyBytes_AS_STRING(name)); - if (err) ++ if (err) { ++ Py_DECREF(name); + return posix_error(); ++ } + + /* Remove the key from posix_putenv_garbage; + * this will cause it to be collected. This has to + * happen after the real unsetenv() call because the + * old value was still accessible until then. + */ + if (PyDict_DelItem(posix_putenv_garbage, name)) { + /* really not much we can do; just leak */ + PyErr_Clear(); + } + Py_DECREF(name); + Py_RETURN_NONE; +} +#endif /* unsetenv */ + +PyDoc_STRVAR(posix_strerror__doc__, +"strerror(code) -> string\n\n\ +Translate an error code to a message string."); + +static PyObject * +posix_strerror(PyObject *self, PyObject *args) +{ + int code; + char *message; + if (!PyArg_ParseTuple(args, "i:strerror", &code)) + return NULL; + message = strerror(code); + if (message == NULL) { + PyErr_SetString(PyExc_ValueError, + "strerror() argument out of range"); + return NULL; + } + return PyUnicode_FromString(message); +} + + +#ifdef HAVE_SYS_WAIT_H + +#ifdef WCOREDUMP +PyDoc_STRVAR(posix_WCOREDUMP__doc__, +"WCOREDUMP(status) -> bool\n\n\ +Return True if the process returning 'status' was dumped to a core file."); + +static PyObject * +posix_WCOREDUMP(PyObject *self, PyObject *args) +{ + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status))) + return NULL; + + return PyBool_FromLong(WCOREDUMP(status)); +} +#endif /* WCOREDUMP */ + +#ifdef WIFCONTINUED +PyDoc_STRVAR(posix_WIFCONTINUED__doc__, +"WIFCONTINUED(status) -> bool\n\n\ +Return True if the process returning 'status' was continued from a\n\ +job control stop."); + +static PyObject * +posix_WIFCONTINUED(PyObject *self, PyObject *args) +{ + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status))) + return NULL; + + return PyBool_FromLong(WIFCONTINUED(status)); +} +#endif /* WIFCONTINUED */ + +#ifdef WIFSTOPPED +PyDoc_STRVAR(posix_WIFSTOPPED__doc__, +"WIFSTOPPED(status) -> bool\n\n\ +Return True if the process returning 'status' was stopped."); + +static PyObject * +posix_WIFSTOPPED(PyObject *self, PyObject *args) +{ + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status))) + return NULL; + + return PyBool_FromLong(WIFSTOPPED(status)); +} +#endif /* WIFSTOPPED */ + +#ifdef WIFSIGNALED +PyDoc_STRVAR(posix_WIFSIGNALED__doc__, +"WIFSIGNALED(status) -> bool\n\n\ +Return True if the process returning 'status' was terminated by a signal."); + +static PyObject * +posix_WIFSIGNALED(PyObject *self, PyObject *args) +{ + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status))) + return NULL; + + return PyBool_FromLong(WIFSIGNALED(status)); +} +#endif /* WIFSIGNALED */ + +#ifdef WIFEXITED +PyDoc_STRVAR(posix_WIFEXITED__doc__, +"WIFEXITED(status) -> bool\n\n\ +Return true if the process returning 'status' exited using the exit()\n\ +system call."); + +static PyObject * +posix_WIFEXITED(PyObject *self, PyObject *args) +{ + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status))) + return NULL; + + return PyBool_FromLong(WIFEXITED(status)); +} +#endif /* WIFEXITED */ + +#ifdef WEXITSTATUS +PyDoc_STRVAR(posix_WEXITSTATUS__doc__, +"WEXITSTATUS(status) -> integer\n\n\ +Return the process return code from 'status'."); + +static PyObject * +posix_WEXITSTATUS(PyObject *self, PyObject *args) +{ + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status))) + return NULL; + + return Py_BuildValue("i", WEXITSTATUS(status)); +} +#endif /* WEXITSTATUS */ + +#ifdef WTERMSIG +PyDoc_STRVAR(posix_WTERMSIG__doc__, +"WTERMSIG(status) -> integer\n\n\ +Return the signal that terminated the process that provided the 'status'\n\ +value."); + +static PyObject * +posix_WTERMSIG(PyObject *self, PyObject *args) +{ + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status))) + return NULL; + + return Py_BuildValue("i", WTERMSIG(status)); +} +#endif /* WTERMSIG */ + +#ifdef WSTOPSIG +PyDoc_STRVAR(posix_WSTOPSIG__doc__, +"WSTOPSIG(status) -> integer\n\n\ +Return the signal that stopped the process that provided\n\ +the 'status' value."); + +static PyObject * +posix_WSTOPSIG(PyObject *self, PyObject *args) +{ + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status))) + return NULL; + + return Py_BuildValue("i", WSTOPSIG(status)); +} +#endif /* WSTOPSIG */ + +#endif /* HAVE_SYS_WAIT_H */ + + +#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) +#ifdef _SCO_DS +/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the + needed definitions in sys/statvfs.h */ +#define _SVID3 +#endif +#include + +static PyObject* +_pystatvfs_fromstructstatvfs(struct statvfs st) { + PyObject *v = PyStructSequence_New(&StatVFSResultType); + if (v == NULL) + return NULL; + +#if !defined(HAVE_LARGEFILE_SUPPORT) + PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); + PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); + PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks)); + PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree)); + PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail)); + PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files)); + PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree)); + PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail)); + PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); + PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); +#else + PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); + PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); + PyStructSequence_SET_ITEM(v, 2, + PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks)); + PyStructSequence_SET_ITEM(v, 3, + PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree)); + PyStructSequence_SET_ITEM(v, 4, + PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail)); + PyStructSequence_SET_ITEM(v, 5, + PyLong_FromLongLong((PY_LONG_LONG) st.f_files)); + PyStructSequence_SET_ITEM(v, 6, + PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree)); + PyStructSequence_SET_ITEM(v, 7, + PyLong_FromLongLong((PY_LONG_LONG) st.f_favail)); + PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); + PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); +#endif + + return v; +} + +PyDoc_STRVAR(posix_fstatvfs__doc__, +"fstatvfs(fd) -> statvfs result\n\n\ +Perform an fstatvfs system call on the given fd."); + +static PyObject * +posix_fstatvfs(PyObject *self, PyObject *args) +{ + int fd, res; + struct statvfs st; + + if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd)) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = fstatvfs(fd, &st); + Py_END_ALLOW_THREADS + if (res != 0) + return posix_error(); + + return _pystatvfs_fromstructstatvfs(st); +} +#endif /* HAVE_FSTATVFS && HAVE_SYS_STATVFS_H */ + + +#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) +#include + +PyDoc_STRVAR(posix_statvfs__doc__, +"statvfs(path) -> statvfs result\n\n\ +Perform a statvfs system call on the given path."); + +static PyObject * +posix_statvfs(PyObject *self, PyObject *args) +{ + PyObject *path; + int res; + struct statvfs st; + if (!PyArg_ParseTuple(args, "O&:statvfs", PyUnicode_FSConverter, &path)) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = statvfs(PyBytes_AS_STRING(path), &st); + Py_END_ALLOW_THREADS + if (res != 0) { + posix_error_with_filename(PyBytes_AS_STRING(path)); + Py_DECREF(path); + return NULL; + } + Py_DECREF(path); + + return _pystatvfs_fromstructstatvfs(st); +} +#endif /* HAVE_STATVFS */ + +#ifdef MS_WINDOWS +PyDoc_STRVAR(win32__getdiskusage__doc__, +"_getdiskusage(path) -> (total, free)\n\n\ +Return disk usage statistics about the given path as (total, free) tuple."); + +static PyObject * +win32__getdiskusage(PyObject *self, PyObject *args) +{ + BOOL retval; + ULARGE_INTEGER _, total, free; + const wchar_t *path; + + if (! PyArg_ParseTuple(args, "u", &path)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + retval = GetDiskFreeSpaceExW(path, &_, &total, &free); + Py_END_ALLOW_THREADS + if (retval == 0) + return PyErr_SetFromWindowsErr(0); + + return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart); +} +#endif + + +/* This is used for fpathconf(), pathconf(), confstr() and sysconf(). + * It maps strings representing configuration variable names to + * integer values, allowing those functions to be called with the + * magic names instead of polluting the module's namespace with tons of + * rarely-used constants. There are three separate tables that use + * these definitions. + * + * This code is always included, even if none of the interfaces that + * need it are included. The #if hackery needed to avoid it would be + * sufficiently pervasive that it's not worth the loss of readability. + */ +struct constdef { + char *name; + long value; +}; + +static int +conv_confname(PyObject *arg, int *valuep, struct constdef *table, + size_t tablesize) +{ + if (PyLong_Check(arg)) { + *valuep = PyLong_AS_LONG(arg); + return 1; + } + else { + /* look up the value in the table using a binary search */ + size_t lo = 0; + size_t mid; + size_t hi = tablesize; + int cmp; + const char *confname; + if (!PyUnicode_Check(arg)) { + PyErr_SetString(PyExc_TypeError, + "configuration names must be strings or integers"); + return 0; + } + confname = _PyUnicode_AsString(arg); + if (confname == NULL) + return 0; + while (lo < hi) { + mid = (lo + hi) / 2; + cmp = strcmp(confname, table[mid].name); + if (cmp < 0) + hi = mid; + else if (cmp > 0) + lo = mid + 1; + else { + *valuep = table[mid].value; + return 1; + } + } + PyErr_SetString(PyExc_ValueError, "unrecognized configuration name"); + return 0; + } +} + + +#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) +static struct constdef posix_constants_pathconf[] = { +#ifdef _PC_ABI_AIO_XFER_MAX + {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX}, +#endif +#ifdef _PC_ABI_ASYNC_IO + {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO}, +#endif +#ifdef _PC_ASYNC_IO + {"PC_ASYNC_IO", _PC_ASYNC_IO}, +#endif +#ifdef _PC_CHOWN_RESTRICTED + {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED}, +#endif +#ifdef _PC_FILESIZEBITS + {"PC_FILESIZEBITS", _PC_FILESIZEBITS}, +#endif +#ifdef _PC_LAST + {"PC_LAST", _PC_LAST}, +#endif +#ifdef _PC_LINK_MAX + {"PC_LINK_MAX", _PC_LINK_MAX}, +#endif +#ifdef _PC_MAX_CANON + {"PC_MAX_CANON", _PC_MAX_CANON}, +#endif +#ifdef _PC_MAX_INPUT + {"PC_MAX_INPUT", _PC_MAX_INPUT}, +#endif +#ifdef _PC_NAME_MAX + {"PC_NAME_MAX", _PC_NAME_MAX}, +#endif +#ifdef _PC_NO_TRUNC + {"PC_NO_TRUNC", _PC_NO_TRUNC}, +#endif +#ifdef _PC_PATH_MAX + {"PC_PATH_MAX", _PC_PATH_MAX}, +#endif +#ifdef _PC_PIPE_BUF + {"PC_PIPE_BUF", _PC_PIPE_BUF}, +#endif +#ifdef _PC_PRIO_IO + {"PC_PRIO_IO", _PC_PRIO_IO}, +#endif +#ifdef _PC_SOCK_MAXBUF + {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF}, +#endif +#ifdef _PC_SYNC_IO + {"PC_SYNC_IO", _PC_SYNC_IO}, +#endif +#ifdef _PC_VDISABLE + {"PC_VDISABLE", _PC_VDISABLE}, +#endif +#ifdef _PC_ACL_ENABLED + {"PC_ACL_ENABLED", _PC_ACL_ENABLED}, +#endif +#ifdef _PC_MIN_HOLE_SIZE + {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE}, +#endif +#ifdef _PC_ALLOC_SIZE_MIN + {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN}, +#endif +#ifdef _PC_REC_INCR_XFER_SIZE + {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE}, +#endif +#ifdef _PC_REC_MAX_XFER_SIZE + {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE}, +#endif +#ifdef _PC_REC_MIN_XFER_SIZE + {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE}, +#endif +#ifdef _PC_REC_XFER_ALIGN + {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN}, +#endif +#ifdef _PC_SYMLINK_MAX + {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX}, +#endif +#ifdef _PC_XATTR_ENABLED + {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED}, +#endif +#ifdef _PC_XATTR_EXISTS + {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS}, +#endif +#ifdef _PC_TIMESTAMP_RESOLUTION + {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION}, +#endif +}; + +static int +conv_path_confname(PyObject *arg, int *valuep) +{ + return conv_confname(arg, valuep, posix_constants_pathconf, + sizeof(posix_constants_pathconf) + / sizeof(struct constdef)); +} +#endif + +#ifdef HAVE_FPATHCONF +PyDoc_STRVAR(posix_fpathconf__doc__, +"fpathconf(fd, name) -> integer\n\n\ +Return the configuration limit name for the file descriptor fd.\n\ +If there is no limit, return -1."); + +static PyObject * +posix_fpathconf(PyObject *self, PyObject *args) +{ + PyObject *result = NULL; + int name, fd; + + if (PyArg_ParseTuple(args, "iO&:fpathconf", &fd, + conv_path_confname, &name)) { + long limit; + + errno = 0; + limit = fpathconf(fd, name); + if (limit == -1 && errno != 0) + posix_error(); + else + result = PyLong_FromLong(limit); + } + return result; +} +#endif + + +#ifdef HAVE_PATHCONF +PyDoc_STRVAR(posix_pathconf__doc__, +"pathconf(path, name) -> integer\n\n\ +Return the configuration limit name for the file or directory path.\n\ +If there is no limit, return -1."); + +static PyObject * +posix_pathconf(PyObject *self, PyObject *args) +{ + PyObject *result = NULL; + int name; + char *path; + + if (PyArg_ParseTuple(args, "sO&:pathconf", &path, + conv_path_confname, &name)) { + long limit; + + errno = 0; + limit = pathconf(path, name); + if (limit == -1 && errno != 0) { + if (errno == EINVAL) + /* could be a path or name problem */ + posix_error(); + else + posix_error_with_filename(path); + } + else + result = PyLong_FromLong(limit); + } + return result; +} +#endif + +#ifdef HAVE_CONFSTR +static struct constdef posix_constants_confstr[] = { +#ifdef _CS_ARCHITECTURE + {"CS_ARCHITECTURE", _CS_ARCHITECTURE}, +#endif +#ifdef _CS_GNU_LIBC_VERSION + {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION}, +#endif +#ifdef _CS_GNU_LIBPTHREAD_VERSION + {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION}, +#endif +#ifdef _CS_HOSTNAME + {"CS_HOSTNAME", _CS_HOSTNAME}, +#endif +#ifdef _CS_HW_PROVIDER + {"CS_HW_PROVIDER", _CS_HW_PROVIDER}, +#endif +#ifdef _CS_HW_SERIAL + {"CS_HW_SERIAL", _CS_HW_SERIAL}, +#endif +#ifdef _CS_INITTAB_NAME + {"CS_INITTAB_NAME", _CS_INITTAB_NAME}, +#endif +#ifdef _CS_LFS64_CFLAGS + {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS}, +#endif +#ifdef _CS_LFS64_LDFLAGS + {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS}, +#endif +#ifdef _CS_LFS64_LIBS + {"CS_LFS64_LIBS", _CS_LFS64_LIBS}, +#endif +#ifdef _CS_LFS64_LINTFLAGS + {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS}, +#endif +#ifdef _CS_LFS_CFLAGS + {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS}, +#endif +#ifdef _CS_LFS_LDFLAGS + {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS}, +#endif +#ifdef _CS_LFS_LIBS + {"CS_LFS_LIBS", _CS_LFS_LIBS}, +#endif +#ifdef _CS_LFS_LINTFLAGS + {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS}, +#endif +#ifdef _CS_MACHINE + {"CS_MACHINE", _CS_MACHINE}, +#endif +#ifdef _CS_PATH + {"CS_PATH", _CS_PATH}, +#endif +#ifdef _CS_RELEASE + {"CS_RELEASE", _CS_RELEASE}, +#endif +#ifdef _CS_SRPC_DOMAIN + {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN}, +#endif +#ifdef _CS_SYSNAME + {"CS_SYSNAME", _CS_SYSNAME}, +#endif +#ifdef _CS_VERSION + {"CS_VERSION", _CS_VERSION}, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS + {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS + {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_LIBS + {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS}, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS + {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS + {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS + {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS + {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS}, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS + {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS}, +#endif +#ifdef _CS_XBS5_LP64_OFF64_CFLAGS + {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS}, +#endif +#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS + {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS}, +#endif +#ifdef _CS_XBS5_LP64_OFF64_LIBS + {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS}, +#endif +#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS + {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS}, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS + {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS}, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS + {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS}, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS + {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS}, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS + {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS}, +#endif +#ifdef _MIPS_CS_AVAIL_PROCESSORS + {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS}, +#endif +#ifdef _MIPS_CS_BASE + {"MIPS_CS_BASE", _MIPS_CS_BASE}, +#endif +#ifdef _MIPS_CS_HOSTID + {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID}, +#endif +#ifdef _MIPS_CS_HW_NAME + {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME}, +#endif +#ifdef _MIPS_CS_NUM_PROCESSORS + {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS}, +#endif +#ifdef _MIPS_CS_OSREL_MAJ + {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ}, +#endif +#ifdef _MIPS_CS_OSREL_MIN + {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN}, +#endif +#ifdef _MIPS_CS_OSREL_PATCH + {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH}, +#endif +#ifdef _MIPS_CS_OS_NAME + {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME}, +#endif +#ifdef _MIPS_CS_OS_PROVIDER + {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER}, +#endif +#ifdef _MIPS_CS_PROCESSORS + {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS}, +#endif +#ifdef _MIPS_CS_SERIAL + {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL}, +#endif +#ifdef _MIPS_CS_VENDOR + {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR}, +#endif +}; + +static int +conv_confstr_confname(PyObject *arg, int *valuep) +{ + return conv_confname(arg, valuep, posix_constants_confstr, + sizeof(posix_constants_confstr) + / sizeof(struct constdef)); +} + +PyDoc_STRVAR(posix_confstr__doc__, +"confstr(name) -> string\n\n\ +Return a string-valued system configuration variable."); + +static PyObject * +posix_confstr(PyObject *self, PyObject *args) +{ + PyObject *result = NULL; + int name; + char buffer[255]; + int len; + + if (!PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name)) + return NULL; + + errno = 0; + len = confstr(name, buffer, sizeof(buffer)); + if (len == 0) { + if (errno) { + posix_error(); + return NULL; + } + else { + Py_RETURN_NONE; + } + } + + if ((unsigned int)len >= sizeof(buffer)) { + char *buf = PyMem_Malloc(len); + if (buf == NULL) + return PyErr_NoMemory(); + confstr(name, buf, len); + result = PyUnicode_DecodeFSDefaultAndSize(buf, len-1); + PyMem_Free(buf); + } + else + result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1); + return result; +} +#endif + + +#ifdef HAVE_SYSCONF +static struct constdef posix_constants_sysconf[] = { +#ifdef _SC_2_CHAR_TERM + {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM}, +#endif +#ifdef _SC_2_C_BIND + {"SC_2_C_BIND", _SC_2_C_BIND}, +#endif +#ifdef _SC_2_C_DEV + {"SC_2_C_DEV", _SC_2_C_DEV}, +#endif +#ifdef _SC_2_C_VERSION + {"SC_2_C_VERSION", _SC_2_C_VERSION}, +#endif +#ifdef _SC_2_FORT_DEV + {"SC_2_FORT_DEV", _SC_2_FORT_DEV}, +#endif +#ifdef _SC_2_FORT_RUN + {"SC_2_FORT_RUN", _SC_2_FORT_RUN}, +#endif +#ifdef _SC_2_LOCALEDEF + {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF}, +#endif +#ifdef _SC_2_SW_DEV + {"SC_2_SW_DEV", _SC_2_SW_DEV}, +#endif +#ifdef _SC_2_UPE + {"SC_2_UPE", _SC_2_UPE}, +#endif +#ifdef _SC_2_VERSION + {"SC_2_VERSION", _SC_2_VERSION}, +#endif +#ifdef _SC_ABI_ASYNCHRONOUS_IO + {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO}, +#endif +#ifdef _SC_ACL + {"SC_ACL", _SC_ACL}, +#endif +#ifdef _SC_AIO_LISTIO_MAX + {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX}, +#endif +#ifdef _SC_AIO_MAX + {"SC_AIO_MAX", _SC_AIO_MAX}, +#endif +#ifdef _SC_AIO_PRIO_DELTA_MAX + {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX}, +#endif +#ifdef _SC_ARG_MAX + {"SC_ARG_MAX", _SC_ARG_MAX}, +#endif +#ifdef _SC_ASYNCHRONOUS_IO + {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO}, +#endif +#ifdef _SC_ATEXIT_MAX + {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX}, +#endif +#ifdef _SC_AUDIT + {"SC_AUDIT", _SC_AUDIT}, +#endif +#ifdef _SC_AVPHYS_PAGES + {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES}, +#endif +#ifdef _SC_BC_BASE_MAX + {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX}, +#endif +#ifdef _SC_BC_DIM_MAX + {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX}, +#endif +#ifdef _SC_BC_SCALE_MAX + {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX}, +#endif +#ifdef _SC_BC_STRING_MAX + {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX}, +#endif +#ifdef _SC_CAP + {"SC_CAP", _SC_CAP}, +#endif +#ifdef _SC_CHARCLASS_NAME_MAX + {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX}, +#endif +#ifdef _SC_CHAR_BIT + {"SC_CHAR_BIT", _SC_CHAR_BIT}, +#endif +#ifdef _SC_CHAR_MAX + {"SC_CHAR_MAX", _SC_CHAR_MAX}, +#endif +#ifdef _SC_CHAR_MIN + {"SC_CHAR_MIN", _SC_CHAR_MIN}, +#endif +#ifdef _SC_CHILD_MAX + {"SC_CHILD_MAX", _SC_CHILD_MAX}, +#endif +#ifdef _SC_CLK_TCK + {"SC_CLK_TCK", _SC_CLK_TCK}, +#endif +#ifdef _SC_COHER_BLKSZ + {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ}, +#endif +#ifdef _SC_COLL_WEIGHTS_MAX + {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX}, +#endif +#ifdef _SC_DCACHE_ASSOC + {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC}, +#endif +#ifdef _SC_DCACHE_BLKSZ + {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ}, +#endif +#ifdef _SC_DCACHE_LINESZ + {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ}, +#endif +#ifdef _SC_DCACHE_SZ + {"SC_DCACHE_SZ", _SC_DCACHE_SZ}, +#endif +#ifdef _SC_DCACHE_TBLKSZ + {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ}, +#endif +#ifdef _SC_DELAYTIMER_MAX + {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX}, +#endif +#ifdef _SC_EQUIV_CLASS_MAX + {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX}, +#endif +#ifdef _SC_EXPR_NEST_MAX + {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX}, +#endif +#ifdef _SC_FSYNC + {"SC_FSYNC", _SC_FSYNC}, +#endif +#ifdef _SC_GETGR_R_SIZE_MAX + {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX}, +#endif +#ifdef _SC_GETPW_R_SIZE_MAX + {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX}, +#endif +#ifdef _SC_ICACHE_ASSOC + {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC}, +#endif +#ifdef _SC_ICACHE_BLKSZ + {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ}, +#endif +#ifdef _SC_ICACHE_LINESZ + {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ}, +#endif +#ifdef _SC_ICACHE_SZ + {"SC_ICACHE_SZ", _SC_ICACHE_SZ}, +#endif +#ifdef _SC_INF + {"SC_INF", _SC_INF}, +#endif +#ifdef _SC_INT_MAX + {"SC_INT_MAX", _SC_INT_MAX}, +#endif +#ifdef _SC_INT_MIN + {"SC_INT_MIN", _SC_INT_MIN}, +#endif +#ifdef _SC_IOV_MAX + {"SC_IOV_MAX", _SC_IOV_MAX}, +#endif +#ifdef _SC_IP_SECOPTS + {"SC_IP_SECOPTS", _SC_IP_SECOPTS}, +#endif +#ifdef _SC_JOB_CONTROL + {"SC_JOB_CONTROL", _SC_JOB_CONTROL}, +#endif +#ifdef _SC_KERN_POINTERS + {"SC_KERN_POINTERS", _SC_KERN_POINTERS}, +#endif +#ifdef _SC_KERN_SIM + {"SC_KERN_SIM", _SC_KERN_SIM}, +#endif +#ifdef _SC_LINE_MAX + {"SC_LINE_MAX", _SC_LINE_MAX}, +#endif +#ifdef _SC_LOGIN_NAME_MAX + {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX}, +#endif +#ifdef _SC_LOGNAME_MAX + {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX}, +#endif +#ifdef _SC_LONG_BIT + {"SC_LONG_BIT", _SC_LONG_BIT}, +#endif +#ifdef _SC_MAC + {"SC_MAC", _SC_MAC}, +#endif +#ifdef _SC_MAPPED_FILES + {"SC_MAPPED_FILES", _SC_MAPPED_FILES}, +#endif +#ifdef _SC_MAXPID + {"SC_MAXPID", _SC_MAXPID}, +#endif +#ifdef _SC_MB_LEN_MAX + {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX}, +#endif +#ifdef _SC_MEMLOCK + {"SC_MEMLOCK", _SC_MEMLOCK}, +#endif +#ifdef _SC_MEMLOCK_RANGE + {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE}, #endif #ifdef _SC_MEMORY_PROTECTION {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION},