sysposix.inc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. POSIX Interface to the system unit
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This is the core of the system unit *nix systems (now FreeBSD
  8. and Unix).
  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. { Default creation mode for directories and files }
  15. { read/write permission for everyone }
  16. MODE_OPEN = S_IWUSR OR S_IRUSR OR
  17. S_IWGRP OR S_IRGRP OR
  18. S_IWOTH OR S_IROTH;
  19. { read/write search permission for everyone }
  20. MODE_MKDIR = MODE_OPEN OR
  21. S_IXUSR OR S_IXGRP OR S_IXOTH;
  22. {*****************************************************************************
  23. Stack check code
  24. *****************************************************************************}
  25. {
  26. {$IFOPT S+}
  27. {$DEFINE STACKCHECK}
  28. {$ENDIF}
  29. {$S-}
  30. procedure int_stackcheck(stack_size:longint);[public,alias:'FPC_STACKCHECK'];
  31. var
  32. c: cardinal;
  33. begin
  34. c := cardinal(Sptr) - cardinal(stack_size) - STACK_MARGIN;
  35. if (c <= cardinal(StackBottom)) then
  36. HandleError(202);
  37. end;
  38. {$IFDEF STACKCHECK}
  39. {$S+}
  40. {$ENDIF}
  41. {$UNDEF STACKCHECK}
  42. }
  43. {*****************************************************************************
  44. Misc. System Dependent Functions
  45. *****************************************************************************}
  46. procedure System_exit;
  47. begin
  48. sys_exit(cint(ExitCode));
  49. End;
  50. Function ParamCount: Longint;
  51. Begin
  52. Paramcount:=argc-1
  53. End;
  54. function BackPos(c:char; const s: shortstring): integer;
  55. var
  56. i: integer;
  57. Begin
  58. for i:=length(s) downto 0 do
  59. if s[i] = c then break;
  60. if i=0 then
  61. BackPos := 0
  62. else
  63. BackPos := i;
  64. end;
  65. { variable where full path and filename and executable is stored }
  66. { is setup by the startup of the system unit. }
  67. var
  68. execpathstr : shortstring;
  69. function paramstr(l: longint) : string;
  70. var
  71. s: string;
  72. s1: string;
  73. begin
  74. { stricly conforming POSIX applications }
  75. { have the executing filename as argv[0] }
  76. if l=0 then
  77. begin
  78. paramstr := execpathstr;
  79. end
  80. else
  81. paramstr:=strpas(argv[l]);
  82. end;
  83. Procedure Randomize;
  84. var
  85. t: time_t;
  86. Begin
  87. randseed:=longint(sys_time(t));
  88. End;
  89. {*****************************************************************************
  90. Heap Management
  91. *****************************************************************************}
  92. var
  93. _HEAP : longint;external name 'HEAP';
  94. _HEAPSIZE : longint;external name 'HEAPSIZE';
  95. {$ifndef SYSTEM_HAS_GETHEAPSTART}
  96. function getheapstart:pointer;
  97. begin
  98. getheapstart := @_HEAP;
  99. end;
  100. {$endif}
  101. {$ifndef SYSTEM_HAS_GETHEAPSIZE}
  102. function getheapsize:longint;
  103. begin
  104. getheapsize := _HEAPSIZE;
  105. end;
  106. {$endif}
  107. {*****************************************************************************
  108. Low Level File Routines
  109. *****************************************************************************}
  110. {
  111. The lowlevel file functions should take care of setting the InOutRes to the
  112. correct value if an error has occured, else leave it untouched
  113. }
  114. Function PosixToRunError (PosixErrno : longint) : longint;
  115. {
  116. Convert ErrNo error to the correct Inoutres value
  117. }
  118. begin
  119. if PosixErrNo=0 then { Else it will go through all the cases }
  120. exit;
  121. case PosixErrNo of
  122. Sys_ENFILE,
  123. Sys_EMFILE : Inoutres:=4;
  124. Sys_ENOENT : Inoutres:=2;
  125. Sys_EBADF : Inoutres:=6;
  126. Sys_ENOMEM,
  127. Sys_EFAULT : Inoutres:=217;
  128. Sys_EINVAL : Inoutres:=218;
  129. Sys_EPIPE,
  130. Sys_EINTR,
  131. Sys_EIO,
  132. Sys_EAGAIN,
  133. Sys_ENOSPC : Inoutres:=101;
  134. Sys_ENAMETOOLONG : Inoutres := 3;
  135. Sys_EROFS,
  136. Sys_EEXIST,
  137. Sys_ENOTEMPTY,
  138. Sys_EACCES : Inoutres:=5;
  139. Sys_EISDIR : InOutRes:=5;
  140. else
  141. begin
  142. InOutRes := Integer(PosixErrno);
  143. end;
  144. end;
  145. end;
  146. Function Errno2InoutRes : longint;
  147. begin
  148. Errno2InoutRes:=PosixToRunError(Errno);
  149. InoutRes:=Errno2InoutRes;
  150. end;
  151. Procedure Do_Close(Handle:Longint);
  152. Begin
  153. sys_close(cint(Handle));
  154. End;
  155. Procedure Do_Erase(p:pchar);
  156. var
  157. fileinfo : stat;
  158. Begin
  159. { verify if the filename is actually a directory }
  160. { if so return error and do nothing, as defined }
  161. { by POSIX }
  162. if sys_stat(p,fileinfo)<0 then
  163. begin
  164. Errno2Inoutres;
  165. exit;
  166. end;
  167. if S_ISDIR(fileinfo.st_mode) then
  168. begin
  169. InOutRes := 2;
  170. exit;
  171. end;
  172. sys_unlink(p);
  173. Errno2Inoutres;
  174. End;
  175. { truncate at a given position }
  176. procedure do_truncate (handle,fpos:longint);
  177. begin
  178. { should be simulated in cases where it is not }
  179. { available. }
  180. If sys_ftruncate(handle,fpos)<0 Then
  181. Errno2Inoutres
  182. Else
  183. InOutRes:=0;
  184. end;
  185. Procedure Do_Rename(p1,p2:pchar);
  186. Begin
  187. If sys_rename(p1,p2)<0 Then
  188. Errno2Inoutres
  189. Else
  190. InOutRes:=0;
  191. End;
  192. Function Do_Write(Handle,Addr,Len:Longint):longint;
  193. Begin
  194. repeat
  195. Do_Write:=sys_write(Handle,pchar(addr),len);
  196. until ErrNo<>Sys_EINTR;
  197. If Do_Write<0 Then
  198. Begin
  199. Errno2InOutRes;
  200. Do_Write:=0;
  201. End
  202. else
  203. InOutRes:=0;
  204. End;
  205. Function Do_Read(Handle,Addr,Len:Longint):Longint;
  206. Begin
  207. repeat
  208. Do_Read:=sys_read(Handle,pchar(addr),len);
  209. until ErrNo<>Sys_EINTR;
  210. If Do_Read<0 Then
  211. Begin
  212. Errno2InOutRes;
  213. Do_Read:=0;
  214. End
  215. else
  216. InOutRes:=0;
  217. End;
  218. function Do_FilePos(Handle: Longint):longint;
  219. Begin
  220. do_FilePos:=sys_lseek(Handle, 0, SEEK_CUR);
  221. If Do_FilePos<0 Then
  222. Errno2InOutRes
  223. else
  224. InOutRes:=0;
  225. End;
  226. Procedure Do_Seek(Handle,Pos:Longint);
  227. Begin
  228. If sys_lseek(Handle, pos, SEEK_SET)<0 Then
  229. Errno2Inoutres
  230. Else
  231. InOutRes:=0;
  232. End;
  233. Function Do_SeekEnd(Handle:Longint): Longint;
  234. begin
  235. Do_SeekEnd:=sys_lseek(Handle,0,SEEK_END);
  236. If Do_SeekEnd<0 Then
  237. Errno2Inoutres
  238. Else
  239. InOutRes:=0;
  240. end;
  241. Function Do_FileSize(Handle:Longint): Longint;
  242. var
  243. Info : Stat;
  244. Ret : Longint;
  245. Begin
  246. Ret:=sys_fstat(handle,info);
  247. If Ret=0 Then
  248. Do_FileSize:=Info.st_size
  249. else
  250. Do_FileSize:=0;
  251. If Ret<0 Then
  252. Errno2InOutRes
  253. Else
  254. InOutRes:=0;
  255. End;
  256. Procedure Do_Open(var f;p:pchar;flags:longint);
  257. {
  258. FileRec and textrec have both Handle and mode as the first items so
  259. they could use the same routine for opening/creating.
  260. when (flags and $100) the file will be append
  261. when (flags and $1000) the file will be truncate/rewritten
  262. when (flags and $10000) there is no check for close (needed for textfiles)
  263. }
  264. var
  265. oflags : cint;
  266. Begin
  267. { close first if opened }
  268. if ((flags and $10000)=0) then
  269. begin
  270. case FileRec(f).mode of
  271. fminput,fmoutput,fminout : Do_Close(FileRec(f).Handle);
  272. fmclosed : ;
  273. else
  274. begin
  275. inoutres:=102; {not assigned}
  276. exit;
  277. end;
  278. end;
  279. end;
  280. { reset file Handle }
  281. FileRec(f).Handle:=UnusedHandle;
  282. { We do the conversion of filemodes here, concentrated on 1 place }
  283. case (flags and 3) of
  284. 0 : begin
  285. oflags :=O_RDONLY;
  286. FileRec(f).mode:=fminput;
  287. end;
  288. 1 : begin
  289. oflags :=O_WRONLY;
  290. FileRec(f).mode:=fmoutput;
  291. end;
  292. 2 : begin
  293. oflags :=O_RDWR;
  294. FileRec(f).mode:=fminout;
  295. end;
  296. end;
  297. if (flags and $1000)=$1000 then
  298. oflags:=oflags or (O_CREAT or O_TRUNC)
  299. else
  300. if (flags and $100)=$100 then
  301. oflags:=oflags or (O_APPEND);
  302. { empty name is special }
  303. if p[0]=#0 then
  304. begin
  305. case FileRec(f).mode of
  306. fminput :
  307. FileRec(f).Handle:=StdInputHandle;
  308. fminout, { this is set by rewrite }
  309. fmoutput :
  310. FileRec(f).Handle:=StdOutputHandle;
  311. fmappend :
  312. begin
  313. FileRec(f).Handle:=StdOutputHandle;
  314. FileRec(f).mode:=fmoutput; {fool fmappend}
  315. end;
  316. end;
  317. exit;
  318. end;
  319. { real open call }
  320. FileRec(f).Handle:=sys_open(p,oflags,MODE_OPEN);
  321. if (ErrNo=Sys_EROFS) and ((OFlags and O_RDWR)<>0) then
  322. begin
  323. Oflags:=Oflags and not(O_RDWR);
  324. FileRec(f).Handle:=sys_open(p,oflags,MODE_OPEN);
  325. end;
  326. If Filerec(f).Handle<0 Then
  327. Errno2Inoutres
  328. else
  329. InOutRes:=0;
  330. End;
  331. {*****************************************************************************
  332. Directory Handling
  333. *****************************************************************************}
  334. Procedure MkDir(Const s: String);[IOCheck];
  335. Var
  336. Buffer: Array[0..255] of Char;
  337. Begin
  338. If (s='') or (InOutRes <> 0) then
  339. exit;
  340. Move(s[1], Buffer, Length(s));
  341. Buffer[Length(s)] := #0;
  342. If sys_mkdir(@buffer, MODE_MKDIR)<0 Then
  343. Errno2Inoutres
  344. Else
  345. InOutRes:=0;
  346. End;
  347. Procedure RmDir(Const s: String);[IOCheck];
  348. Var
  349. Buffer: Array[0..255] of Char;
  350. Begin
  351. if (s = '.') then
  352. InOutRes := 16;
  353. If (s='') or (InOutRes <> 0) then
  354. exit;
  355. Move(s[1], Buffer, Length(s));
  356. Buffer[Length(s)] := #0;
  357. If sys_rmdir(@buffer)<0 Then
  358. Errno2Inoutres
  359. Else
  360. InOutRes:=0;
  361. End;
  362. Procedure ChDir(Const s: String);[IOCheck];
  363. Var
  364. Buffer: Array[0..255] of Char;
  365. Begin
  366. If (s='') or (InOutRes <> 0) then
  367. exit;
  368. Move(s[1], Buffer, Length(s));
  369. Buffer[Length(s)] := #0;
  370. If sys_chdir(@buffer)<0 Then
  371. Errno2Inoutres
  372. Else
  373. InOutRes:=0;
  374. { file not exists is path not found under tp7 }
  375. if InOutRes=2 then
  376. InOutRes:=3;
  377. End;
  378. procedure getdir(drivenr : byte;var dir : shortstring);
  379. var
  380. cwdinfo : stat;
  381. rootinfo : stat;
  382. thedir,dummy : string[255];
  383. dirstream : pdir;
  384. d : pdirent;
  385. name : string[255];
  386. tmp : string[255];
  387. thisdir : stat;
  388. begin
  389. dir:='';
  390. thedir:='';
  391. dummy:='';
  392. { get root directory information }
  393. tmp := '/'+#0;
  394. if sys_stat(@tmp[1],rootinfo)<0 then
  395. Begin
  396. Errno2Inoutres;
  397. Exit
  398. End
  399. Else
  400. InOutRes:=0;
  401. repeat
  402. tmp := dummy+'.'+#0;
  403. { get current directory information }
  404. if sys_stat(@tmp[1],cwdinfo)<0 then
  405. Begin
  406. Errno2Inoutres;
  407. Exit
  408. End
  409. Else
  410. InOutRes:=0;
  411. tmp:=dummy+'..'+#0;
  412. { open directory stream }
  413. { try to find the current inode number of the cwd }
  414. dirstream:=sys_opendir(@tmp[1]);
  415. if dirstream=nil then
  416. exit;
  417. repeat
  418. name:='';
  419. d:=sys_readdir(dirstream);
  420. { no more entries to read ... }
  421. if not assigned(d) then
  422. begin
  423. break;
  424. end;
  425. tmp:=dummy+'../'+strpas(d^.d_name) + #0;
  426. if sys_stat(@tmp[1],thisdir)<0 then
  427. begin
  428. Errno2Inoutres;
  429. Exit
  430. End
  431. Else
  432. InOutRes:=0;
  433. { found the entry for this directory name }
  434. if (cwdinfo.st_dev=thisdir.st_dev) and (cwdinfo.st_ino=thisdir.st_ino) then
  435. begin
  436. { are the filenames of type '.' or '..' ? }
  437. { then do not set the name. }
  438. if (not ((d^.d_name[0]='.') and ((d^.d_name[1]=#0) or
  439. ((d^.d_name[1]='.') and (d^.d_name[2]=#0))))) then
  440. begin
  441. name:='/'+strpas(d^.d_name);
  442. end;
  443. end
  444. until (name<>'');
  445. If sys_closedir(dirstream)<0 THen
  446. Begin
  447. Errno2Inoutres;
  448. Exit
  449. End
  450. Else
  451. InOutRes:=0;
  452. thedir:=name+thedir;
  453. dummy:=dummy+'../';
  454. if ((cwdinfo.st_dev=rootinfo.st_dev) and (cwdinfo.st_ino=rootinfo.st_ino)) then
  455. begin
  456. if thedir='' then
  457. dir:='/'
  458. else
  459. dir:=thedir;
  460. exit;
  461. end;
  462. until false;
  463. end;
  464. {*****************************************************************************
  465. SystemUnit Initialization
  466. *****************************************************************************}
  467. procedure SignalToRunerror(signo: cint); cdecl;
  468. var
  469. res : word;
  470. begin
  471. res:=0;
  472. if signo = SIGFPE then
  473. begin
  474. res := 200;
  475. end
  476. else
  477. if (signo = SIGILL) or (signo = SIGBUS) or (signo = SIGSEGV) then
  478. begin
  479. res := 216;
  480. end;
  481. { give runtime error at the position where the signal was raised }
  482. if res<>0 then
  483. begin
  484. HandleError(res);
  485. end;
  486. end;
  487. var
  488. act: SigActionRec;
  489. Procedure InstallSignals;
  490. var
  491. oldact: SigActionRec;
  492. begin
  493. { Initialize the sigaction structure }
  494. { all flags and information set to zero }
  495. FillChar(act, sizeof(SigActionRec),0);
  496. { initialize handler }
  497. act.sa_handler := @SignalToRunError;
  498. sys_SigAction(SIGFPE,act,oldact);
  499. sys_SigAction(SIGSEGV,act,oldact);
  500. sys_SigAction(SIGBUS,act,oldact);
  501. sys_SigAction(SIGILL,act,oldact);
  502. end;
  503. procedure SetupCmdLine;
  504. var
  505. bufsize,
  506. len,j,
  507. size,i : longint;
  508. found : boolean;
  509. buf : pchar;
  510. procedure AddBuf;
  511. begin
  512. reallocmem(cmdline,size+bufsize);
  513. move(buf^,cmdline[size],bufsize);
  514. inc(size,bufsize);
  515. bufsize:=0;
  516. end;
  517. begin
  518. GetMem(buf,ARG_MAX);
  519. size:=0;
  520. bufsize:=0;
  521. i:=0;
  522. while (i<argc) do
  523. begin
  524. len:=strlen(argv[i]);
  525. if len>ARG_MAX-2 then
  526. len:=ARG_MAX-2;
  527. found:=false;
  528. for j:=1 to len do
  529. if argv[i][j]=' ' then
  530. begin
  531. found:=true;
  532. break;
  533. end;
  534. if bufsize+len>=ARG_MAX-2 then
  535. AddBuf;
  536. if found then
  537. begin
  538. buf[bufsize]:='"';
  539. inc(bufsize);
  540. end;
  541. move(argv[i]^,buf[bufsize],len);
  542. inc(bufsize,len);
  543. if found then
  544. begin
  545. buf[bufsize]:='"';
  546. inc(bufsize);
  547. end;
  548. if i<argc then
  549. buf[bufsize]:=' '
  550. else
  551. buf[bufsize]:=#0;
  552. inc(bufsize);
  553. inc(i);
  554. end;
  555. AddBuf;
  556. FreeMem(buf,ARG_MAX);
  557. end;
  558. (*
  559. Begin
  560. { Set up signals handlers }
  561. InstallSignals;
  562. { Setup heap }
  563. InitHeap;
  564. InitExceptions;
  565. { Arguments }
  566. SetupCmdLine;
  567. { Setup stdin, stdout and stderr }
  568. OpenStdIO(Input,fmInput,StdInputHandle);
  569. OpenStdIO(Output,fmOutput,StdOutputHandle);
  570. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  571. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  572. { Reset IO Error }
  573. InOutRes:=0;
  574. End.
  575. *)
  576. {
  577. $Log$
  578. Revision 1.4 2002-09-07 16:01:26 peter
  579. * old logs removed and tabs fixed
  580. Revision 1.3 2002/08/20 12:50:22 marco
  581. * New errno handling. Should be libc compatible.
  582. Revision 1.2 2002/08/10 13:42:36 marco
  583. * Fixes Posix dir copied to devel branch
  584. Revision 1.1.2.18 2002/03/10 11:45:02 carl
  585. * InOutRes := 16 with rmdir()
  586. * InOutRes := 5 more checking
  587. Revision 1.1.2.17 2002/03/03 15:11:51 carl
  588. * erase() bugfix (erasing a directory is done via rmdir() only!)
  589. Revision 1.1.2.16 2002/02/15 18:13:35 carl
  590. * bugfix for paramstr(0)
  591. }