uuid.inc 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. {
  2. $Id: sysutils.pp,v 1.59 2005/03/25 22:53:39 jonas Exp $
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Florian Klaempfl
  5. member of the Free Pascal development team
  6. Sysutils unit for linux
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. Const
  14. KernelUUID = '/proc/sys/kernel/random/uuid';
  15. PreferKernelUUID = False;
  16. Procedure GetURandomBytes(Var Buf; NBytes : Integer);
  17. Var
  18. fd,I : Integer;
  19. P : PByte;
  20. begin
  21. P:=@Buf;
  22. fd:=FileOpen('/dev/urandom',fmOpenRead);
  23. if (fd>=0) then
  24. Try
  25. While (NBytes>0) do
  26. begin
  27. I:=FileRead(fd,P^,nbytes);
  28. If I>0 then
  29. begin
  30. Inc(P,I);
  31. Dec(NBytes,I);
  32. end;
  33. end;
  34. Finally
  35. FileClose(Fd);
  36. end
  37. else
  38. GetRandomBytes(Buf,NBytes);
  39. end;
  40. Const
  41. MAX_ADJUSTMENT = 10;
  42. IPPROTO_IP = 0;
  43. AF_INET = 2;
  44. SOCK_DGRAM = 2;
  45. IF_NAMESIZE = 16;
  46. SIOCGIFCONF = $8912;
  47. SIOCGIFHWADDR = $8927;
  48. Type
  49. {$ifdef FreeBSD}
  50. {$DEFINE SOCK_HAS_SINLEN} // BSD definition of scoketaddr
  51. {$endif}
  52. {$ifdef SOCK_HAS_SINLEN}
  53. sa_family_t=cuchar;
  54. {$else}
  55. sa_family_t=cushort;
  56. {$endif}
  57. Type
  58. in_addr = packed record
  59. case boolean of
  60. true: (s_addr : cuint32); // inaddr_t=cuint32
  61. false: (s_bytes : packed array[1..4] of byte);
  62. end;
  63. TSockAddr = packed Record // if sa_len is defined, sa_family_t is smaller
  64. {$ifdef SOCK_HAS_SINLEN}
  65. sa_len : cuchar;
  66. {$endif}
  67. case integer of
  68. 0: (sa_family: sa_family_t;
  69. sa_data: packed array[0..13] of Byte);
  70. 1: (sin_family: sa_family_t;
  71. sin_port: cushort;
  72. sin_addr: in_addr;
  73. sin_zero: packed array[0..7] of Byte);
  74. end;
  75. PSockAddr = ^TSockAddr;
  76. Sockaddr = TSockAddr; // Kylix compat
  77. {$packrecords c}
  78. tifr_ifrn = record
  79. case integer of
  80. 0 : (ifrn_name: array [0..IF_NAMESIZE-1] of char);
  81. end;
  82. tifmap = record
  83. mem_start : cardinal;
  84. mem_end : cardinal;
  85. base_addr : word;
  86. irq : byte;
  87. dma : byte;
  88. port : byte;
  89. end;
  90. TIFrec = record
  91. ifr_ifrn : tifr_ifrn;
  92. case integer of
  93. 0 : (ifru_addr : TSockAddr);
  94. 1 : (ifru_dstaddr : TSockAddr);
  95. 2 : (ifru_broadaddr : TSockAddr);
  96. 3 : (ifru_netmask : TSockAddr);
  97. 4 : (ifru_hwaddr : TSockAddr);
  98. 5 : (ifru_flags : word);
  99. 6 : (ifru_ivalue : longint);
  100. 7 : (ifru_mtu : longint);
  101. 8 : (ifru_map : tifmap);
  102. 9 : (ifru_slave : Array[0..IF_NAMESIZE-1] of char);
  103. 10 : (ifru_newname : Array[0..IF_NAMESIZE-1] of char);
  104. 11 : (ifru_data : pointer);
  105. end;
  106. TIFConf = record
  107. ifc_len : longint;
  108. case integer of
  109. 0 : (ifcu_buf : pointer);
  110. 1 : (ifcu_req : ^tifrec);
  111. end;
  112. tuuid = record
  113. time_low : cardinal;
  114. time_mid : Word;
  115. time_hi_and_version : Word;
  116. clock_seq : Word;
  117. node : Array[0..5] of byte;
  118. end;
  119. Function SocketCall(SockCallNr,a1,a2,a3,a4,a5,a6:longint):longint;
  120. var
  121. Args:array[1..6] of longint;
  122. begin
  123. args[1]:=a1;
  124. args[2]:=a2;
  125. args[3]:=a3;
  126. args[4]:=a4;
  127. args[5]:=a5;
  128. args[6]:=a6;
  129. SocketCall:=do_Syscall(syscall_nr_socketcall,sockcallnr,longint(@args));
  130. end;
  131. function SocketCall(SockCallNr,a1,a2,a3:longint):longint;
  132. begin
  133. SocketCall:=SocketCall(SockCallNr,a1,a2,a3,0,0,0);
  134. end;
  135. function fpsocket (domain:cint; xtype:cint; protocol: cint):cint;
  136. begin
  137. fpSocket:=SocketCall(1,Domain,xtype,Protocol);
  138. end;
  139. Var
  140. MacAddr : Packed Array[1..6] of byte = (0,0,0,0,0,0);
  141. MacAddrTried : Byte = 0 ;
  142. Last : TTimeVal = (tv_sec:0;tv_usec:0);
  143. ClockSeq : Word = 0;
  144. AdjustMent : Integer = 0;
  145. Function GetMacAddr : Boolean;
  146. var
  147. i,j,n,Sd : Integer;
  148. buf : Array[0..1023] of byte;
  149. ifc : TIfConf;
  150. ifr : TIFRec;
  151. ifp : ^TIFRec;
  152. p : PChar;
  153. begin
  154. Result:=MacAddrTried>0;
  155. If Result then
  156. Result:=MacAddrTried>1
  157. else
  158. begin
  159. MacAddrTried:=1;
  160. sd:=fpSocket(AF_INET,SOCK_DGRAM,IPPROTO_IP);
  161. if (sd<0) then
  162. exit;
  163. Try
  164. ifc.ifc_len:=Sizeof(Buf);
  165. ifc.ifcu_buf:=@buf;
  166. if fpioctl(sd, SIOCGIFCONF, @ifc)<0 then
  167. Exit;
  168. n:= ifc.ifc_len;
  169. i:=0;
  170. While (Not Result) and (I<N) do
  171. begin
  172. ifp:=@PByte(ifc.ifcu_buf)[i];
  173. move(ifp^.ifr_ifrn.ifrn_name,ifr.ifr_ifrn.ifrn_name,IF_NAMESIZE);
  174. if (fpioctl(sd, SIOCGIFHWADDR, @ifr) >= 0) then
  175. begin
  176. P:=Pchar(@ifr.ifru_hwaddr.sa_data);
  177. Result:=(p[0]<>#0) or (p[1]<>#0) or (p[2]<>#0)
  178. or (p[3]<>#0) or (p[4]<>#0) or (p[5]<>#0);
  179. If Result Then
  180. begin
  181. Move(P^,MacAddr,SizeOf(MacAddr));
  182. MacAddrTried:=2;
  183. // DumpMacAddr;
  184. end;
  185. end;
  186. I:=I+sizeof(tifrec);
  187. end;
  188. Finally
  189. fileClose(sd);
  190. end;
  191. end;
  192. end;
  193. Function GetClock(Var ClockHigh,ClockLow : Cardinal; Var RetClockSeq : Word) : boolean;
  194. Var
  195. TV : TTImeVal;
  196. ClockReg : QWord;
  197. OK : Boolean;
  198. begin
  199. OK:=True;
  200. Repeat
  201. FPGetTimeOfDay(@Tv,Nil);
  202. If (Last.tv_sec=0) and (last.tv_sec=0) then
  203. begin
  204. GetRandomBytes(ClockSeq,SizeOf(ClockSeq));
  205. ClockSeq:=ClockSeq and $1FFF;
  206. last:=TV;
  207. Dec(last.tv_sec);
  208. end;
  209. if (tv.tv_sec<last.tv_sec) or
  210. ((tv.tv_sec=last.tv_sec) and (tv.tv_usec<last.tv_usec)) then
  211. begin
  212. ClockSeq:=(ClockSeq+1) and $1FFF;
  213. Adjustment:=0;
  214. Last:=Tv;
  215. end
  216. else if (tv.tv_sec=last.tv_sec) and (tv.tv_usec=last.tv_usec) then
  217. begin
  218. If Adjustment>=MAX_ADJUSTMENT then
  219. OK:=False
  220. else
  221. inc(AdjustMent);
  222. end
  223. else
  224. begin
  225. AdjustMent:=0;
  226. Last:=tv;
  227. end;
  228. Until OK;
  229. ClockReg:=tv.tv_usec*10+adjustment;
  230. Inc(ClockReg,tv.tv_sec*10000000);
  231. Inc(ClockReg,($01B21DD2 shl 32) + $13814000);
  232. ClockHigh :=Hi(ClockReg);
  233. ClockLow :=Lo(ClockReg);
  234. RetClockSeq :=ClockSeq;
  235. Result :=True;
  236. end;
  237. Procedure UUIDPack(Const UU : TUUID; Var GUID : TGUID);
  238. Var
  239. tmp : Cardinal;
  240. P : PByte;
  241. begin
  242. P:=@GUID;
  243. tmp:=uu.time_low;
  244. P[3]:=tmp and $FF;
  245. tmp:=tmp shr 8;
  246. P[2]:=tmp and $FF;
  247. tmp:=tmp shr 8;
  248. P[1]:=tmp and $FF;
  249. tmp:=tmp shr 8;
  250. P[0]:=tmp and $FF;
  251. tmp:=uu.time_mid;
  252. P[5]:=tmp and $FF;
  253. tmp:=tmp shr 8;
  254. P[4]:=tmp and $FF;
  255. tmp:=uu.time_hi_and_version;
  256. P[7]:=tmp and $FF;
  257. tmp:=tmp shr 8;
  258. P[6]:=tmp and $FF;
  259. tmp:=uu.clock_seq;
  260. P[9]:=tmp and $FF;
  261. tmp:=tmp shr 8;
  262. P[8]:=tmp and $FF;
  263. Move(uu.node,P[10],6);
  264. end;
  265. Procedure DumpMacAddr;
  266. var
  267. I : Integer;
  268. begin
  269. Write('Mac Addr: ');
  270. For i:=1 to 6 do
  271. write(hexstr(MacAddr[i],2),':');
  272. end;
  273. Function CreateMacGUID(Var GUID : TGUID) : Boolean;
  274. Var
  275. UU : TUUId;
  276. ClockMid : Cardinal;
  277. begin
  278. Result:=GetMacAddr;
  279. If Result then
  280. begin
  281. // DumpMacAddr;
  282. // Writeln;
  283. GetClock(ClockMid,uu.time_low,uu.clock_seq);
  284. uu.Clock_seq:=uu.Clock_seq or $8000;
  285. uu.time_mid:=lo(clockMid);
  286. uu.time_hi_and_version:=hi(ClockMid) or $1000;
  287. move(MacAddr,uu.node,sizeof(MacAddr));
  288. UUIDPack(UU,GUID);
  289. end;
  290. end;
  291. Function CreateKernelGUID(Var GUID : TGUID) : Boolean;
  292. Const
  293. UUIDLen = 36;
  294. Var
  295. fd: Longint;
  296. S : String;
  297. begin
  298. fd:=FileOpen(KernelUUID,fmOpenRead);
  299. Result:=(Fd>=0);
  300. if Result then
  301. begin
  302. SetLength(S,UUIDLen);
  303. SetLength(S,FileRead(fd,S[1],UUIDLen));
  304. Result:=(Length(S)=UUIDLen);
  305. If Result then
  306. begin
  307. GUID:=StringToGUID('{'+S+'}');
  308. //Writeln('Kernel ID = ',GuidToString(GUID));
  309. end;
  310. end;
  311. end;
  312. Function CreateGUID(out GUID : TGUID) : Integer;
  313. begin
  314. if PreferKernelUUID then
  315. begin
  316. if not CreateKernelGUID(Guid) then
  317. if not CreateMACGuid(Guid) then
  318. GetRandomBytes(GUID,SizeOf(Guid));
  319. end
  320. else
  321. if not CreateMACGuid(Guid) then
  322. if not CreateKernelGUID(Guid) then
  323. GetRandomBytes(GUID,SizeOf(Guid));
  324. Result:=0;
  325. end;