summaryrefslogtreecommitdiff
path: root/pipermail/pycrypto/attachments/20120203/0576251d/attachment-0001.patch
blob: 6e506b6c7cdff85ee57918831d7139dad3b5d5a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
>From 00160026b80399b962ea0c367aa5b7ec55cbc9a8 Mon Sep 17 00:00:00 2001
From: Sebastian Ramacher <s.ramacher@gmx.at>
Date: Fri, 3 Feb 2012 15:26:27 +0100
Subject: [PATCH] Fix DevURandomRNG to work with Python3's new I/O stack.

---
 lib/Crypto/Random/OSRNG/posix.py |   27 +++++++++++++++++++++++++--
 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)
-- 
1.7.9