1 /*******************************************************************************
2         copyright:      Copyright (c) 2008. Fawzi Mohamed
3         license:        BSD style: $(LICENSE)
4         version:        Initial release: July 2008
5         author:         Fawzi Mohamed
6 *******************************************************************************/
7 module tango.math.random.engines.URandom;
8 version(OSX) { version=has_urandom; }
9 version(linux)  { version=has_urandom; }
10 version(solaris){ version=has_urandom; }
11 
12 version(has_urandom) {
13     private import Integer = tango.text.convert.Integer;
14     import tango.core.sync.Mutex: Mutex;
15     import tango.io.device.File; // use stdc read/write?
16 
17     /// basic source that takes data from system random device
18     /// This is an engine, do not use directly, use RandomG!(Urandom)
19     /// should use stdc rad/write?
20     struct URandom{
21         static __gshared File.Style readStyle;
22         static __gshared Mutex lock;
23         shared static this(){
24             readStyle.access=File.Access.Read;
25             readStyle.open  =File.Open.Exists;
26             readStyle.share =File.Share.Read;
27             readStyle.cache =File.Cache.None;
28 
29             lock=new Mutex();
30         }
31         enum int canCheckpoint=false;
32         enum int canSeed=false;
33     
34         void skip(uint n){ }
35         ubyte nextB(){
36             union ToVoidA{
37                 ubyte i;
38                 void[1] a;
39             }
40             ToVoidA el;
41             synchronized(lock){
42                 auto fn = new File("/dev/urandom", readStyle); 
43                 if(fn.read(el.a)!=el.a.length){
44                     throw new Exception("could not write the requested bytes from urandom");
45                 }
46                 fn.close();
47             }
48             return el.i;
49         }
50         uint next(){
51             union ToVoidA{
52                 uint i;
53                 void[4] a;
54             }
55             ToVoidA el;
56             synchronized(lock){
57                 auto fn = new File("/dev/urandom", readStyle); 
58                 if(fn.read(el.a)!=el.a.length){
59                     throw new Exception("could not write the requested bytes from urandom");
60                 }
61                 fn.close();
62             }
63             return el.i;
64         }
65         ulong nextL(){
66             union ToVoidA{
67                 ulong l;
68                 void[8] a;
69             }
70             ToVoidA el;
71             synchronized(lock){
72                 auto fn = new File("/dev/urandom", readStyle); 
73                 if(fn.read(el.a)!=el.a.length){
74                     throw new Exception("could not write the requested bytes from urandom");
75                 }
76                 fn.close();
77             }
78             return el.l;
79         }
80         /// does nothing
81         void seed(scope uint delegate() r) { }
82         /// writes the current status in a string
83         immutable(char)[] toString(){
84             return "URandom";
85         }
86         /// reads the current status from a string (that should have been trimmed)
87         /// returns the number of chars read
88         size_t fromString(const(char[]) s){
89             const(char)[] r="URandom";
90             assert(s[0.. r.length]==r,"unxepected string instad of URandom:"~s);
91             return r.length;
92         }
93     }
94 }