summaryrefslogtreecommitdiffstats
path: root/Modules/posixmodule.c
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2011-02-25 23:25:17 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2011-02-25 23:25:17 (GMT)
commitf65132de3d00171b74bc81791cacc5abdbafe3e4 (patch)
tree32c7880735f646598b91d13590dab51b9423e0ce /Modules/posixmodule.c
parent68e5c044e898c474750baeaee3234be8e27b5607 (diff)
downloadcpython-f65132de3d00171b74bc81791cacc5abdbafe3e4.zip
cpython-f65132de3d00171b74bc81791cacc5abdbafe3e4.tar.gz
cpython-f65132de3d00171b74bc81791cacc5abdbafe3e4.tar.bz2
Issue #4761: Add the *at() family of functions (openat(), etc.) to the posix
module. Patch by Ross Lagerwall.
Diffstat (limited to 'Modules/posixmodule.c')
-rw-r--r--Modules/posixmodule.c614
1 files changed, 614 insertions, 0 deletions
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 3226b32..1281af7 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -8009,6 +8009,552 @@ posix_getresgid (PyObject *self, PyObject *noargs)
}
#endif
+/* Posix *at family of functions:
+ faccessat, fchmodat, fchownat, fstatat, futimesat,
+ linkat, mkdirat, mknodat, openat, readlinkat, renameat, symlinkat,
+ unlinkat, utimensat, mkfifoat */
+
+#ifdef HAVE_FACCESSAT
+PyDoc_STRVAR(posix_faccessat__doc__,
+"faccessat(dirfd, path, mode, flags=0) -> True if granted, False otherwise\n\n\
+Like access() but if path is relative, it is taken as relative to dirfd.\n\
+flags is optional and can be constructed by ORing together zero or more\n\
+of these values: AT_SYMLINK_NOFOLLOW, AT_EACCESS.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_faccessat(PyObject *self, PyObject *args)
+{
+ PyObject *opath;
+ char *path;
+ int mode;
+ int res;
+ int dirfd, flags = 0;
+ if (!PyArg_ParseTuple(args, "iO&i|i:faccessat",
+ &dirfd, PyUnicode_FSConverter, &opath, &mode, &flags))
+ return NULL;
+ path = PyBytes_AsString(opath);
+ Py_BEGIN_ALLOW_THREADS
+ res = faccessat(dirfd, path, mode, flags);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opath);
+ return PyBool_FromLong(res == 0);
+}
+#endif
+
+#ifdef HAVE_FCHMODAT
+PyDoc_STRVAR(posix_fchmodat__doc__,
+"fchmodat(dirfd, path, mode, flags=0)\n\n\
+Like chmod() but if path is relative, it is taken as relative to dirfd.\n\
+flags is optional and may be 0 or AT_SYMLINK_NOFOLLOW.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_fchmodat(PyObject *self, PyObject *args)
+{
+ int dirfd, mode, res;
+ int flags = 0;
+ PyObject *opath;
+ char *path;
+
+ if (!PyArg_ParseTuple(args, "iO&i|i:fchmodat",
+ &dirfd, PyUnicode_FSConverter, &opath, &mode, &flags))
+ return NULL;
+
+ path = PyBytes_AsString(opath);
+
+ Py_BEGIN_ALLOW_THREADS
+ res = fchmodat(dirfd, path, mode, flags);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opath);
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_FCHMODAT */
+
+#ifdef HAVE_FCHOWNAT
+PyDoc_STRVAR(posix_fchownat__doc__,
+"fchownat(dirfd, path, uid, gid, flags=0)\n\n\
+Like chown() but if path is relative, it is taken as relative to dirfd.\n\
+flags is optional and may be 0 or AT_SYMLINK_NOFOLLOW.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_fchownat(PyObject *self, PyObject *args)
+{
+ PyObject *opath;
+ int dirfd, res;
+ long uid, gid;
+ int flags = 0;
+ char *path;
+
+ if (!PyArg_ParseTuple(args, "iO&ll|i:fchownat",
+ &dirfd, PyUnicode_FSConverter, &opath, &uid, &gid, &flags))
+ return NULL;
+
+ path = PyBytes_AsString(opath);
+
+ Py_BEGIN_ALLOW_THREADS
+ res = fchownat(dirfd, path, (uid_t) uid, (gid_t) gid, flags);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opath);
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_FCHOWNAT */
+
+#ifdef HAVE_FSTATAT
+PyDoc_STRVAR(posix_fstatat__doc__,
+"fstatat(dirfd, path, flags=0) -> stat result\n\n\
+Like stat() but if path is relative, it is taken as relative to dirfd.\n\
+flags is optional and may be 0 or AT_SYMLINK_NOFOLLOW.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_fstatat(PyObject *self, PyObject *args)
+{
+ PyObject *opath;
+ char *path;
+ STRUCT_STAT st;
+ int dirfd, res, flags = 0;
+
+ if (!PyArg_ParseTuple(args, "iO&|i:fstatat",
+ &dirfd, PyUnicode_FSConverter, &opath, &flags))
+ return NULL;
+ path = PyBytes_AsString(opath);
+
+ Py_BEGIN_ALLOW_THREADS
+ res = fstatat(dirfd, path, &st, flags);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opath);
+ if (res != 0)
+ return posix_error();
+
+ return _pystat_fromstructstat(&st);
+}
+#endif
+
+#ifdef HAVE_FUTIMESAT
+PyDoc_STRVAR(posix_futimesat__doc__,
+"futimesat(dirfd, path, (atime, mtime))\n\
+futimesat(dirfd, path, None)\n\n\
+Like utime() but if path is relative, it is taken as relative to dirfd.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_futimesat(PyObject *self, PyObject *args)
+{
+ PyObject *opath;
+ char *path;
+ int res, dirfd;
+ PyObject* arg;
+
+ struct timeval buf[2];
+
+ if (!PyArg_ParseTuple(args, "iO&O:futimesat",
+ &dirfd, PyUnicode_FSConverter, &opath, &arg))
+ return NULL;
+ path = PyBytes_AsString(opath);
+ if (arg == Py_None) {
+ /* optional time values not given */
+ Py_BEGIN_ALLOW_THREADS
+ res = futimesat(dirfd, path, NULL);
+ Py_END_ALLOW_THREADS
+ }
+ else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) {
+ PyErr_SetString(PyExc_TypeError,
+ "futimesat() arg 3 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 = futimesat(dirfd, path, buf);
+ Py_END_ALLOW_THREADS
+ }
+ Py_DECREF(opath);
+ if (res < 0) {
+ return posix_error();
+ }
+ Py_RETURN_NONE;
+}
+#endif
+
+#ifdef HAVE_LINKAT
+PyDoc_STRVAR(posix_linkat__doc__,
+"linkat(srcfd, srcpath, dstfd, dstpath, flags=0)\n\n\
+Like link() but if srcpath is relative, it is taken as relative to srcfd\n\
+and if dstpath is relative, it is taken as relative to dstfd.\n\
+flags is optional and may be 0 or AT_SYMLINK_FOLLOW.\n\
+If srcpath is relative and srcfd is the special value AT_FDCWD, then\n\
+srcpath is interpreted relative to the current working directory. This\n\
+also applies for dstpath.");
+
+static PyObject *
+posix_linkat(PyObject *self, PyObject *args)
+{
+ PyObject *osrc, *odst;
+ char *src, *dst;
+ int res, srcfd, dstfd;
+ int flags = 0;
+
+ if (!PyArg_ParseTuple(args, "iO&iO&|i:linkat",
+ &srcfd, PyUnicode_FSConverter, &osrc, &dstfd, PyUnicode_FSConverter, &odst, &flags))
+ return NULL;
+ src = PyBytes_AsString(osrc);
+ dst = PyBytes_AsString(odst);
+ Py_BEGIN_ALLOW_THREADS
+ res = linkat(srcfd, src, dstfd, dst, flags);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(osrc);
+ Py_DECREF(odst);
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_LINKAT */
+
+#ifdef HAVE_MKDIRAT
+PyDoc_STRVAR(posix_mkdirat__doc__,
+"mkdirat(dirfd, path, mode=0o777)\n\n\
+Like mkdir() but if path is relative, it is taken as relative to dirfd.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_mkdirat(PyObject *self, PyObject *args)
+{
+ int res, dirfd;
+ PyObject *opath;
+ char *path;
+ int mode = 0777;
+
+ if (!PyArg_ParseTuple(args, "iO&|i:mkdirat",
+ &dirfd, PyUnicode_FSConverter, &opath, &mode))
+ return NULL;
+ path = PyBytes_AsString(opath);
+ Py_BEGIN_ALLOW_THREADS
+ res = mkdirat(dirfd, path, mode);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opath);
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif
+
+#if defined(HAVE_MKNODAT) && defined(HAVE_MAKEDEV)
+PyDoc_STRVAR(posix_mknodat__doc__,
+"mknodat(dirfd, path, mode=0o600, device=0)\n\n\
+Like mknod() but if path is relative, it is taken as relative to dirfd.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_mknodat(PyObject *self, PyObject *args)
+{
+ PyObject *opath;
+ char *filename;
+ int mode = 0600;
+ int device = 0;
+ int res, dirfd;
+ if (!PyArg_ParseTuple(args, "iO&|ii:mknodat", &dirfd,
+ PyUnicode_FSConverter, &opath, &mode, &device))
+ return NULL;
+ filename = PyBytes_AS_STRING(opath);
+ Py_BEGIN_ALLOW_THREADS
+ res = mknodat(dirfd, filename, mode, device);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opath);
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif
+
+#ifdef HAVE_OPENAT
+PyDoc_STRVAR(posix_openat__doc__,
+"openat(dirfd, path, flag, mode=0o777) -> fd\n\n\
+Like open() but if path is relative, it is taken as relative to dirfd.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_openat(PyObject *self, PyObject *args)
+{
+ PyObject *ofile;
+ char *file;
+ int flag, dirfd, fd;
+ int mode = 0777;
+
+ if (!PyArg_ParseTuple(args, "iO&i|i:openat",
+ &dirfd, PyUnicode_FSConverter, &ofile,
+ &flag, &mode))
+ return NULL;
+ file = PyBytes_AsString(ofile);
+ Py_BEGIN_ALLOW_THREADS
+ fd = openat(dirfd, file, flag, mode);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(ofile);
+ if (fd < 0)
+ return posix_error();
+ return PyLong_FromLong((long)fd);
+}
+#endif
+
+#ifdef HAVE_READLINKAT
+PyDoc_STRVAR(posix_readlinkat__doc__,
+"readlinkat(dirfd, path) -> path\n\n\
+Like readlink() but if path is relative, it is taken as relative to dirfd.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_readlinkat(PyObject *self, PyObject *args)
+{
+ PyObject *v, *opath;
+ char buf[MAXPATHLEN];
+ char *path;
+ int n, dirfd;
+ int arg_is_unicode = 0;
+
+ if (!PyArg_ParseTuple(args, "iO&:readlinkat",
+ &dirfd, PyUnicode_FSConverter, &opath))
+ return NULL;
+ path = PyBytes_AsString(opath);
+ v = PySequence_GetItem(args, 1);
+ if (v == NULL) {
+ Py_DECREF(opath);
+ return NULL;
+ }
+
+ if (PyUnicode_Check(v)) {
+ arg_is_unicode = 1;
+ }
+ Py_DECREF(v);
+
+ Py_BEGIN_ALLOW_THREADS
+ n = readlinkat(dirfd, path, buf, (int) sizeof buf);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opath);
+ if (n < 0)
+ return posix_error();
+
+ if (arg_is_unicode)
+ return PyUnicode_DecodeFSDefaultAndSize(buf, n);
+ else
+ return PyBytes_FromStringAndSize(buf, n);
+}
+#endif /* HAVE_READLINKAT */
+
+#ifdef HAVE_RENAMEAT
+PyDoc_STRVAR(posix_renameat__doc__,
+"renameat(olddirfd, oldpath, newdirfd, newpath)\n\n\
+Like rename() but if oldpath is relative, it is taken as relative to\n\
+olddirfd and if newpath is relative, it is taken as relative to newdirfd.\n\
+If oldpath is relative and olddirfd is the special value AT_FDCWD, then\n\
+oldpath is interpreted relative to the current working directory. This\n\
+also applies for newpath.");
+
+static PyObject *
+posix_renameat(PyObject *self, PyObject *args)
+{
+ int res;
+ PyObject *opathold, *opathnew;
+ char *opath, *npath;
+ int oldfd, newfd;
+
+ if (!PyArg_ParseTuple(args, "iO&iO&:renameat",
+ &oldfd, PyUnicode_FSConverter, &opathold, &newfd, PyUnicode_FSConverter, &opathnew))
+ return NULL;
+ opath = PyBytes_AsString(opathold);
+ npath = PyBytes_AsString(opathnew);
+ Py_BEGIN_ALLOW_THREADS
+ res = renameat(oldfd, opath, newfd, npath);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opathold);
+ Py_DECREF(opathnew);
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif
+
+#if HAVE_SYMLINKAT
+PyDoc_STRVAR(posix_symlinkat__doc__,
+"symlinkat(src, dstfd, dst)\n\n\
+Like symlink() but if dst is relative, it is taken as relative to dstfd.\n\
+If dst is relative and dstfd is the special value AT_FDCWD, then dst\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_symlinkat(PyObject *self, PyObject *args)
+{
+ int res, dstfd;
+ PyObject *osrc, *odst;
+ char *src, *dst;
+
+ if (!PyArg_ParseTuple(args, "O&iO&:symlinkat",
+ PyUnicode_FSConverter, &osrc, &dstfd, PyUnicode_FSConverter, &odst))
+ return NULL;
+ src = PyBytes_AsString(osrc);
+ dst = PyBytes_AsString(odst);
+ Py_BEGIN_ALLOW_THREADS
+ res = symlinkat(src, dstfd, dst);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(osrc);
+ Py_DECREF(odst);
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_SYMLINKAT */
+
+#ifdef HAVE_UNLINKAT
+PyDoc_STRVAR(posix_unlinkat__doc__,
+"unlinkat(dirfd, path, flags=0)\n\n\
+Like unlink() but if path is relative, it is taken as relative to dirfd.\n\
+flags is optional and may be 0 or AT_REMOVEDIR. If AT_REMOVEDIR is\n\
+specified, unlinkat() behaves like rmdir().\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_unlinkat(PyObject *self, PyObject *args)
+{
+ int dirfd, res, flags = 0;
+ PyObject *opath;
+ char *path;
+
+ if (!PyArg_ParseTuple(args, "iO&|i:unlinkat",
+ &dirfd, PyUnicode_FSConverter, &opath, &flags))
+ return NULL;
+ path = PyBytes_AsString(opath);
+ Py_BEGIN_ALLOW_THREADS
+ res = unlinkat(dirfd, path, flags);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opath);
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif
+
+#ifdef HAVE_UTIMENSAT
+PyDoc_STRVAR(posix_utimensat__doc__,
+"utimensat(dirfd, path, (atime_sec, atime_nsec),\n\
+ (mtime_sec, mtime_nsec), flags)\n\
+utimensat(dirfd, path, None, None, flags)\n\n\
+Updates the timestamps of a file with nanosecond precision. If path is\n\
+relative, it is taken as relative to dirfd.\n\
+The second form sets atime and mtime to the current time.\n\
+flags is optional and may be 0 or AT_SYMLINK_NOFOLLOW.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.\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_utimensat(PyObject *self, PyObject *args)
+{
+ PyObject *opath;
+ char *path;
+ int res, dirfd, flags = 0;
+ PyObject *atime, *mtime;
+
+ struct timespec buf[2];
+
+ if (!PyArg_ParseTuple(args, "iO&OO|i:utimensat",
+ &dirfd, PyUnicode_FSConverter, &opath, &atime, &mtime, &flags))
+ return NULL;
+ path = PyBytes_AsString(opath);
+ if (atime == Py_None && mtime == Py_None) {
+ /* optional time values not given */
+ Py_BEGIN_ALLOW_THREADS
+ res = utimensat(dirfd, path, NULL, flags);
+ Py_END_ALLOW_THREADS
+ }
+ else if (!PyTuple_Check(atime) || PyTuple_Size(atime) != 2) {
+ PyErr_SetString(PyExc_TypeError,
+ "utimensat() arg 3 must be a tuple (atime_sec, atime_nsec)");
+ Py_DECREF(opath);
+ return NULL;
+ }
+ else if (!PyTuple_Check(mtime) || PyTuple_Size(mtime) != 2) {
+ PyErr_SetString(PyExc_TypeError,
+ "utimensat() arg 4 must be a tuple (mtime_sec, mtime_nsec)");
+ Py_DECREF(opath);
+ return NULL;
+ }
+ else {
+ if (!PyArg_ParseTuple(atime, "ll:utimensat",
+ &(buf[0].tv_sec), &(buf[0].tv_nsec))) {
+ Py_DECREF(opath);
+ return NULL;
+ }
+ if (!PyArg_ParseTuple(mtime, "ll:utimensat",
+ &(buf[1].tv_sec), &(buf[1].tv_nsec))) {
+ Py_DECREF(opath);
+ return NULL;
+ }
+ Py_BEGIN_ALLOW_THREADS
+ res = utimensat(dirfd, path, buf, flags);
+ Py_END_ALLOW_THREADS
+ }
+ Py_DECREF(opath);
+ if (res < 0) {
+ return posix_error();
+ }
+ Py_RETURN_NONE;
+}
+#endif
+
+#ifdef HAVE_MKFIFOAT
+PyDoc_STRVAR(posix_mkfifoat__doc__,
+"mkfifoat(dirfd, path, mode=0o666)\n\n\
+Like mkfifo() but if path is relative, it is taken as relative to dirfd.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_mkfifoat(PyObject *self, PyObject *args)
+{
+ PyObject *opath;
+ char *filename;
+ int mode = 0666;
+ int res, dirfd;
+ if (!PyArg_ParseTuple(args, "iO&|i:mkfifoat",
+ &dirfd, PyUnicode_FSConverter, &opath, &mode))
+ return NULL;
+ filename = PyBytes_AS_STRING(opath);
+ Py_BEGIN_ALLOW_THREADS
+ res = mkfifoat(dirfd, filename, mode);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opath);
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif
+
static PyMethodDef posix_methods[] = {
{"access", posix_access, METH_VARARGS, posix_access__doc__},
#ifdef HAVE_TTYNAME
@@ -8335,6 +8881,52 @@ static PyMethodDef posix_methods[] = {
{"getresgid", posix_getresgid, METH_NOARGS, posix_getresgid__doc__},
#endif
+/* posix *at family of functions */
+#ifdef HAVE_FACCESSAT
+ {"faccessat", posix_faccessat, METH_VARARGS, posix_faccessat__doc__},
+#endif
+#ifdef HAVE_FCHMODAT
+ {"fchmodat", posix_fchmodat, METH_VARARGS, posix_fchmodat__doc__},
+#endif /* HAVE_FCHMODAT */
+#ifdef HAVE_FCHOWNAT
+ {"fchownat", posix_fchownat, METH_VARARGS, posix_fchownat__doc__},
+#endif /* HAVE_FCHOWNAT */
+#ifdef HAVE_FSTATAT
+ {"fstatat", posix_fstatat, METH_VARARGS, posix_fstatat__doc__},
+#endif
+#ifdef HAVE_FUTIMESAT
+ {"futimesat", posix_futimesat, METH_VARARGS, posix_futimesat__doc__},
+#endif
+#ifdef HAVE_LINKAT
+ {"linkat", posix_linkat, METH_VARARGS, posix_linkat__doc__},
+#endif /* HAVE_LINKAT */
+#ifdef HAVE_MKDIRAT
+ {"mkdirat", posix_mkdirat, METH_VARARGS, posix_mkdirat__doc__},
+#endif
+#if defined(HAVE_MKNODAT) && defined(HAVE_MAKEDEV)
+ {"mknodat", posix_mknodat, METH_VARARGS, posix_mknodat__doc__},
+#endif
+#ifdef HAVE_OPENAT
+ {"openat", posix_openat, METH_VARARGS, posix_openat__doc__},
+#endif
+#ifdef HAVE_READLINKAT
+ {"readlinkat", posix_readlinkat, METH_VARARGS, posix_readlinkat__doc__},
+#endif /* HAVE_READLINKAT */
+#ifdef HAVE_RENAMEAT
+ {"renameat", posix_renameat, METH_VARARGS, posix_renameat__doc__},
+#endif
+#if HAVE_SYMLINKAT
+ {"symlinkat", posix_symlinkat, METH_VARARGS, posix_symlinkat__doc__},
+#endif /* HAVE_SYMLINKAT */
+#ifdef HAVE_UNLINKAT
+ {"unlinkat", posix_unlinkat, METH_VARARGS, posix_unlinkat__doc__},
+#endif
+#ifdef HAVE_UTIMENSAT
+ {"utimensat", posix_utimensat, METH_VARARGS, posix_utimensat__doc__},
+#endif
+#ifdef HAVE_MKFIFOAT
+ {"mkfifoat", posix_mkfifoat, METH_VARARGS, posix_mkfifoat__doc__},
+#endif
{NULL, NULL} /* Sentinel */
};
@@ -8520,6 +9112,28 @@ all_ins(PyObject *d)
#ifdef PRIO_USER
if (ins(d, "PRIO_USER", (long)PRIO_USER)) return -1;
#endif
+/* posix - constants for *at functions */
+#ifdef AT_SYMLINK_NOFOLLOW
+ if (ins(d, "AT_SYMLINK_NOFOLLOW", (long)AT_SYMLINK_NOFOLLOW)) return -1;
+#endif
+#ifdef AT_EACCESS
+ if (ins(d, "AT_EACCESS", (long)AT_EACCESS)) return -1;
+#endif
+#ifdef AT_FDCWD
+ if (ins(d, "AT_FDCWD", (long)AT_FDCWD)) return -1;
+#endif
+#ifdef AT_REMOVEDIR
+ if (ins(d, "AT_REMOVEDIR", (long)AT_REMOVEDIR)) return -1;
+#endif
+#ifdef AT_SYMLINK_FOLLOW
+ if (ins(d, "AT_SYMLINK_FOLLOW", (long)AT_SYMLINK_FOLLOW)) return -1;
+#endif
+#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
/* MS Windows */