osmain.inc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Main OS dependant body of the system unit, loosely modelled
  5. after POSIX. *BSD version (Linux version is near identical)
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. const
  13. { Default creation mode for directories and files }
  14. { read/write permission for everyone }
  15. MODE_OPEN = S_IWUSR OR S_IRUSR OR
  16. S_IWGRP OR S_IRGRP OR
  17. S_IWOTH OR S_IROTH;
  18. { read/write search permission for everyone }
  19. MODE_MKDIR = MODE_OPEN OR
  20. S_IXUSR OR S_IXGRP OR S_IXOTH;
  21. {*****************************************************************************
  22. Misc. System Dependent Functions
  23. *****************************************************************************}
  24. procedure System_exit;
  25. begin
  26. Fpexit(cint(ExitCode));
  27. End;
  28. Function ParamCount: Longint;
  29. Begin
  30. Paramcount:=argc-1
  31. End;
  32. function BackPos(c:char; const s: shortstring): integer;
  33. var
  34. i: integer;
  35. Begin
  36. for i:=length(s) downto 0 do
  37. if s[i] = c then break;
  38. if i=0 then
  39. BackPos := 0
  40. else
  41. BackPos := i;
  42. end;
  43. { variable where full path and filename and executable is stored }
  44. { is setup by the startup of the system unit. }
  45. var
  46. execpathstr : shortstring;
  47. function paramstr(l: longint) : string;
  48. var
  49. s: string;
  50. s1: string;
  51. begin
  52. { stricly conforming POSIX applications }
  53. { have the executing filename as argv[0] }
  54. // if l=0 then
  55. // begin
  56. // paramstr := execpathstr;
  57. // end
  58. // else
  59. paramstr:=strpas(argv[l]);
  60. end;
  61. Procedure Randomize;
  62. Begin
  63. randseed:=longint(Fptime(nil));
  64. End;
  65. {*****************************************************************************
  66. Low Level File Routines
  67. *****************************************************************************}
  68. {
  69. The lowlevel file functions should take care of setting the InOutRes to the
  70. correct value if an error has occured, else leave it untouched
  71. }
  72. Function PosixToRunError (PosixErrno : longint) : longint;
  73. {
  74. Convert ErrNo error to the correct Inoutres value
  75. }
  76. begin
  77. if PosixErrNo=0 then { Else it will go through all the cases }
  78. exit(0);
  79. case PosixErrNo of
  80. ESysENFILE,
  81. ESysEMFILE : Inoutres:=4;
  82. ESysENOENT : Inoutres:=2;
  83. ESysEBADF : Inoutres:=6;
  84. ESysENOMEM,
  85. ESysEFAULT : Inoutres:=217;
  86. ESysEINVAL : Inoutres:=218;
  87. ESysEPIPE,
  88. ESysEINTR,
  89. ESysEIO,
  90. ESysEAGAIN,
  91. ESysENOSPC : Inoutres:=101;
  92. ESysENAMETOOLONG : Inoutres := 3;
  93. ESysEROFS,
  94. ESysEEXIST,
  95. ESysENOTEMPTY,
  96. ESysEACCES : Inoutres:=5;
  97. ESysEISDIR : InOutRes:=5;
  98. else
  99. begin
  100. InOutRes := Integer(PosixErrno);
  101. end;
  102. end;
  103. PosixToRunError:=InOutRes;
  104. end;
  105. Function Errno2InoutRes : longint;
  106. begin
  107. Errno2InoutRes:=PosixToRunError(getErrno);
  108. InoutRes:=Errno2InoutRes;
  109. end;
  110. Procedure Do_Close(Handle:thandle);
  111. Begin
  112. Fpclose(cint(Handle));
  113. End;
  114. Procedure Do_Erase(p:pchar);
  115. var
  116. fileinfo : stat;
  117. Begin
  118. { verify if the filename is actually a directory }
  119. { if so return error and do nothing, as defined }
  120. { by POSIX }
  121. if Fpstat(p,fileinfo)<0 then
  122. begin
  123. Errno2Inoutres;
  124. exit;
  125. end;
  126. if FpS_ISDIR(fileinfo.st_mode) then
  127. begin
  128. InOutRes := 2;
  129. exit;
  130. end;
  131. if Fpunlink(p)<0 then
  132. Errno2Inoutres
  133. Else
  134. InOutRes:=0;
  135. End;
  136. { truncate at a given position }
  137. procedure do_truncate (handle:thandle;fpos:longint);
  138. begin
  139. { should be simulated in cases where it is not }
  140. { available. }
  141. If Fpftruncate(handle,fpos)<0 Then
  142. Errno2Inoutres
  143. Else
  144. InOutRes:=0;
  145. end;
  146. Procedure Do_Rename(p1,p2:pchar);
  147. Begin
  148. If Fprename(p1,p2)<0 Then
  149. Errno2Inoutres
  150. Else
  151. InOutRes:=0;
  152. End;
  153. Function Do_Write(Handle:thandle;Addr:Pointer;Len:Longint):longint;
  154. var j : cint;
  155. Begin
  156. repeat
  157. Do_Write:=Fpwrite(Handle,addr,len);
  158. j:=geterrno;
  159. until (do_write<>-1) or ((j<>ESysEINTR) and (j<>ESysEAgain));
  160. If Do_Write<0 Then
  161. Begin
  162. Errno2InOutRes;
  163. Do_Write:=0;
  164. End
  165. else
  166. InOutRes:=0;
  167. End;
  168. Function Do_Read(Handle:thandle;Addr:Pointer;Len:Longint):Longint;
  169. var j:cint;
  170. Begin
  171. repeat
  172. Do_Read:=Fpread(Handle,addr,len);
  173. j:=geterrno;
  174. until (do_read<>-1) or ((j<>ESysEINTR) and (j<>ESysEAgain));
  175. If Do_Read<0 Then
  176. Begin
  177. Errno2InOutRes;
  178. Do_Read:=0;
  179. End
  180. else
  181. InOutRes:=0;
  182. End;
  183. function Do_FilePos(Handle: thandle):longint;
  184. Begin
  185. do_FilePos:=Fplseek(Handle, 0, SEEK_CUR);
  186. If Do_FilePos<0 Then
  187. Errno2InOutRes
  188. else
  189. InOutRes:=0;
  190. End;
  191. Procedure Do_Seek(Handle:thandle;Pos:Longint);
  192. Begin
  193. If Fplseek(Handle, pos, SEEK_SET)<0 Then
  194. Errno2Inoutres
  195. Else
  196. InOutRes:=0;
  197. End;
  198. Function Do_SeekEnd(Handle:thandle): Longint;
  199. begin
  200. Do_SeekEnd:=Fplseek(Handle,0,SEEK_END);
  201. If Do_SeekEnd<0 Then
  202. Errno2Inoutres
  203. Else
  204. InOutRes:=0;
  205. end;
  206. Function Do_FileSize(Handle:thandle): Longint;
  207. var
  208. Info : Stat;
  209. Ret : Longint;
  210. Begin
  211. Ret:=Fpfstat(handle,info);
  212. If Ret=0 Then
  213. Do_FileSize:=Info.st_size
  214. else
  215. Do_FileSize:=0;
  216. If Ret<0 Then
  217. Errno2InOutRes
  218. Else
  219. InOutRes:=0;
  220. End;
  221. Procedure Do_Open(var f;p:pchar;flags:longint);
  222. {
  223. FileRec and textrec have both Handle and mode as the first items so
  224. they could use the same routine for opening/creating.
  225. when (flags and $100) the file will be append
  226. when (flags and $1000) the file will be truncate/rewritten
  227. when (flags and $10000) there is no check for close (needed for textfiles)
  228. }
  229. var
  230. oflags : cint;
  231. Begin
  232. { close first if opened }
  233. if ((flags and $10000)=0) then
  234. begin
  235. case FileRec(f).mode of
  236. fminput,fmoutput,fminout : Do_Close(FileRec(f).Handle);
  237. fmclosed : ;
  238. else
  239. begin
  240. inoutres:=102; {not assigned}
  241. exit;
  242. end;
  243. end;
  244. end;
  245. { reset file Handle }
  246. FileRec(f).Handle:=UnusedHandle;
  247. { We do the conversion of filemodes here, concentrated on 1 place }
  248. case (flags and 3) of
  249. 0 : begin
  250. oflags :=O_RDONLY;
  251. FileRec(f).mode:=fminput;
  252. end;
  253. 1 : begin
  254. oflags :=O_WRONLY;
  255. FileRec(f).mode:=fmoutput;
  256. end;
  257. 2 : begin
  258. oflags :=O_RDWR;
  259. FileRec(f).mode:=fminout;
  260. end;
  261. end;
  262. if (flags and $1000)=$1000 then
  263. oflags:=oflags or (O_CREAT or O_TRUNC)
  264. else
  265. if (flags and $100)=$100 then
  266. oflags:=oflags or (O_APPEND);
  267. { empty name is special }
  268. if p[0]=#0 then
  269. begin
  270. case FileRec(f).mode of
  271. fminput :
  272. FileRec(f).Handle:=StdInputHandle;
  273. fminout, { this is set by rewrite }
  274. fmoutput :
  275. FileRec(f).Handle:=StdOutputHandle;
  276. fmappend :
  277. begin
  278. FileRec(f).Handle:=StdOutputHandle;
  279. FileRec(f).mode:=fmoutput; {fool fmappend}
  280. end;
  281. end;
  282. exit;
  283. end;
  284. { real open call }
  285. FileRec(f).Handle:=Fpopen(p,oflags,MODE_OPEN);
  286. if (FileRec(f).Handle<0) and
  287. (getErrNo=ESysEROFS) and ((OFlags and O_RDWR)<>0) then
  288. begin
  289. Oflags:=Oflags and not(O_RDWR);
  290. FileRec(f).Handle:=Fpopen(p,oflags,MODE_OPEN);
  291. end;
  292. If Filerec(f).Handle<0 Then
  293. Errno2Inoutres
  294. else
  295. InOutRes:=0;
  296. End;
  297. {*****************************************************************************
  298. Directory Handling
  299. *****************************************************************************}
  300. Procedure MkDir(Const s: String);[IOCheck];
  301. Var
  302. Buffer: Array[0..255] of Char;
  303. Begin
  304. If (s='') or (InOutRes <> 0) then
  305. exit;
  306. Move(s[1], Buffer, Length(s));
  307. Buffer[Length(s)] := #0;
  308. If Fpmkdir(@buffer, MODE_MKDIR)<0 Then
  309. Errno2Inoutres
  310. Else
  311. InOutRes:=0;
  312. End;
  313. Procedure RmDir(Const s: String);[IOCheck];
  314. Var
  315. Buffer: Array[0..255] of Char;
  316. Begin
  317. if (s = '.') then
  318. InOutRes := 16;
  319. If (s='') or (InOutRes <> 0) then
  320. exit;
  321. Move(s[1], Buffer, Length(s));
  322. Buffer[Length(s)] := #0;
  323. If Fprmdir(@buffer)<0 Then
  324. Errno2Inoutres
  325. Else
  326. InOutRes:=0;
  327. End;
  328. Procedure ChDir(Const s: String);[IOCheck];
  329. Var
  330. Buffer: Array[0..255] of Char;
  331. Begin
  332. If (s='') or (InOutRes <> 0) then
  333. exit;
  334. Move(s[1], Buffer, Length(s));
  335. Buffer[Length(s)] := #0;
  336. If Fpchdir(@buffer)<0 Then
  337. Errno2Inoutres
  338. Else
  339. InOutRes:=0;
  340. { file not exists is path not found under tp7 }
  341. if InOutRes=2 then
  342. InOutRes:=3;
  343. End;
  344. { // $define usegetcwd}
  345. procedure getdir(drivenr : byte;var dir : shortstring);
  346. var
  347. {$ifndef usegetcwd}
  348. cwdinfo : stat;
  349. rootinfo : stat;
  350. thedir,dummy : string[255];
  351. dirstream : pdir;
  352. d : pdirent;
  353. name : string[255];
  354. thisdir : stat;
  355. {$endif}
  356. tmp : string[255];
  357. begin
  358. {$ifdef usegetcwd}
  359. Fpgetcwd(@tmp[1],4096);
  360. dir:=tmp;
  361. {$else}
  362. dir:='';
  363. thedir:='';
  364. dummy:='';
  365. { get root directory information }
  366. tmp := '/'+#0;
  367. if Fpstat(@tmp[1],rootinfo)<0 then
  368. Exit;
  369. repeat
  370. tmp := dummy+'.'+#0;
  371. { get current directory information }
  372. if Fpstat(@tmp[1],cwdinfo)<0 then
  373. Exit;
  374. tmp:=dummy+'..'+#0;
  375. { open directory stream }
  376. { try to find the current inode number of the cwd }
  377. dirstream:=Fpopendir(@tmp[1]);
  378. if dirstream=nil then
  379. exit;
  380. repeat
  381. name:='';
  382. d:=Fpreaddir(dirstream);
  383. { no more entries to read ... }
  384. if not assigned(d) then
  385. break;
  386. tmp:=dummy+'../'+strpas(d^.d_name) + #0;
  387. if (Fpstat(@tmp[1],thisdir)=0) then
  388. begin
  389. { found the entry for this directory name }
  390. if (cwdinfo.st_dev=thisdir.st_dev) and (cwdinfo.st_ino=thisdir.st_ino) then
  391. begin
  392. { are the filenames of type '.' or '..' ? }
  393. { then do not set the name. }
  394. if (not ((d^.d_name[0]='.') and ((d^.d_name[1]=#0) or
  395. ((d^.d_name[1]='.') and (d^.d_name[2]=#0))))) then
  396. name:='/'+strpas(d^.d_name);
  397. end;
  398. end;
  399. until (name<>'');
  400. if Fpclosedir(dirstream)<0 then
  401. Exit;
  402. thedir:=name+thedir;
  403. dummy:=dummy+'../';
  404. if ((cwdinfo.st_dev=rootinfo.st_dev) and (cwdinfo.st_ino=rootinfo.st_ino)) then
  405. begin
  406. if thedir='' then
  407. dir:='/'
  408. else
  409. dir:=thedir;
  410. exit;
  411. end;
  412. until false;
  413. {$endif}
  414. end;
  415. {*****************************************************************************
  416. SystemUnit Initialization
  417. *****************************************************************************}
  418. function reenable_signal(sig : longint) : boolean;
  419. var
  420. e,oe : TSigSet;
  421. i,j : byte;
  422. begin
  423. fillchar(e,sizeof(e),#0);
  424. fillchar(oe,sizeof(oe),#0);
  425. { set is 1 based PM }
  426. dec(sig);
  427. i:=sig mod 32;
  428. j:=sig div 32;
  429. e[j]:=1 shl i;
  430. fpsigprocmask(SIG_UNBLOCK,@e,@oe);
  431. reenable_signal:=geterrno=0;
  432. end;
  433. {$i sighnd.inc}
  434. var
  435. act: SigActionRec;
  436. Procedure InstallSignals;
  437. var
  438. oldact: SigActionRec;
  439. begin
  440. { Initialize the sigaction structure }
  441. { all flags and information set to zero }
  442. FillChar(act, sizeof(SigActionRec),0);
  443. { initialize handler }
  444. act.sa_handler :=@SignalToRunError;
  445. act.sa_flags:=SA_SIGINFO;
  446. FpSigAction(SIGFPE,act,oldact);
  447. FpSigAction(SIGSEGV,act,oldact);
  448. FpSigAction(SIGBUS,act,oldact);
  449. FpSigAction(SIGILL,act,oldact);
  450. end;
  451. procedure SetupCmdLine;
  452. var
  453. bufsize,
  454. len,j,
  455. size,i : longint;
  456. found : boolean;
  457. buf : pchar;
  458. procedure AddBuf;
  459. begin
  460. reallocmem(cmdline,size+bufsize);
  461. move(buf^,cmdline[size],bufsize);
  462. inc(size,bufsize);
  463. bufsize:=0;
  464. end;
  465. begin
  466. GetMem(buf,ARG_MAX);
  467. size:=0;
  468. bufsize:=0;
  469. i:=0;
  470. while (i<argc) do
  471. begin
  472. len:=strlen(argv[i]);
  473. if len>ARG_MAX-2 then
  474. len:=ARG_MAX-2;
  475. found:=false;
  476. for j:=1 to len do
  477. if argv[i][j]=' ' then
  478. begin
  479. found:=true;
  480. break;
  481. end;
  482. if bufsize+len>=ARG_MAX-2 then
  483. AddBuf;
  484. if found then
  485. begin
  486. buf[bufsize]:='"';
  487. inc(bufsize);
  488. end;
  489. move(argv[i]^,buf[bufsize],len);
  490. inc(bufsize,len);
  491. if found then
  492. begin
  493. buf[bufsize]:='"';
  494. inc(bufsize);
  495. end;
  496. if i<argc then
  497. buf[bufsize]:=' '
  498. else
  499. buf[bufsize]:=#0;
  500. inc(bufsize);
  501. inc(i);
  502. end;
  503. AddBuf;
  504. FreeMem(buf,ARG_MAX);
  505. end;
  506. {
  507. $Log$
  508. Revision 1.16 2004-10-25 15:38:59 peter
  509. * compiler defined HEAP and HEAPSIZE removed
  510. Revision 1.15 2004/07/17 15:20:55 jonas
  511. * don't use O_CREATE when opening a file for appending (fixes tw1744)
  512. Revision 1.14 2004/05/16 18:51:20 peter
  513. * use thandle in do_*
  514. Revision 1.13 2004/04/22 21:10:56 peter
  515. * do_read/do_write addr argument changed to pointer
  516. Revision 1.12 2004/01/06 15:42:05 marco
  517. * o_creat added when o_append
  518. Revision 1.11 2004/01/03 14:56:10 marco
  519. * typo fix
  520. Revision 1.10 2004/01/03 12:35:39 marco
  521. * sighnd to separate file, like linux. Some comments removed
  522. Revision 1.9 2003/12/30 12:26:21 marco
  523. * FPC_USE_LIBC
  524. Revision 1.8 2003/12/21 20:31:50 peter
  525. * fix getdir when directory contains files that give EACCESS
  526. Revision 1.7 2003/12/14 14:47:02 marco
  527. * fix for repeating 'x' bug
  528. Revision 1.6 2003/11/18 10:12:25 marco
  529. * Small fixes for EAGAIN. bunxfunc only has comments added.
  530. Revision 1.5 2003/10/27 17:12:45 marco
  531. * fixes for signal handling.
  532. Revision 1.4 2003/10/26 17:01:04 marco
  533. * moved sigprocmask to system
  534. Revision 1.3 2003/09/27 13:04:58 peter
  535. * fpISxxx renamed
  536. Revision 1.2 2003/05/29 20:54:09 marco
  537. * progname fix.
  538. Revision 1.1 2003/01/05 19:01:28 marco
  539. * FreeBSD compiles now with baseunix mods.
  540. }