1
0

random.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /* Copyright libuv contributors. All rights reserved.
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to
  5. * deal in the Software without restriction, including without limitation the
  6. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  7. * sell copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. *
  10. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  18. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  19. * IN THE SOFTWARE.
  20. */
  21. #include "uv.h"
  22. #include "uv-common.h"
  23. #ifdef _WIN32
  24. # include "win/internal.h"
  25. #else
  26. # include "unix/internal.h"
  27. #endif
  28. static int uv__random(void* buf, size_t buflen) {
  29. int rc;
  30. #if defined(__PASE__)
  31. rc = uv__random_readpath("/dev/urandom", buf, buflen);
  32. #elif defined(_AIX) || defined(__QNX__)
  33. rc = uv__random_readpath("/dev/random", buf, buflen);
  34. #elif defined(__APPLE__) || defined(__OpenBSD__) || \
  35. (defined(__ANDROID_API__) && __ANDROID_API__ >= 28)
  36. rc = uv__random_getentropy(buf, buflen);
  37. if (rc == UV_ENOSYS)
  38. rc = uv__random_devurandom(buf, buflen);
  39. #elif defined(__NetBSD__)
  40. rc = uv__random_sysctl(buf, buflen);
  41. #elif defined(__FreeBSD__) || defined(__linux__)
  42. rc = uv__random_getrandom(buf, buflen);
  43. if (rc == UV_ENOSYS)
  44. rc = uv__random_devurandom(buf, buflen);
  45. # if defined(__linux__)
  46. switch (rc) {
  47. case UV_EACCES:
  48. case UV_EIO:
  49. case UV_ELOOP:
  50. case UV_EMFILE:
  51. case UV_ENFILE:
  52. case UV_ENOENT:
  53. case UV_EPERM:
  54. rc = uv__random_sysctl(buf, buflen);
  55. break;
  56. }
  57. # endif
  58. #elif defined(_WIN32)
  59. uv__once_init();
  60. rc = uv__random_rtlgenrandom(buf, buflen);
  61. #else
  62. rc = uv__random_devurandom(buf, buflen);
  63. #endif
  64. return rc;
  65. }
  66. static void uv__random_work(struct uv__work* w) {
  67. uv_random_t* req;
  68. req = container_of(w, uv_random_t, work_req);
  69. req->status = uv__random(req->buf, req->buflen);
  70. }
  71. static void uv__random_done(struct uv__work* w, int status) {
  72. uv_random_t* req;
  73. req = container_of(w, uv_random_t, work_req);
  74. uv__req_unregister(req->loop, req);
  75. if (status == 0)
  76. status = req->status;
  77. req->cb(req, status, req->buf, req->buflen);
  78. }
  79. int uv_random(uv_loop_t* loop,
  80. uv_random_t* req,
  81. void *buf,
  82. size_t buflen,
  83. unsigned flags,
  84. uv_random_cb cb) {
  85. if (buflen > 0x7FFFFFFFu)
  86. return UV_E2BIG;
  87. if (flags != 0)
  88. return UV_EINVAL;
  89. if (cb == NULL)
  90. return uv__random(buf, buflen);
  91. uv__req_init(loop, req, UV_RANDOM);
  92. req->loop = loop;
  93. req->status = 0;
  94. req->cb = cb;
  95. req->buf = buf;
  96. req->buflen = buflen;
  97. uv__work_submit(loop,
  98. &req->work_req,
  99. UV__WORK_CPU,
  100. uv__random_work,
  101. uv__random_done);
  102. return 0;
  103. }