Index: configure =================================================================== --- configure (revision 87540) +++ configure (working copy) @@ -5999,7 +5999,7 @@ sys/lock.h sys/mkdev.h sys/modem.h \ sys/param.h sys/poll.h sys/select.h sys/socket.h sys/statvfs.h sys/stat.h \ sys/termio.h sys/time.h \ -sys/times.h sys/types.h sys/un.h sys/utsname.h sys/wait.h pty.h libutil.h \ +sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h libutil.h \ sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \ bluetooth/bluetooth.h linux/tipc.h spawn.h util.h do : @@ -9240,19 +9240,20 @@ # checks for library functions for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ - clock confstr ctermid execv fchmod fchown fork fpathconf ftime ftruncate \ - gai_strerror getgroups getlogin getloadavg getpeername getpgid getpid \ + clock confstr ctermid execv fchmod fchown fexecve fork fpathconf ftime \ + ftruncate futimens futimes \ + gai_strerror getgroups gethostid getlogin getloadavg getpeername getpgid getpid \ getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \ - initgroups kill killpg lchmod lchown lstat mbrtowc mkfifo mknod mktime \ - mremap nice pathconf pause plock poll pthread_init \ - putenv readlink realpath \ + initgroups kill killpg lchmod lchown lockf lstat lutimes mbrtowc mkfifo mknod \ + mktime mremap nice pathconf pause plock poll posix_fallocate posix_fadvise pread \ + pthread_init putenv pwrite readlink readv realpath \ select sem_open sem_timedwait sem_getvalue sem_unlink setegid seteuid \ - setgid \ + setgid sethostid sethostname \ setlocale setregid setreuid setresuid setresgid setsid setpgid setpgrp setuid setvbuf \ - sigaction siginterrupt sigrelse snprintf strftime strlcpy \ + sigaction siginterrupt sigrelse snprintf strftime strlcpy sync \ sysconf tcgetpgrp tcsetpgrp tempnam timegm times tmpfile tmpnam tmpnam_r \ - truncate uname unsetenv utimes waitpid wait3 wait4 \ - wcscoll wcsftime wcsxfrm _getpty + truncate uname unsetenv utimes waitid waitpid wait3 wait4 \ + wcscoll wcsftime wcsxfrm writev _getpty do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" Index: configure.in =================================================================== --- configure.in (revision 87540) +++ configure.in (working copy) @@ -1283,7 +1283,7 @@ sys/lock.h sys/mkdev.h sys/modem.h \ sys/param.h sys/poll.h sys/select.h sys/socket.h sys/statvfs.h sys/stat.h \ sys/termio.h sys/time.h \ -sys/times.h sys/types.h sys/un.h sys/utsname.h sys/wait.h pty.h libutil.h \ +sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h libutil.h \ sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \ bluetooth/bluetooth.h linux/tipc.h spawn.h util.h) AC_HEADER_DIRENT @@ -2525,19 +2525,20 @@ # checks for library functions AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ - clock confstr ctermid execv fchmod fchown fork fpathconf ftime ftruncate \ - gai_strerror getgroups getlogin getloadavg getpeername getpgid getpid \ + clock confstr ctermid execv fchmod fchown fexecve fork fpathconf ftime \ + ftruncate futimens futimes \ + gai_strerror getgroups gethostid getlogin getloadavg getpeername getpgid getpid \ getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \ - initgroups kill killpg lchmod lchown lstat mbrtowc mkfifo mknod mktime \ - mremap nice pathconf pause plock poll pthread_init \ - putenv readlink realpath \ + initgroups kill killpg lchmod lchown lockf lstat lutimes mbrtowc mkfifo mknod \ + mktime mremap nice pathconf pause plock poll posix_fallocate posix_fadvise pread \ + pthread_init putenv pwrite readlink readv realpath \ select sem_open sem_timedwait sem_getvalue sem_unlink setegid seteuid \ - setgid \ + setgid sethostid sethostname \ setlocale setregid setreuid setresuid setresgid setsid setpgid setpgrp setuid setvbuf \ - sigaction siginterrupt sigrelse snprintf strftime strlcpy \ + sigaction siginterrupt sigrelse snprintf strftime strlcpy sync \ sysconf tcgetpgrp tcsetpgrp tempnam timegm times tmpfile tmpnam tmpnam_r \ - truncate uname unsetenv utimes waitpid wait3 wait4 \ - wcscoll wcsftime wcsxfrm _getpty) + truncate uname unsetenv utimes waitid waitpid wait3 wait4 \ + wcscoll wcsftime wcsxfrm writev _getpty) # For some functions, having a definition is not sufficient, since # we want to take their address. Index: Misc/NEWS =================================================================== --- Misc/NEWS (revision 87540) +++ Misc/NEWS (working copy) @@ -2,6 +2,9 @@ Python News +++++++++++ +- Issue #XXXXX: Add some missing functions to the posix module. Patch by + Ross Lagerwall. + What's New in Python 3.2 Release Candidate 1 ============================================ Index: Doc/library/os.rst =================================================================== --- Doc/library/os.rst (revision 87540) +++ Doc/library/os.rst (working copy) @@ -637,6 +637,17 @@ This function is not available on MacOS. +.. function:: fexecve(fd, args, env) + + Execute the program specified by a file descriptor *fd* with arguments given + by *args* and environment given by *env*, replacing the current process. + *args* and *env* are given as in :func:`execve`. + + Availability: Unix. + + .. versionadded:: 3.3 + + .. function:: fpathconf(fd, name) Return system configuration information relevant to an open file. *name* @@ -690,6 +701,45 @@ Availability: Unix. +.. function:: futimens(fd, (atime_sec, atime_nsec), (mtime_sec, mtime_nsec)) + futimens(fd, None, None) + + Updates the timestamps of a file specified by the file descriptor *fd*, with + nanosecond precision. + The second form sets *atime* and *mtime* to the current time. + If *atime_nsec* or *mtime_nsec* is specified as :data:`UTIME_NOW`, the corresponding + timestamp is updated to the current time. + If *atime_nsec* or *mtime_nsec* is specified as :data:`UTIME_OMIT`, the corresponding + timestamp is not updated. + + Availability: Unix. + + .. versionadded:: 3.3 + + +.. data:: UTIME_NOW + UTIME_OMIT + + Flags used with :func:`futimens` to specify that the timestamp must be + updated either to the current time or not updated at all. + + Availability: Unix. + + .. versionadded:: 3.3 + + +.. function:: futimes(fd, (atime, mtime)) + futimes(fd, None) + + Set the access and modified time of the file specified by the file + descriptor *fd* to the given values. If the second form is used, set the + access and modified times to the current time. + + Availability: Unix. + + .. versionadded:: 3.3 + + .. function:: isatty(fd) Return ``True`` if the file descriptor *fd* is open and connected to a @@ -698,6 +748,30 @@ Availability: Unix. +.. function:: lockf(fd, cmd, len) + + Apply, test or remove a POSIX lock on an open file descriptor. + *fd* is an open file descriptor. + *cmd* specifies the command to use - one of :data:`F_LOCK`, :data:`F_TLOCK`, + :data:`F_ULOCK` or :data:`F_TEST`. + *len* specifies the section of the file to lock. + + Availability: Unix. + + .. versionadded:: 3.3 + + +.. data:: F_LOCK + F_TLOCK + F_ULOCK + F_TEST + + Flags that specify what action :func:`lockf` will take. + + Availability: Unix. + + .. versionadded:: 3.3 + .. function:: lseek(fd, pos, how) Set the current position of file descriptor *fd* to position *pos*, modified @@ -758,6 +832,66 @@ Availability: Unix, Windows. +.. function:: posix_fallocate(fd, offset, len) + + Ensures that enough disk space is allocated for the file specified by *fd* + starting from *offset* and continuing for *len* bytes. + + Availability: Unix. + + .. versionadded:: 3.3 + + +.. function:: posix_fadvise(fd, offset, len, advice) + + Announces an intention to access data in a specific pattern thus allowing + the kernel to make optimizations. + The advice applies to the region of the file specified by *fd* starting at + *offset* and continuing for *len* bytes. + *advice* is one of :data:`POSIX_FADV_NORMAL`, :data:`POSIX_FADV_SEQUENTIAL`, + :data:`POSIX_FADV_RANDOM`, :data:`POSIX_FADV_NOREUSE`, + :data:`POSIX_FADV_WILLNEED` or :data:`POSIX_FADV_DONTNEED`. + + Availability: Unix. + + .. versionadded:: 3.3 + + +.. data:: POSIX_FADV_NORMAL + POSIX_FADV_SEQUENTIAL + POSIX_FADV_RANDOM + POSIX_FADV_NOREUSE + POSIX_FADV_WILLNEED + POSIX_FADV_DONTNEED + + Flags that can be used in *advice* in :func:`posix_fadvise` that specify + the access pattern that is likely to be used. + + Availability: Unix. + + .. versionadded:: 3.3 + + +.. function:: pread(fd, buffersize, offset) + + Read from a file descriptor, *fd*, at a position of *offset*. It will read up + to *buffersize* number of bytes. The file offset remains unchanged. + + Availability: Unix. + + .. versionadded:: 3.3 + + +.. function:: pwrite(fd, string, offset) + + Write *string* to a file descriptor, *fd*, from *offset*, leaving the file + offset unchanged. + + Availability: Unix. + + .. versionadded:: 3.3 + + .. function:: read(fd, n) Read at most *n* bytes from file descriptor *fd*. Return a bytestring containing the @@ -775,6 +909,18 @@ :meth:`~file.readline` methods. +.. function:: readv(fd, (size1, size2, ...)) + + Read from a file descriptor into multiple strings, specified by a tuple + of sizes, returning a tuple of bytestrings. It may read fewer bytes than + the sum of the sizes and may return fewer bytestrings than the number of + sizes given. + + Availability: Unix. + + .. versionadded:: 3.3 + + .. function:: tcgetpgrp(fd) Return the process group associated with the terminal given by *fd* (an open @@ -816,6 +962,16 @@ :meth:`~file.write` method. +.. function:: writev(fd, (bytes1, bytes2, ...)) + + Write the bytestring in *bytes1*, *bytes2*, etc, to file descriptor *fd*. + Returns the total number of bytes written. + + Availability: Unix. + + .. versionadded:: 3.3 + + .. _open-constants: ``open()`` flag constants @@ -1087,6 +1243,17 @@ Added support for Windows 6.0 (Vista) symbolic links. +.. function:: lutimes(path, (atime, mtime)) + lutimes(path, None) + + Like :func:`utime`, but if *path* is a symbolic link, it is not + dereferenced. + + Availability: Unix. + + .. versionadded:: 3.3 + + .. function:: mkfifo(path[, mode]) Create a FIFO (a named pipe) named *path* with numeric mode *mode*. The @@ -1408,6 +1575,25 @@ Added support for Windows 6.0 (Vista) symbolic links. +.. function:: sync() + + Force write of everything to disk. + + Availability: Unix. + + .. versionadded:: 3.3 + + +.. function:: truncate(path, length) + + Truncate the file corresponding to *path*, so that it is at most + *length* bytes in size. + + Availability: Unix. + + .. versionadded:: 3.3 + + .. function:: unlink(path) Remove (delete) the file *path*. This is the same function as @@ -1987,7 +2173,43 @@ Availability: Unix. +.. function:: waitid(idtype, id, options) + Wait for the completion of one or more child processes. + *idtype* can be :data:`P_PID`, :data:`P_PGID` or :data:`P_ALL`. + *id* specifies the pid to wait on. + *options* is constructed from the ORing of one or more of :data:`WEXITED`, + :data:`WSTOPPED` or :data:`WCONTINUED` and additionally may be ORed with + :data:`WNOHANG` or :data:`WNOWAIT`. The result is a tuple containing the + same data as *siginfo_t* in the POSIX specification. + + Availability: Unix. + + .. versionadded:: 3.3 + +.. data:: P_PID + P_PGID + P_ALL + + These are the possible values for *idtype* in :func:`waitid`. They affect + how *id* is interpreted. + + Availability: Unix. + + .. versionadded:: 3.3 + +.. data:: WEXITED + WSTOPPED + WNOWAIT + + Flags that can be used in *options* in :func:`waitid` that specify what + child signal to wait for. + + Availability: Unix. + + .. versionadded:: 3.3 + + .. function:: waitpid(pid, options) The details of this function differ on Unix and Windows. @@ -2164,6 +2386,15 @@ Availability: Unix. +.. function:: gethostid() + + Returns the host id, a unique 32-bit identifier for the current machine. + + Availability: Unix. + + .. versionadded:: 3.3 + + .. function:: getloadavg() Return the number of processes in the system run queue averaged over the last @@ -2173,6 +2404,15 @@ Availability: Unix. +.. function:: sethostname(name) + + Sets the machine's hostname to *name*. + + Availability: Unix. + + .. versionadded:: 3.3 + + .. function:: sysconf(name) Return integer-valued system configuration values. If the configuration value Index: Lib/test/test_posix.py =================================================================== --- Lib/test/test_posix.py (revision 87540) +++ Lib/test/test_posix.py (working copy) @@ -132,6 +132,176 @@ finally: fp.close() + @unittest.skipUnless(hasattr(posix, 'truncate'), "test needs posix.truncate()") + def test_truncate(self): + fp = open(support.TESTFN, 'w+') + try: + # we need to have some data to truncate + fp.write('test') + fp.flush() + posix.truncate(support.TESTFN, 0) + finally: + fp.close() + + @unittest.skipUnless(hasattr(posix, 'sync'), "test needs posix.sync()") + def test_sync(self): + posix.sync() + + @unittest.skipUnless(hasattr(posix, 'fexecve'), "test needs posix.fexecve()") + @unittest.skipUnless(hasattr(os, 'fork'), "test needs os.fork()") + @unittest.skipUnless(hasattr(os, 'chdir'), "test needs os.chdir()") + @unittest.skipUnless(hasattr(os, 'waitpid'), "test needs os.waitpid()") + def test_fexecve(self): + fp = os.open(sys.executable, os.O_RDONLY) + try: + pid = os.fork() + if pid == 0: + os.chdir(os.path.split(sys.executable)[0]) + posix.fexecve(fp, [sys.executable, '-c', 'pass'], os.environ) + else: + os.waitpid(pid, 0) + finally: + os.close(fp) + + @unittest.skipUnless(hasattr(posix, 'gethostid'), "test needs posix.gethostid()") + def test_gethostid(self): + self.assertTrue(isinstance(posix.gethostid(), int)) + + @unittest.skipUnless(hasattr(posix, 'sethostname'), "test needs posix.sethostname()") + def test_sethostname(self): + import socket + oldhn = socket.gethostname() + try: + posix.sethostname('new') + except OSError as inst: + # requires root permission + self.assertEqual(inst.errno, 1) + else: + # running test as root! + self.assertEqual(socket.gethostname(), 'new') + posix.sethostname(oldhn) + + @unittest.skipUnless(hasattr(posix, 'waitid'), "test needs posix.waitid()") + @unittest.skipUnless(hasattr(os, 'chdir'), "test needs os.chdir()") + @unittest.skipUnless(hasattr(os, 'fork'), "test needs os.fork()") + def test_waitid(self): + pid = os.fork() + if pid == 0: + os.chdir(os.path.split(sys.executable)[0]) + posix.execve(sys.executable, [sys.executable, '-c', 'pass'], os.environ) + else: + res = posix.waitid(posix.P_PID, pid, posix.WEXITED) + self.assertEqual(pid, res[3]) + + @unittest.skipUnless(hasattr(posix, 'lockf'), "test needs posix.lockf()") + def test_lockf(self): + fd = os.open(support.TESTFN, os.O_WRONLY | os.O_CREAT) + try: + os.write(fd, b'test') + os.lseek(fd, 0, os.SEEK_SET) + posix.lockf(fd, posix.F_LOCK, 4) + # section is locked + posix.lockf(fd, posix.F_ULOCK, 4) + finally: + os.close(fd) + + @unittest.skipUnless(hasattr(posix, 'pread'), "test needs posix.pread()") + def test_pread(self): + fd = os.open(support.TESTFN, os.O_RDWR | os.O_CREAT) + try: + os.write(fd, b'test') + os.lseek(fd, 0, os.SEEK_SET) + self.assertEqual(b'es', posix.pread(fd, 2, 1)) + # the first pread() shoudn't disturb the file offset + self.assertEqual(b'te', posix.read(fd, 2)) + finally: + os.close(fd) + + @unittest.skipUnless(hasattr(posix, 'pwrite'), "test needs posix.pwrite()") + def test_pwrite(self): + fd = os.open(support.TESTFN, os.O_RDWR | os.O_CREAT) + try: + os.write(fd, b'test') + os.lseek(fd, 0, os.SEEK_SET) + posix.pwrite(fd, b'xx', 1) + self.assertEqual(b'txxt', posix.read(fd, 4)) + finally: + os.close(fd) + + @unittest.skipUnless(hasattr(posix, 'posix_fallocate'), + "test needs posix.posix_fallocate()") + def test_posix_fallocate(self): + fd = os.open(support.TESTFN, os.O_WRONLY | os.O_CREAT) + try: + posix.posix_fallocate(fd, 0, 10) + finally: + os.close(fd) + + @unittest.skipUnless(hasattr(posix, 'posix_fadvise'), + "test needs posix.posix_fadvise()") + def test_posix_fadvise(self): + fd = os.open(support.TESTFN, os.O_RDONLY) + try: + posix.posix_fadvise(fd, 0, 0, posix.POSIX_FADV_WILLNEED) + finally: + os.close(fd) + + @unittest.skipUnless(hasattr(posix, 'futimes'), "test needs posix.futimes()") + def test_futimes(self): + now = time.time() + fd = os.open(support.TESTFN, os.O_RDONLY) + try: + posix.futimes(fd, None) + self.assertRaises(TypeError, posix.futimes, fd, (None, None)) + self.assertRaises(TypeError, posix.futimes, fd, (now, None)) + self.assertRaises(TypeError, posix.futimes, fd, (None, now)) + posix.futimes(fd, (int(now), int(now))) + posix.futimes(fd, (now, now)) + finally: + os.close(fd) + + def test_lutimes(self): + now = time.time() + posix.lutimes(support.TESTFN, None) + self.assertRaises(TypeError, posix.lutimes, support.TESTFN, (None, None)) + self.assertRaises(TypeError, posix.lutimes, support.TESTFN, (now, None)) + self.assertRaises(TypeError, posix.lutimes, support.TESTFN, (None, now)) + posix.lutimes(support.TESTFN, (int(now), int(now))) + posix.lutimes(support.TESTFN, (now, now)) + + @unittest.skipUnless(hasattr(posix, 'futimens'), "test needs posix.futimens()") + def test_futimens(self): + now = time.time() + fd = os.open(support.TESTFN, os.O_RDONLY) + try: + self.assertRaises(TypeError, posix.futimens, fd, (None, None), (None, None)) + self.assertRaises(TypeError, posix.futimens, fd, (now, 0), None) + self.assertRaises(TypeError, posix.futimens, fd, None, (now, 0)) + posix.futimens(fd, (int(now), int((now - int(now)) * 1e9)), + (int(now), int((now - int(now)) * 1e9))) + finally: + os.close(fd) + + @unittest.skipUnless(hasattr(posix, 'writev'), "test needs posix.writev()") + def test_writev(self): + fd = os.open(support.TESTFN, os.O_RDWR | os.O_CREAT) + try: + os.writev(fd, (b'test1', b'tt2', b't3')) + os.lseek(fd, 0, os.SEEK_SET) + self.assertEqual(b'test1tt2t3', posix.read(fd, 10)) + finally: + os.close(fd) + + @unittest.skipUnless(hasattr(posix, 'readv'), "test needs posix.readv()") + def test_readv(self): + fd = os.open(support.TESTFN, os.O_RDWR | os.O_CREAT) + try: + os.write(fd, b'test1tt2t3') + os.lseek(fd, 0, os.SEEK_SET) + self.assertEqual((b'test1', b'tt2', b't3'), posix.readv(fd, (5, 3, 2))) + finally: + os.close(fd) + def test_dup(self): if hasattr(posix, 'dup'): fp = open(support.TESTFN) Index: Modules/posixmodule.c =================================================================== --- Modules/posixmodule.c (revision 87540) +++ Modules/posixmodule.c (working copy) @@ -59,6 +59,10 @@ #include "osdefs.h" #endif +#ifdef HAVE_SYS_UIO_H +#include +#endif + #ifdef HAVE_SYS_TYPES_H #include #endif /* HAVE_SYS_TYPES_H */ @@ -2074,6 +2078,21 @@ } #endif /* HAVE_FSYNC */ +#ifdef HAVE_SYNC +PyDoc_STRVAR(posix_sync__doc__, +"sync()\n\n\ +Force write of everything to disk."); + +static PyObject * +posix_sync(PyObject *self, PyObject *noargs) +{ + Py_BEGIN_ALLOW_THREADS + sync(); + Py_END_ALLOW_THREADS + Py_RETURN_NONE; +} +#endif + #ifdef HAVE_FDATASYNC #ifdef __hpux @@ -3333,7 +3352,164 @@ #endif /* MS_WINDOWS */ } +#ifdef HAVE_FUTIMES +PyDoc_STRVAR(posix_futimes__doc__, +"futimes(fd, (atime, mtime))\n\ +futimes(fd, None)\n\n\ +Set the access and modified time of the file specified by the file\n\ +descriptor fd to the given values. If the second form is used, set the\n\ +access and modified times to the current time."); +static PyObject * +posix_futimes(PyObject *self, PyObject *args) +{ + int res, fd; + PyObject* arg; + + struct timeval buf[2]; + + if (!PyArg_ParseTuple(args, "iO:futimes", &fd, &arg)) + return NULL; + + if (arg == Py_None) { + /* optional time values not given */ + Py_BEGIN_ALLOW_THREADS + res = futimes(fd, NULL); + Py_END_ALLOW_THREADS + } + else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) { + PyErr_SetString(PyExc_TypeError, + "futimes() arg 2 must be a tuple (atime, mtime)"); + return NULL; + } + else { + if (extract_time(PyTuple_GET_ITEM(arg, 0), + &(buf[0].tv_sec), &(buf[0].tv_usec)) == -1) { + return NULL; + } + if (extract_time(PyTuple_GET_ITEM(arg, 1), + &(buf[1].tv_sec), &(buf[1].tv_usec)) == -1) { + return NULL; + } + Py_BEGIN_ALLOW_THREADS + res = futimes(fd, buf); + Py_END_ALLOW_THREADS + } + if (res < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif + +#ifdef HAVE_LUTIMES +PyDoc_STRVAR(posix_lutimes__doc__, +"lutimes(path, (atime, mtime))\n\ +lutimes(path, None)\n\n\ +Like utime(), but if path is a symbolic link, it is not dereferenced."); + +static PyObject * +posix_lutimes(PyObject *self, PyObject *args) +{ + PyObject *opath, *arg; + char *path; + int res; + struct timeval buf[2]; + + if (!PyArg_ParseTuple(args, "O&O:lutimes", + PyUnicode_FSConverter, &opath, &arg)) + return NULL; + path = PyBytes_AsString(opath); + if (arg == Py_None) { + /* optional time values not given */ + Py_BEGIN_ALLOW_THREADS + res = lutimes(path, NULL); + Py_END_ALLOW_THREADS + } + else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) { + PyErr_SetString(PyExc_TypeError, + "lutimes() arg 2 must be a tuple (atime, mtime)"); + Py_DECREF(opath); + return NULL; + } + else { + if (extract_time(PyTuple_GET_ITEM(arg, 0), + &(buf[0].tv_sec), &(buf[0].tv_usec)) == -1) { + Py_DECREF(opath); + return NULL; + } + if (extract_time(PyTuple_GET_ITEM(arg, 1), + &(buf[1].tv_sec), &(buf[1].tv_usec)) == -1) { + Py_DECREF(opath); + return NULL; + } + Py_BEGIN_ALLOW_THREADS + res = lutimes(path, buf); + Py_END_ALLOW_THREADS + } + Py_DECREF(opath); + if (res < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif + +#ifdef HAVE_FUTIMENS +PyDoc_STRVAR(posix_futimens__doc__, +"futimens(fd, (atime_sec, atime_nsec), (mtime_sec, mtime_nsec))\n\ +futimens(fd, None, None)\n\n\ +Updates the timestamps of a file specified by the file descriptor fd, with\n\ +nanosecond precision.\n\ +The second form sets atime and mtime to the current time.\n\ +If *_nsec is specified as UTIME_NOW, the timestamp is updated to the\n\ +current time.\n\ +If *_nsec is specified as UTIME_OMIT, the timestamp is not updated."); + +static PyObject * +posix_futimens(PyObject *self, PyObject *args) +{ + int res, fd; + PyObject *atime, *mtime; + + struct timespec buf[2]; + + if (!PyArg_ParseTuple(args, "iOO:futimens", + &fd, &atime, &mtime)) + return NULL; + if (atime == Py_None && mtime == Py_None) { + /* optional time values not given */ + Py_BEGIN_ALLOW_THREADS + res = futimens(fd, NULL); + Py_END_ALLOW_THREADS + } + else if (!PyTuple_Check(atime) || PyTuple_Size(atime) != 2) { + PyErr_SetString(PyExc_TypeError, + "futimens() arg 2 must be a tuple (atime_sec, atime_nsec)"); + return NULL; + } + else if (!PyTuple_Check(mtime) || PyTuple_Size(mtime) != 2) { + PyErr_SetString(PyExc_TypeError, + "futimens() arg 3 must be a tuple (mtime_sec, mtime_nsec)"); + return NULL; + } + else { + if (!PyArg_ParseTuple(atime, "ll:futimens", + &(buf[0].tv_sec), &(buf[0].tv_nsec))) { + return NULL; + } + if (!PyArg_ParseTuple(mtime, "ll:futimens", + &(buf[1].tv_sec), &(buf[1].tv_nsec))) { + return NULL; + } + Py_BEGIN_ALLOW_THREADS + res = futimens(fd, buf); + Py_END_ALLOW_THREADS + } + if (res < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif + /* Process operations */ PyDoc_STRVAR(posix__exit__doc__, @@ -3616,7 +3792,88 @@ } #endif /* HAVE_EXECV */ +#ifdef HAVE_FEXECVE +PyDoc_STRVAR(posix_fexecve__doc__, +"fexecve(fd, args, env)\n\n\ +Execute the program specified by a file descriptor with arguments and\n\ +environment, replacing the current process.\n\ +\n\ + fd: file descriptor of executable\n\ + args: tuple or list of arguments\n\ + env: dictionary of strings mapping to strings"); +static PyObject * +posix_fexecve(PyObject *self, PyObject *args) +{ + int fd; + PyObject *argv, *env; + char **argvlist; + char **envlist; + Py_ssize_t i, argc, envc; + PyObject *(*getitem)(PyObject *, Py_ssize_t); + Py_ssize_t lastarg = 0; + + /* fexecve has three arguments: (fd, argv, env), where + argv is a list or tuple of strings and env is a dictionary + like posix.environ. */ + + if (!PyArg_ParseTuple(args, "iOO:fexecve", + &fd, &argv, &env)) + return NULL; + if (PyList_Check(argv)) { + argc = PyList_Size(argv); + getitem = PyList_GetItem; + } + else if (PyTuple_Check(argv)) { + argc = PyTuple_Size(argv); + getitem = PyTuple_GetItem; + } + else { + PyErr_SetString(PyExc_TypeError, + "fexecve() arg 2 must be a tuple or list"); + return NULL; + } + if (!PyMapping_Check(env)) { + PyErr_SetString(PyExc_TypeError, + "fexecve() arg 3 must be a mapping object"); + return NULL; + } + + argvlist = PyMem_NEW(char *, argc+1); + if (argvlist == NULL) { + PyErr_NoMemory(); + return NULL; + } + for (i = 0; i < argc; i++) { + if (!fsconvert_strdup((*getitem)(argv, i), + &argvlist[i])) + { + lastarg = i; + goto fail_1; + } + } + lastarg = argc; + argvlist[argc] = NULL; + + envlist = parse_envlist(env, &envc); + if (envlist == NULL) + goto fail_1; + + fexecve(fd, argvlist, envlist); + + /* If we get here it's definitely an error */ + + (void) posix_error(); + + while (--envc >= 0) + PyMem_DEL(envlist[envc]); + PyMem_DEL(envlist); + fail_1: + free_string_array(argvlist, lastarg); + return NULL; +} +#endif /* HAVE_FEXECVE */ + #ifdef HAVE_SPAWNV PyDoc_STRVAR(posix_spawnv__doc__, "spawnv(mode, path, args)\n\n\ @@ -4182,6 +4439,41 @@ } #endif +#ifdef HAVE_GETHOSTID +PyDoc_STRVAR(posix_gethostid__doc__, +"gethostid() -> hostid\n\n\ +Gets the host id, a unique 32-bit identifier for the current machine."); + +static PyObject * +posix_gethostid(PyObject *self, PyObject *noargs) +{ + return PyLong_FromLong(gethostid()); +} +#endif + +#ifdef HAVE_SETHOSTNAME +PyDoc_STRVAR(posix_sethostname__doc__, +"sethostname(name)\n\n\ +Sets the hostname to name."); + +static PyObject * +posix_sethostname(PyObject *self, PyObject *args) +{ + int res; + char *hostname; + + if (!PyArg_ParseTuple(args, "s:sethostname", &hostname)) + return NULL; + + res = sethostname(hostname, strlen(hostname)); + + if (res == -1) + return posix_error(); + + Py_RETURN_NONE; +} +#endif + #ifdef HAVE_GETEGID PyDoc_STRVAR(posix_getegid__doc__, "getegid() -> egid\n\n\ @@ -4972,6 +5264,38 @@ } #endif /* HAVE_WAIT4 */ +#ifdef HAVE_WAITID +PyDoc_STRVAR(posix_waitid__doc__, +"waitid(idtype, id, options) -> siginfo\n\n\ +Wait for the completion of one or more child processes.\n\n\ +idtype can be P_PID, P_PGID or P_ALL.\n\ +id specifies the pid to wait on.\ +options is constructed from the ORing of one or more of WEXITED, WSTOPPED\n\ +or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.\n\ +siginfo is a tuple containing the same data as siginfo_t in the POSIX\n\ +specification."); + +static PyObject * +posix_waitid(PyObject *self, PyObject *args) +{ + idtype_t idtype; + id_t id; + int options, res; + siginfo_t si; + if (!PyArg_ParseTuple(args, "lli:waitid", &idtype, &id, &options)) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = waitid(idtype, id, &si, options); + Py_END_ALLOW_THREADS + if (res == -1) + return posix_error(); + + return Py_BuildValue("iiililill", si.si_signo, si.si_code, + si.si_errno, si.si_pid, si.si_uid, si.si_addr, si.si_status, + si.si_band, si.si_value); +} +#endif + #ifdef HAVE_WAITPID PyDoc_STRVAR(posix_waitpid__doc__, "waitpid(pid, options) -> (pid, status)\n\n\ @@ -5587,7 +5911,46 @@ return Py_None; } +#ifdef HAVE_LOCKF +PyDoc_STRVAR(posix_lockf__doc__, +"lockf(fd, cmd, len)\n\n\ +Apply, test or remove a POSIX lock on an open file descriptor.\n\n\ +fd is an open file descriptor.\n\ +cmd specifies the command to use - one of F_LOCK, F_TLOCK, F_ULOCK or\n\ +F_TEST.\n\ +len specifies the section of the file to lock."); +static PyObject * +posix_lockf(PyObject *self, PyObject *args) +{ + int fd, cmd, res; + off_t len; + PyObject *lenobj; + if (!PyArg_ParseTuple(args, "iiO:lockf", + &fd, &cmd, &lenobj)) + return NULL; + +#if !defined(HAVE_LARGEFILE_SUPPORT) + len = PyLong_AsLong(lenobj); +#else + len = PyLong_Check(lenobj) ? + PyLong_AsLongLong(lenobj) : PyLong_AsLong(lenobj); +#endif + if (PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + res = lockf(fd, cmd, len); + Py_END_ALLOW_THREADS + + if (res < 0) + return posix_error(); + + Py_RETURN_NONE; +} +#endif + + PyDoc_STRVAR(posix_lseek__doc__, "lseek(fd, pos, how) -> newpos\n\n\ Set the current position of a file descriptor."); @@ -5677,7 +6040,135 @@ return buffer; } +#ifdef HAVE_READV +PyDoc_STRVAR(posix_readv__doc__, +"readv(fd, (size1, size2, ...)) -> strings\n\n\ +Read from a file descriptor into multiple strings, specified by a tuple\n\ +of sizes."); +static PyObject * +posix_readv(PyObject *self, PyObject *args) +{ + int fd, cnt, i, j, n; + PyObject *sizetuple; + PyObject *res; + Py_ssize_t rem; + struct iovec *iov; + + if (!PyArg_ParseTuple(args, "iO:readv", &fd, &sizetuple)) + return NULL; + if (!PyTuple_Check(sizetuple)) { + PyErr_SetString(PyExc_TypeError, + "readv() arg 2 must be a tuple"); + return NULL; + } + cnt = PyTuple_Size(sizetuple); + + res = PyTuple_New(cnt); + if (res == NULL) + return PyErr_NoMemory(); + + iov = PyMem_New(struct iovec, cnt); + if (iov == NULL) { + Py_DECREF(res); + return PyErr_NoMemory(); + } + + for (i = 0; i < cnt; i++) { + Py_ssize_t size = PyLong_AsSsize_t(PyTuple_GetItem(sizetuple, i)); + if (size == -1) { + for (j = 0; j < i ;j++) + PyMem_Free(iov[j].iov_base); + PyMem_Del(iov); + Py_DECREF(res); + return NULL; + } + iov[i].iov_base = PyMem_Malloc(size); + iov[i].iov_len = size; + } + + Py_BEGIN_ALLOW_THREADS + n = readv(fd, iov, cnt); + Py_END_ALLOW_THREADS + + rem = n; + for (i = 0; i < cnt && rem > 0; i++) { + PyObject *o; + if (rem < iov[i].iov_len) + o = PyBytes_FromStringAndSize(iov[i].iov_base, rem); + else + o = PyBytes_FromStringAndSize(iov[i].iov_base, iov[i].iov_len); + if (o == NULL) { + for (j = 0; j < i ;j++) + Py_DECREF(PyTuple_GetItem(res, j)); + Py_DECREF(res); + for (; j < cnt; j++) + PyMem_Free(iov[j].iov_base); + PyMem_Del(iov); + return NULL; + } + PyMem_Free(iov[i].iov_base); + PyTuple_SET_ITEM(res, i, o); + rem -= iov[i].iov_len; + } + _PyTuple_Resize(&res, i); + for (; i < cnt; i++) { + PyMem_Free(iov[i].iov_base); + } + PyMem_Del(iov); + return res; +} +#endif + +#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, *offobj; + if (!PyArg_ParseTuple(args, "iiO:pread", &fd, &size, &offobj)) + return NULL; + +#if !defined(HAVE_LARGEFILE_SUPPORT) + offset = PyLong_AsLong(offobj); +#else + offset = PyLong_Check(offobj) ? + PyLong_AsLongLong(offobj) : PyLong_AsLong(offobj); +#endif + if (PyErr_Occurred()) + 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 + PyDoc_STRVAR(posix_write__doc__, "write(fd, string) -> byteswritten\n\n\ Write a string to a file descriptor."); @@ -5704,7 +6195,107 @@ return PyLong_FromSsize_t(size); } +#ifdef HAVE_WRITEV +PyDoc_STRVAR(posix_writev__doc__, +"writev(fd, (bytes1, bytes2, ...)) -> byteswritten\n\n\ +Write to a file descriptor, from bytes1, bytes2, etc.\n\ +Returns the total bytes written."); +static PyObject * +posix_writev(PyObject *self, PyObject *args) +{ + int fd, cnt, i, j; + Py_ssize_t res; + PyObject *sizetuple; + struct iovec *iov; + Py_buffer *buf; + if (!PyArg_ParseTuple(args, "iO:writev", &fd, &sizetuple)) + return NULL; + if (!PyTuple_Check(sizetuple)) { + PyErr_SetString(PyExc_TypeError, + "writev() arg 2 must be a tuple"); + return NULL; + } + cnt = PyTuple_Size(sizetuple); + + iov = PyMem_New(struct iovec, cnt); + if (iov == NULL) + return PyErr_NoMemory(); + buf = PyMem_New(Py_buffer, cnt); + if (buf == NULL) { + PyMem_Del(iov); + return PyErr_NoMemory(); + } + + for (i = 0; i < cnt; i++) { + if (PyObject_GetBuffer(PyTuple_GetItem(sizetuple, i), &buf[i], + PyBUF_SIMPLE) == -1) { + PyMem_Del(iov); + for (j = 0; j < i; j++) { + PyBuffer_Release(&buf[j]); + } + PyMem_Del(buf); + return NULL; + } + iov[i].iov_base = buf[i].buf; + iov[i].iov_len = buf[i].len; + } + + Py_BEGIN_ALLOW_THREADS + res = writev(fd, iov, cnt); + Py_END_ALLOW_THREADS + + PyMem_Del(iov); + for (j = 0; j < cnt; j++) { + PyBuffer_Release(&buf[j]); + } + PyMem_Del(buf); + + return PyLong_FromSsize_t(res); +} +#endif + +#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; + PyObject *offobj; + + if (!PyArg_ParseTuple(args, "iy*O:pwrite", &fd, &pbuf, &offobj)) + return NULL; + +#if !defined(HAVE_LARGEFILE_SUPPORT) + offset = PyLong_AsLong(offobj); +#else + offset = PyLong_Check(offobj) ? + PyLong_AsLongLong(offobj) : PyLong_AsLong(offobj); +#endif + if (PyErr_Occurred()) + 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 + PyDoc_STRVAR(posix_fstat__doc__, "fstat(fd) -> stat result\n\n\ Like stat(), but for an open file descriptor."); @@ -5939,6 +6530,118 @@ } #endif +#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; + char *path; + off_t length; + int res; + PyObject *lenobj; + + if (!PyArg_ParseTuple(args, "O&O:truncate", + PyUnicode_FSConverter, &opath, &lenobj)) + return NULL; + path = PyBytes_AsString(opath); + +#if !defined(HAVE_LARGEFILE_SUPPORT) + length = PyLong_AsLong(lenobj); +#else + length = PyLong_Check(lenobj) ? + PyLong_AsLongLong(lenobj) : PyLong_AsLong(lenobj); +#endif + if (PyErr_Occurred()) { + Py_DECREF(opath); + return NULL; + } + + 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 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; + PyObject *lenobj, *offobj; + + if (!PyArg_ParseTuple(args, "iOO:posix_fallocate", + &fd, &offobj, &lenobj)) + return NULL; + +#if !defined(HAVE_LARGEFILE_SUPPORT) + offset = PyLong_AsLong(offobj); + len = PyLong_AsLong(lenobj); +#else + offset = PyLong_Check(offobj) ? + PyLong_AsLongLong(offobj) : PyLong_AsLong(offobj); + len = PyLong_Check(lenobj) ? + PyLong_AsLongLong(lenobj) : PyLong_AsLong(lenobj); +#endif + if (PyErr_Occurred()) + 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 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, "illi:posix_fadvise", + &fd, &offset, &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 HAVE_PUTENV PyDoc_STRVAR(posix_putenv__doc__, "putenv(key, value)\n\n\ @@ -7819,6 +8522,15 @@ {"unlink", posix_unlink, METH_VARARGS, posix_unlink__doc__}, {"remove", posix_unlink, METH_VARARGS, posix_remove__doc__}, {"utime", posix_utime, METH_VARARGS, posix_utime__doc__}, +#ifdef HAVE_FUTIMES + {"futimes", posix_futimes, METH_VARARGS, posix_futimes__doc__}, +#endif +#ifdef HAVE_LUTIMES + {"lutimes", posix_lutimes, METH_VARARGS, posix_lutimes__doc__}, +#endif +#ifdef HAVE_FUTIMENS + {"futimens", posix_futimens, METH_VARARGS, posix_futimens__doc__}, +#endif #ifdef HAVE_TIMES {"times", posix_times, METH_NOARGS, posix_times__doc__}, #endif /* HAVE_TIMES */ @@ -7827,6 +8539,9 @@ {"execv", posix_execv, METH_VARARGS, posix_execv__doc__}, {"execve", posix_execve, METH_VARARGS, posix_execve__doc__}, #endif /* HAVE_EXECV */ +#ifdef HAVE_FEXECVE + {"fexecve", posix_fexecve, METH_VARARGS, posix_fexecve__doc__}, +#endif #ifdef HAVE_SPAWNV {"spawnv", posix_spawnv, METH_VARARGS, posix_spawnv__doc__}, {"spawnve", posix_spawnve, METH_VARARGS, posix_spawnve__doc__}, @@ -7847,6 +8562,12 @@ #ifdef HAVE_FORKPTY {"forkpty", posix_forkpty, METH_NOARGS, posix_forkpty__doc__}, #endif /* HAVE_FORKPTY */ +#ifdef HAVE_GETHOSTID + {"gethostid", posix_gethostid, METH_NOARGS, posix_gethostid__doc__}, +#endif +#ifdef HAVE_SETHOSTNAME + {"sethostname", posix_sethostname, METH_VARARGS, posix_sethostname__doc__}, +#endif #ifdef HAVE_GETEGID {"getegid", posix_getegid, METH_NOARGS, posix_getegid__doc__}, #endif /* HAVE_GETEGID */ @@ -7925,6 +8646,9 @@ #ifdef HAVE_WAIT4 {"wait4", posix_wait4, METH_VARARGS, posix_wait4__doc__}, #endif /* HAVE_WAIT4 */ +#ifdef HAVE_WAITID + {"waitid", posix_waitid, METH_VARARGS, posix_waitid__doc__}, +#endif #if defined(HAVE_WAITPID) || defined(HAVE_CWAIT) {"waitpid", posix_waitpid, METH_VARARGS, posix_waitpid__doc__}, #endif /* HAVE_WAITPID */ @@ -7949,9 +8673,24 @@ {"device_encoding", device_encoding, METH_VARARGS, device_encoding__doc__}, {"dup", posix_dup, METH_VARARGS, posix_dup__doc__}, {"dup2", posix_dup2, METH_VARARGS, posix_dup2__doc__}, +#ifdef HAVE_LOCKF + {"lockf", posix_lockf, METH_VARARGS, posix_lockf__doc__}, +#endif {"lseek", posix_lseek, METH_VARARGS, posix_lseek__doc__}, {"read", posix_read, METH_VARARGS, posix_read__doc__}, +#ifdef HAVE_READV + {"readv", posix_readv, METH_VARARGS, posix_readv__doc__}, +#endif +#ifdef HAVE_PREAD + {"pread", posix_pread, METH_VARARGS, posix_pread__doc__}, +#endif {"write", posix_write, METH_VARARGS, posix_write__doc__}, +#ifdef HAVE_WRITEV + {"writev", posix_writev, METH_VARARGS, posix_writev__doc__}, +#endif +#ifdef HAVE_PWRITE + {"pwrite", posix_pwrite, METH_VARARGS, posix_pwrite__doc__}, +#endif {"fstat", posix_fstat, METH_VARARGS, posix_fstat__doc__}, {"isatty", posix_isatty, METH_VARARGS, posix_isatty__doc__}, #ifdef HAVE_PIPE @@ -7971,6 +8710,15 @@ #ifdef HAVE_FTRUNCATE {"ftruncate", posix_ftruncate, METH_VARARGS, posix_ftruncate__doc__}, #endif +#ifdef HAVE_TRUNCATE + {"truncate", posix_truncate, METH_VARARGS, posix_truncate__doc__}, +#endif +#ifdef HAVE_POSIX_FALLOCATE + {"posix_fallocate", posix_posix_fallocate, METH_VARARGS, posix_posix_fallocate__doc__}, +#endif +#ifdef HAVE_POSIX_FADVISE + {"posix_fadvise", posix_posix_fadvise, METH_VARARGS, posix_posix_fadvise__doc__}, +#endif #ifdef HAVE_PUTENV {"putenv", posix_putenv, METH_VARARGS, posix_putenv__doc__}, #endif @@ -7984,6 +8732,9 @@ #ifdef HAVE_FSYNC {"fsync", posix_fsync, METH_O, posix_fsync__doc__}, #endif +#ifdef HAVE_SYNC + {"sync", posix_sync, METH_NOARGS, posix_sync__doc__}, +#endif #ifdef HAVE_FDATASYNC {"fdatasync", posix_fdatasync, METH_O, posix_fdatasync__doc__}, #endif @@ -8343,6 +9094,64 @@ if (ins(d, "ST_NOSUID", (long)ST_NOSUID)) return -1; #endif /* ST_NOSUID */ + /* constants for posix_fadvise */ +#ifdef POSIX_FADV_NORMAL + if (ins(d, "POSIX_FADV_NORMAL", (long)POSIX_FADV_NORMAL)) return -1; +#endif +#ifdef POSIX_FADV_SEQUENTIAL + if (ins(d, "POSIX_FADV_SEQUENTIAL", (long)POSIX_FADV_SEQUENTIAL)) return -1; +#endif +#ifdef POSIX_FADV_RANDOM + if (ins(d, "POSIX_FADV_RANDOM", (long)POSIX_FADV_RANDOM)) return -1; +#endif +#ifdef POSIX_FADV_NOREUSE + if (ins(d, "POSIX_FADV_NOREUSE", (long)POSIX_FADV_NOREUSE)) return -1; +#endif +#ifdef POSIX_FADV_WILLNEED + if (ins(d, "POSIX_FADV_WILLNEED", (long)POSIX_FADV_WILLNEED)) return -1; +#endif +#ifdef POSIX_FADV_DONTNEED + if (ins(d, "POSIX_FADV_DONTNEED", (long)POSIX_FADV_DONTNEED)) return -1; +#endif + + /* constants for waitid */ +#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID) + if (ins(d, "P_PID", (long)P_PID)) return -1; + if (ins(d, "P_PGID", (long)P_PGID)) return -1; + if (ins(d, "P_ALL", (long)P_ALL)) return -1; +#endif +#ifdef WEXITED + if (ins(d, "WEXITED", (long)WEXITED)) return -1; +#endif +#ifdef WNOWAIT + if (ins(d, "WNOWAIT", (long)WNOWAIT)) return -1; +#endif +#ifdef WSTOPPED + if (ins(d, "WSTOPPED", (long)WSTOPPED)) return -1; +#endif + + /* constants for lockf */ +#ifdef F_LOCK + if (ins(d, "F_LOCK", (long)F_LOCK)) return -1; +#endif +#ifdef F_TLOCK + if (ins(d, "F_TLOCK", (long)F_TLOCK)) return -1; +#endif +#ifdef F_ULOCK + if (ins(d, "F_ULOCK", (long)F_ULOCK)) return -1; +#endif +#ifdef F_TEST + if (ins(d, "F_TEST", (long)F_TEST)) return -1; +#endif + + /* constants for futimens */ +#ifdef UTIME_NOW + if (ins(d, "UTIME_NOW", (long)UTIME_NOW)) return -1; +#endif +#ifdef UTIME_OMIT + if (ins(d, "UTIME_OMIT", (long)UTIME_OMIT)) return -1; +#endif + #ifdef HAVE_SPAWNV #if defined(PYOS_OS2) && defined(PYCC_GCC) if (ins(d, "P_WAIT", (long)P_WAIT)) return -1; Index: pyconfig.h.in =================================================================== --- pyconfig.h.in (revision 87540) +++ pyconfig.h.in (working copy) @@ -220,6 +220,9 @@ /* Define if you have the 'fdatasync' function. */ #undef HAVE_FDATASYNC +/* Define to 1 if you have the `fexecve' function. */ +#undef HAVE_FEXECVE + /* Define to 1 if you have the `finite' function. */ #undef HAVE_FINITE @@ -259,6 +262,12 @@ /* Define to 1 if you have the `ftruncate' function. */ #undef HAVE_FTRUNCATE +/* Define to 1 if you have the `futimens' function. */ +#undef HAVE_FUTIMENS + +/* Define to 1 if you have the `futimes' function. */ +#undef HAVE_FUTIMES + /* Define to 1 if you have the `gai_strerror' function. */ #undef HAVE_GAI_STRERROR @@ -296,6 +305,9 @@ /* Define this if you have the 6-arg version of gethostbyname_r(). */ #undef HAVE_GETHOSTBYNAME_R_6_ARG +/* Define to 1 if you have the `gethostid' function. */ +#undef HAVE_GETHOSTID + /* Define to 1 if you have the `getitimer' function. */ #undef HAVE_GETITIMER @@ -437,6 +449,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_TIPC_H +/* Define to 1 if you have the `lockf' function. */ +#undef HAVE_LOCKF + /* Define to 1 if you have the `log1p' function. */ #undef HAVE_LOG1P @@ -449,6 +464,9 @@ /* Define to 1 if you have the `lstat' function. */ #undef HAVE_LSTAT +/* Define to 1 if you have the `lutimes' function. */ +#undef HAVE_LUTIMES + /* Define this if you have the makedev macro. */ #undef HAVE_MAKEDEV @@ -497,6 +515,9 @@ /* Define to 1 if you have the `pause' function. */ #undef HAVE_PAUSE +/* Define if the OS supports pipe2() */ +#undef HAVE_PIPE2 + /* Define to 1 if you have the `plock' function. */ #undef HAVE_PLOCK @@ -506,6 +527,15 @@ /* Define to 1 if you have the header file. */ #undef HAVE_POLL_H +/* Define to 1 if you have the `posix_fadvise' function. */ +#undef HAVE_POSIX_FADVISE + +/* Define to 1 if you have the `posix_fallocate' function. */ +#undef HAVE_POSIX_FALLOCATE + +/* Define to 1 if you have the `pread' function. */ +#undef HAVE_PREAD + /* Define to 1 if you have the header file. */ #undef HAVE_PROCESS_H @@ -530,9 +560,15 @@ /* Define to 1 if you have the `putenv' function. */ #undef HAVE_PUTENV +/* Define to 1 if you have the `pwrite' function. */ +#undef HAVE_PWRITE + /* Define to 1 if you have the `readlink' function. */ #undef HAVE_READLINK +/* Define to 1 if you have the `readv' function. */ +#undef HAVE_READV + /* Define to 1 if you have the `realpath' function. */ #undef HAVE_REALPATH @@ -587,6 +623,12 @@ /* Define if you have the 'setgroups' function. */ #undef HAVE_SETGROUPS +/* Define to 1 if you have the `sethostid' function. */ +#undef HAVE_SETHOSTID + +/* Define to 1 if you have the `sethostname' function. */ +#undef HAVE_SETHOSTNAME + /* Define to 1 if you have the `setitimer' function. */ #undef HAVE_SETITIMER @@ -718,6 +760,9 @@ /* Define if you have the 'symlink' function. */ #undef HAVE_SYMLINK +/* Define to 1 if you have the `sync' function. */ +#undef HAVE_SYNC + /* Define to 1 if you have the `sysconf' function. */ #undef HAVE_SYSCONF @@ -792,6 +837,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UIO_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_UN_H @@ -883,6 +931,9 @@ /* Define to 1 if you have the `wait4' function. */ #undef HAVE_WAIT4 +/* Define to 1 if you have the `waitid' function. */ +#undef HAVE_WAITID + /* Define to 1 if you have the `waitpid' function. */ #undef HAVE_WAITPID @@ -902,6 +953,9 @@ */ #undef HAVE_WORKING_TZSET +/* Define to 1 if you have the `writev' function. */ +#undef HAVE_WRITEV + /* Define if the zlib library has inflateCopy */ #undef HAVE_ZLIB_COPY