sysutils.pp 15 KB

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