diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2016-09-06 23:18:52 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2016-09-06 23:18:52 (GMT) |
commit | 9b1f474df6f284de982c422c9a490971ccc1b296 (patch) | |
tree | 0db34b14b2c1b480d31050d035a2684333e8fc44 /Modules | |
parent | 3580b03352d8f04ebd0e9ce358868a6c53f4243c (diff) | |
download | cpython-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.h | 41 | ||||
-rw-r--r-- | Modules/posixmodule.c | 66 |
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; } |