summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2016-09-06 23:18:52 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2016-09-06 23:18:52 (GMT)
commit9b1f474df6f284de982c422c9a490971ccc1b296 (patch)
tree0db34b14b2c1b480d31050d035a2684333e8fc44 /Modules
parent3580b03352d8f04ebd0e9ce358868a6c53f4243c (diff)
downloadcpython-9b1f474df6f284de982c422c9a490971ccc1b296.zip
cpython-9b1f474df6f284de982c422c9a490971ccc1b296.tar.gz
cpython-9b1f474df6f284de982c422c9a490971ccc1b296.tar.bz2
Add os.getrandom()
Issue #27778: Expose the Linux getrandom() syscall as a new os.getrandom() function. This change is part of the PEP 524.
Diffstat (limited to 'Modules')
-rw-r--r--Modules/clinic/posixmodule.c.h41
-rw-r--r--Modules/posixmodule.c66
2 files changed, 106 insertions, 1 deletions
diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h
index b99f180..e543db4 100644
--- a/Modules/clinic/posixmodule.c.h
+++ b/Modules/clinic/posixmodule.c.h
@@ -5571,6 +5571,41 @@ exit:
return return_value;
}
+#if defined(HAVE_GETRANDOM_SYSCALL)
+
+PyDoc_STRVAR(os_getrandom__doc__,
+"getrandom($module, /, size, flags=0)\n"
+"--\n"
+"\n"
+"Obtain a series of random bytes.");
+
+#define OS_GETRANDOM_METHODDEF \
+ {"getrandom", (PyCFunction)os_getrandom, METH_VARARGS|METH_KEYWORDS, os_getrandom__doc__},
+
+static PyObject *
+os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags);
+
+static PyObject *
+os_getrandom(PyObject *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"size", "flags", NULL};
+ static _PyArg_Parser _parser = {"n|i:getrandom", _keywords, 0};
+ Py_ssize_t size;
+ int flags = 0;
+
+ if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
+ &size, &flags)) {
+ goto exit;
+ }
+ return_value = os_getrandom_impl(module, size, flags);
+
+exit:
+ return return_value;
+}
+
+#endif /* defined(HAVE_GETRANDOM_SYSCALL) */
+
#ifndef OS_TTYNAME_METHODDEF
#define OS_TTYNAME_METHODDEF
#endif /* !defined(OS_TTYNAME_METHODDEF) */
@@ -6042,4 +6077,8 @@ exit:
#ifndef OS_SET_HANDLE_INHERITABLE_METHODDEF
#define OS_SET_HANDLE_INHERITABLE_METHODDEF
#endif /* !defined(OS_SET_HANDLE_INHERITABLE_METHODDEF) */
-/*[clinic end generated code: output=677ce794fb126161 input=a9049054013a1b77]*/
+
+#ifndef OS_GETRANDOM_METHODDEF
+ #define OS_GETRANDOM_METHODDEF
+#endif /* !defined(OS_GETRANDOM_METHODDEF) */
+/*[clinic end generated code: output=fce51c7d432662c2 input=a9049054013a1b77]*/
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index beea9e0..2dc6d7b 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -133,6 +133,13 @@ corresponding Unix manual entries for more information on calls.");
#include <sys/sysctl.h>
#endif
+#ifdef HAVE_LINUX_RANDOM_H
+# include <linux/random.h>
+#endif
+#ifdef HAVE_GETRANDOM_SYSCALL
+# include <sys/syscall.h>
+#endif
+
#if defined(MS_WINDOWS)
# define TERMSIZE_USE_CONIO
#elif defined(HAVE_SYS_IOCTL_H)
@@ -12421,6 +12428,59 @@ os_fspath_impl(PyObject *module, PyObject *path)
return PyOS_FSPath(path);
}
+#ifdef HAVE_GETRANDOM_SYSCALL
+/*[clinic input]
+os.getrandom
+
+ size: Py_ssize_t
+ flags: int=0
+
+Obtain a series of random bytes.
+[clinic start generated code]*/
+
+static PyObject *
+os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
+/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
+{
+ char *buffer;
+ Py_ssize_t n;
+ PyObject *bytes;
+
+ if (size < 0) {
+ errno = EINVAL;
+ return posix_error();
+ }
+
+ buffer = PyMem_Malloc(size);
+ if (buffer == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ while (1) {
+ n = syscall(SYS_getrandom, buffer, size, flags);
+ if (n < 0 && errno == EINTR) {
+ if (PyErr_CheckSignals() < 0) {
+ return NULL;
+ }
+ continue;
+ }
+ break;
+ }
+
+ if (n < 0) {
+ PyMem_Free(buffer);
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+
+ bytes = PyBytes_FromStringAndSize(buffer, n);
+ PyMem_Free(buffer);
+
+ return bytes;
+}
+#endif /* HAVE_GETRANDOM_SYSCALL */
+
#include "clinic/posixmodule.c.h"
/*[clinic input]
@@ -12621,6 +12681,7 @@ static PyMethodDef posix_methods[] = {
METH_VARARGS | METH_KEYWORDS,
posix_scandir__doc__},
OS_FSPATH_METHODDEF
+ OS_GETRANDOM_METHODDEF
{NULL, NULL} /* Sentinel */
};
@@ -13066,6 +13127,11 @@ all_ins(PyObject *m)
if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
#endif
+#ifdef HAVE_GETRANDOM_SYSCALL
+ if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
+ if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
+#endif
+
return 0;
}