sysutils.pp 14 KB

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