summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Ramacher <s.ramacher@gmx.at>2012-02-03 15:26:27 +0100
committerDwayne C. Litzenberger <dlitz@dlitz.net>2012-04-21 12:59:49 -0400
commit95d65366e9ac7e194bf8317d69785c9a5b877790 (patch)
tree52777b4b2ffbc677d4b28d044f0ad78adb6d040c
parent5f1d0abf8d615dcf8bdcf17f310f9644c8c06305 (diff)
downloadpycrypto-95d65366e9ac7e194bf8317d69785c9a5b877790.tar.gz
Fix DevURandomRNG to work with Python3's new I/O stack.
-rw-r--r--lib/Crypto/Random/OSRNG/posix.py27
1 files changed, 25 insertions, 2 deletions
diff --git a/lib/Crypto/Random/OSRNG/posix.py b/lib/Crypto/Random/OSRNG/posix.py
index f88cd77..ca6ac05 100644
--- a/lib/Crypto/Random/OSRNG/posix.py
+++ b/lib/Crypto/Random/OSRNG/posix.py
@@ -25,10 +25,12 @@
__revision__ = "$Id$"
__all__ = ['DevURandomRNG']
+import errno
import os
import stat
from rng_base import BaseRNG
+from Crypto.Util.py3compat import b
class DevURandomRNG(BaseRNG):
@@ -46,7 +48,6 @@ class DevURandomRNG(BaseRNG):
raise TypeError("%r is not a character special device" % (self.name,))
self.__file = f
- self._read = f.read
BaseRNG.__init__(self)
@@ -54,7 +55,29 @@ class DevURandomRNG(BaseRNG):
self.__file.close()
def _read(self, N):
- return self.__file.read(N)
+ # Starting with Python 3 open with buffering=0 returns a FileIO object.
+ # FileIO.read behaves like read(2) and not like fread(3) and thus we
+ # have to handle the case that read returns less data as requested here
+ # more carefully.
+ data = b("")
+ while len(data) < N:
+ try:
+ d = self.__file.read(N - len(data))
+ except IOError, e:
+ # read(2) has been interrupted by a signal; redo the read
+ if e.errno == errno.EINTR:
+ continue
+ raise
+
+ if d is None:
+ # __file is in non-blocking mode and no data is available
+ return data
+ if len(d) == 0:
+ # __file is in blocking mode and arrived at EOF
+ return data
+
+ data += d
+ return data
def new(*args, **kwargs):
return DevURandomRNG(*args, **kwargs)