sysutils.pp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. {
  2. $Id$
  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. unit sysutils;
  14. interface
  15. {$MODE objfpc}
  16. { force ansistrings }
  17. {$H+}
  18. {$DEFINE HAS_SLEEP}
  19. uses
  20. Unix,errors,sysconst;
  21. { Include platform independent interface part }
  22. {$i sysutilh.inc}
  23. implementation
  24. Uses UnixUtil,Baseunix;
  25. { Include platform independent implementation part }
  26. {$i sysutils.inc}
  27. {****************************************************************************
  28. File Functions
  29. ****************************************************************************}
  30. Function FileOpen (Const FileName : string; Mode : Integer) : Longint;
  31. Var LinuxFlags : longint;
  32. BEGIN
  33. LinuxFlags:=0;
  34. Case (Mode and 3) of
  35. 0 : LinuxFlags:=LinuxFlags or O_RdOnly;
  36. 1 : LinuxFlags:=LinuxFlags or O_WrOnly;
  37. 2 : LinuxFlags:=LinuxFlags or O_RdWr;
  38. end;
  39. FileOpen:=fpOpen (FileName,LinuxFlags);
  40. //!! We need to set locking based on Mode !!
  41. end;
  42. Function FileCreate (Const FileName : String) : Longint;
  43. begin
  44. FileCreate:=fpOpen(FileName,O_RdWr or O_Creat or O_Trunc);
  45. end;
  46. Function FileCreate (Const FileName : String;Mode : Longint) : Longint;
  47. Var LinuxFlags : longint;
  48. BEGIN
  49. LinuxFlags:=0;
  50. Case (Mode and 3) of
  51. 0 : LinuxFlags:=LinuxFlags or O_RdOnly;
  52. 1 : LinuxFlags:=LinuxFlags or O_WrOnly;
  53. 2 : LinuxFlags:=LinuxFlags or O_RdWr;
  54. end;
  55. FileCreate:=fpOpen(FileName,LinuxFlags or O_Creat or O_Trunc);
  56. end;
  57. Function FileRead (Handle : Longint; Var Buffer; Count : longint) : Longint;
  58. begin
  59. FileRead:=fpRead (Handle,Buffer,Count);
  60. end;
  61. Function FileWrite (Handle : Longint; const Buffer; Count : Longint) : Longint;
  62. begin
  63. FileWrite:=fpWrite (Handle,Buffer,Count);
  64. end;
  65. Function FileSeek (Handle,FOffset,Origin : Longint) : Longint;
  66. begin
  67. FileSeek:=fplSeek (Handle,FOffset,Origin);
  68. end;
  69. Function FileSeek (Handle : Longint; FOffset,Origin : Int64) : Int64;
  70. begin
  71. {$warning need to add 64bit call }
  72. FileSeek:=fplSeek (Handle,FOffset,Origin);
  73. end;
  74. Procedure FileClose (Handle : Longint);
  75. begin
  76. fpclose(Handle);
  77. end;
  78. Function FileTruncate (Handle,Size: Longint) : boolean;
  79. begin
  80. FileTruncate:=fpftruncate(Handle,Size)>=0;
  81. end;
  82. Function FileAge (Const FileName : String): Longint;
  83. Var Info : Stat;
  84. Y,M,D,hh,mm,ss : word;
  85. begin
  86. If fpstat (FileName,Info)<0 then
  87. exit(-1)
  88. else
  89. begin
  90. EpochToLocal(info.st_mtime,y,m,d,hh,mm,ss);
  91. Result:=DateTimeToFileDate(EncodeDate(y,m,d)+EncodeTime(hh,mm,ss,0));
  92. end;
  93. end;
  94. Function FileExists (Const FileName : String) : Boolean;
  95. Var Info : Stat;
  96. begin
  97. FileExists:=fpstat(filename,Info)>=0;
  98. end;
  99. Function DirectoryExists (Const Directory : String) : Boolean;
  100. Var Info : Stat;
  101. begin
  102. DirectoryExists:=(fpstat(Directory,Info)>=0) and fpS_ISDIR(Info.st_mode);
  103. end;
  104. Function LinuxToWinAttr (FN : Pchar; Const Info : Stat) : Longint;
  105. begin
  106. Result:=faArchive;
  107. If fpS_ISDIR(Info.st_mode) then
  108. Result:=Result or faDirectory;
  109. If (FN[0]='.') and (not (FN[1] in [#0,'.'])) then
  110. Result:=Result or faHidden;
  111. If (Info.st_Mode and S_IWUSR)=0 Then
  112. Result:=Result or faReadOnly;
  113. If fpS_ISSOCK(Info.st_mode) or fpS_ISBLK(Info.st_mode) or fpS_ISCHR(Info.st_mode) or fpS_ISFIFO(Info.st_mode) Then
  114. Result:=Result or faSysFile;
  115. end;
  116. {
  117. GlobToSearch takes a glob entry, stats the file.
  118. The glob entry is removed.
  119. If FileAttributes match, the entry is reused
  120. }
  121. Type
  122. TGlobSearchRec = Record
  123. Path : String;
  124. GlobHandle : PGlob;
  125. end;
  126. PGlobSearchRec = ^TGlobSearchRec;
  127. Function GlobToTSearchRec (Var Info : TSearchRec) : Boolean;
  128. Var SInfo : Stat;
  129. p : Pglob;
  130. GlobSearchRec : PGlobSearchrec;
  131. begin
  132. GlobSearchRec:=PGlobSearchrec(Info.FindHandle);
  133. P:=GlobSearchRec^.GlobHandle;
  134. Result:=P<>Nil;
  135. If Result then
  136. begin
  137. GlobSearchRec^.GlobHandle:=P^.Next;
  138. Result:=Fpstat(GlobSearchRec^.Path+StrPas(p^.name),SInfo)>=0;
  139. If Result then
  140. begin
  141. Info.Attr:=LinuxToWinAttr(p^.name,SInfo);
  142. Result:=(Info.ExcludeAttr and Info.Attr)=0;
  143. If Result Then
  144. With Info do
  145. begin
  146. Attr:=Info.Attr;
  147. If P^.Name<>Nil then
  148. Name:=strpas(p^.name);
  149. Time:=Sinfo.st_mtime;
  150. Size:=Sinfo.st_Size;
  151. end;
  152. end;
  153. P^.Next:=Nil;
  154. GlobFree(P);
  155. end;
  156. end;
  157. Function DoFind(Var Rslt : TSearchRec) : Longint;
  158. Var
  159. GlobSearchRec : PGlobSearchRec;
  160. begin
  161. Result:=-1;
  162. GlobSearchRec:=PGlobSearchRec(Rslt.FindHandle);
  163. If (GlobSearchRec^.GlobHandle<>Nil) then
  164. While (GlobSearchRec^.GlobHandle<>Nil) and not (Result=0) do
  165. If GlobToTSearchRec(Rslt) Then Result:=0;
  166. end;
  167. Function FindFirst (Const Path : String; Attr : Longint; Var Rslt : TSearchRec) : Longint;
  168. Var
  169. GlobSearchRec : PGlobSearchRec;
  170. begin
  171. New(GlobSearchRec);
  172. GlobSearchRec^.Path:=ExpandFileName(ExtractFilePath(Path));
  173. GlobSearchRec^.GlobHandle:=Glob(Path);
  174. Rslt.ExcludeAttr:=Not Attr; //!! Not correct !!
  175. Rslt.FindHandle:=Longint(GlobSearchRec);
  176. Result:=DoFind (Rslt);
  177. end;
  178. Function FindNext (Var Rslt : TSearchRec) : Longint;
  179. begin
  180. Result:=DoFind (Rslt);
  181. end;
  182. Procedure FindClose (Var F : TSearchrec);
  183. Var
  184. GlobSearchRec : PGlobSearchRec;
  185. begin
  186. GlobSearchRec:=PGlobSearchRec(F.FindHandle);
  187. GlobFree (GlobSearchRec^.GlobHandle);
  188. Dispose(GlobSearchRec);
  189. end;
  190. Function FileGetDate (Handle : Longint) : Longint;
  191. Var Info : Stat;
  192. begin
  193. If (fpFStat(Handle,Info))<0 then
  194. Result:=-1
  195. else
  196. Result:=Info.st_Mtime;
  197. end;
  198. Function FileSetDate (Handle,Age : Longint) : Longint;
  199. begin
  200. // Impossible under Linux from FileHandle !!
  201. FileSetDate:=-1;
  202. end;
  203. Function FileGetAttr (Const FileName : String) : Longint;
  204. Var Info : Stat;
  205. begin
  206. If FpStat (FileName,Info)<0 then
  207. Result:=-1
  208. Else
  209. Result:=LinuxToWinAttr(Pchar(FileName),Info);
  210. end;
  211. Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
  212. begin
  213. Result:=-1;
  214. end;
  215. Function DeleteFile (Const FileName : String) : Boolean;
  216. begin
  217. Result:=fpUnLink (FileName)>=0;
  218. end;
  219. Function RenameFile (Const OldName, NewName : String) : Boolean;
  220. begin
  221. RenameFile:=BaseUnix.FpRename(OldNAme,NewName)>=0;
  222. end;
  223. {****************************************************************************
  224. Disk Functions
  225. ****************************************************************************}
  226. {
  227. The Diskfree and Disksize functions need a file on the specified drive, since this
  228. is required for the statfs system call.
  229. These filenames are set in drivestr[0..26], and have been preset to :
  230. 0 - '.' (default drive - hence current dir is ok.)
  231. 1 - '/fd0/.' (floppy drive 1 - should be adapted to local system )
  232. 2 - '/fd1/.' (floppy drive 2 - should be adapted to local system )
  233. 3 - '/' (C: equivalent of dos is the root partition)
  234. 4..26 (can be set by you're own applications)
  235. ! Use AddDisk() to Add new drives !
  236. They both return -1 when a failure occurs.
  237. }
  238. Const
  239. FixDriveStr : array[0..3] of pchar=(
  240. '.',
  241. '/fd0/.',
  242. '/fd1/.',
  243. '/.'
  244. );
  245. var
  246. Drives : byte;
  247. DriveStr : array[4..26] of pchar;
  248. Procedure AddDisk(const path:string);
  249. begin
  250. if not (DriveStr[Drives]=nil) then
  251. FreeMem(DriveStr[Drives],StrLen(DriveStr[Drives])+1);
  252. GetMem(DriveStr[Drives],length(Path)+1);
  253. StrPCopy(DriveStr[Drives],path);
  254. inc(Drives);
  255. if Drives>26 then
  256. Drives:=4;
  257. end;
  258. Function DiskFree(Drive: Byte): int64;
  259. var
  260. fs : tstatfs;
  261. Begin
  262. if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and (statfs(StrPas(fixdrivestr[drive]),fs)<>-1)) or
  263. ((not (drivestr[Drive]=nil)) and (statfs(StrPas(drivestr[drive]),fs)<>-1)) then
  264. Diskfree:=int64(fs.bavail)*int64(fs.bsize)
  265. else
  266. Diskfree:=-1;
  267. End;
  268. Function DiskSize(Drive: Byte): int64;
  269. var
  270. fs : tstatfs;
  271. Begin
  272. if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and (statfs(StrPas(fixdrivestr[drive]),fs)<>-1)) or
  273. ((not (drivestr[Drive]=nil)) and (statfs(StrPas(drivestr[drive]),fs)<>-1)) then
  274. DiskSize:=int64(fs.blocks)*int64(fs.bsize)
  275. else
  276. DiskSize:=-1;
  277. End;
  278. Function GetCurrentDir : String;
  279. begin
  280. GetDir (0,Result);
  281. end;
  282. Function SetCurrentDir (Const NewDir : String) : Boolean;
  283. begin
  284. {$I-}
  285. ChDir(NewDir);
  286. {$I+}
  287. result := (IOResult = 0);
  288. end;
  289. Function CreateDir (Const NewDir : String) : Boolean;
  290. begin
  291. {$I-}
  292. MkDir(NewDir);
  293. {$I+}
  294. result := (IOResult = 0);
  295. end;
  296. Function RemoveDir (Const Dir : String) : Boolean;
  297. begin
  298. {$I-}
  299. RmDir(Dir);
  300. {$I+}
  301. result := (IOResult = 0);
  302. end;
  303. {****************************************************************************
  304. Misc Functions
  305. ****************************************************************************}
  306. procedure Beep;
  307. begin
  308. end;
  309. {****************************************************************************
  310. Locale Functions
  311. ****************************************************************************}
  312. Procedure GetLocalTime(var SystemTime: TSystemTime);
  313. begin
  314. Unix.GetTime(SystemTime.Hour, SystemTime.Minute, SystemTime.Second);
  315. Unix.GetDate(SystemTime.Year, SystemTime.Month, SystemTime.Day);
  316. SystemTime.MilliSecond := 0;
  317. end ;
  318. Procedure InitAnsi;
  319. Var
  320. i : longint;
  321. begin
  322. { Fill table entries 0 to 127 }
  323. for i := 0 to 96 do
  324. UpperCaseTable[i] := chr(i);
  325. for i := 97 to 122 do
  326. UpperCaseTable[i] := chr(i - 32);
  327. for i := 123 to 191 do
  328. UpperCaseTable[i] := chr(i);
  329. Move (CPISO88591UCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  330. for i := 0 to 64 do
  331. LowerCaseTable[i] := chr(i);
  332. for i := 65 to 90 do
  333. LowerCaseTable[i] := chr(i + 32);
  334. for i := 91 to 191 do
  335. LowerCaseTable[i] := chr(i);
  336. Move (CPISO88591LCT,LowerCaseTable[192],SizeOf(CPISO88591UCT));
  337. end;
  338. Procedure InitInternational;
  339. begin
  340. InitAnsi;
  341. end;
  342. function SysErrorMessage(ErrorCode: Integer): String;
  343. begin
  344. Result:=StrError(ErrorCode);
  345. end;
  346. {****************************************************************************
  347. OS utility functions
  348. ****************************************************************************}
  349. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  350. begin
  351. Result:=StrPas(BaseUnix.FPGetenv(PChar(EnvVar)));
  352. end;
  353. function ExecuteProcess(Const Path: AnsiString; Const ComLine: AnsiString):integer;
  354. var
  355. pid : longint;
  356. err : longint;
  357. e : EOSError;
  358. CommandLine: AnsiString;
  359. Begin
  360. { always surround the name of the application by quotes
  361. so that long filenames will always be accepted. But don't
  362. do it if there are already double quotes!
  363. }
  364. if Pos ('"', Path) = 0 then
  365. CommandLine := '"' + Path + '"'
  366. else
  367. CommandLine := Path;
  368. if ComLine <> '' then
  369. CommandLine := Commandline + ' ' + ComLine;
  370. pid:=fpFork;
  371. if pid=0 then
  372. begin
  373. {The child does the actual exec, and then exits}
  374. Execl(CommandLine);
  375. { If the execve fails, we return an exitvalue of 127, to let it be known}
  376. fpExit(127);
  377. end
  378. else
  379. if pid=-1 then {Fork failed}
  380. begin
  381. e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,-1]);
  382. e.ErrorCode:=-1;
  383. raise e;
  384. end;
  385. { We're in the parent, let's wait. }
  386. result:=WaitProcess(pid); // WaitPid and result-convert
  387. if (result>=0) and (result<>127) then
  388. result:=0
  389. else
  390. begin
  391. e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,result]);
  392. e.ErrorCode:=result;
  393. raise e;
  394. end;
  395. End;
  396. procedure Sleep(milliseconds: Cardinal);
  397. Var
  398. fd : Integer;
  399. fds : TfdSet;
  400. timeout : TimeVal;
  401. begin
  402. fd:=FileOpen('/dev/null',fmOpenRead);
  403. If Not(Fd<0) then
  404. begin
  405. fpfd_zero(fds);
  406. fpfd_set(0,fds);
  407. timeout.tv_sec:=Milliseconds div 1000;
  408. timeout.tv_usec:=(Milliseconds mod 1000) * 1000;
  409. fpSelect(1,Nil,Nil,@fds,@timeout);
  410. end;
  411. end;
  412. {****************************************************************************
  413. Initialization code
  414. ****************************************************************************}
  415. Initialization
  416. InitExceptions; { Initialize exceptions. OS independent }
  417. InitInternational; { Initialize internationalization settings }
  418. Finalization
  419. DoneExceptions;
  420. end.
  421. {
  422. $Log$
  423. Revision 1.31 2004-01-20 23:13:53 hajny
  424. * ExecuteProcess fixes, ProcessID and ThreadID added
  425. Revision 1.30 2004/01/10 17:34:36 michael
  426. + Implemented sleep() on Unix.
  427. Revision 1.29 2004/01/05 22:42:35 florian
  428. * compilation error fixed
  429. Revision 1.28 2004/01/05 22:37:15 florian
  430. * changed sysutils.exec to ExecuteProcess
  431. Revision 1.27 2004/01/03 09:09:11 marco
  432. * Unix exec(ansistring)
  433. Revision 1.26 2003/11/26 20:35:14 michael
  434. + Some fixes to have everything compile again
  435. Revision 1.25 2003/11/17 10:05:51 marco
  436. * threads for FreeBSD. Not working tho
  437. Revision 1.24 2003/10/25 23:43:59 hajny
  438. * THandle in sysutils common using System.THandle
  439. Revision 1.23 2003/10/07 08:28:49 marco
  440. * fix from Vincent to casetables
  441. Revision 1.22 2003/09/27 12:51:33 peter
  442. * fpISxxx macros renamed to C compliant fpS_ISxxx
  443. Revision 1.21 2003/09/17 19:07:44 marco
  444. * more fixes for Unix<->unixutil
  445. Revision 1.20 2003/09/17 12:41:31 marco
  446. * Uses more baseunix, less unix now
  447. Revision 1.19 2003/09/14 20:15:01 marco
  448. * Unix reform stage two. Remove all calls from Unix that exist in Baseunix.
  449. Revision 1.18 2003/04/01 15:57:41 peter
  450. * made THandle platform dependent and unique type
  451. Revision 1.17 2003/03/30 10:38:00 armin
  452. * corrected typo in DirectoryExists
  453. Revision 1.16 2003/03/29 18:21:42 hajny
  454. * DirectoryExists declaration changed to that one from fixes branch
  455. Revision 1.15 2003/03/28 19:06:59 peter
  456. * directoryexists added
  457. Revision 1.14 2003/01/03 20:41:04 peter
  458. * FileCreate(string,mode) overload added
  459. Revision 1.13 2002/09/07 16:01:28 peter
  460. * old logs removed and tabs fixed
  461. Revision 1.12 2002/01/25 16:23:03 peter
  462. * merged filesearch() fix
  463. }