{ $Id$ This file is part of the Free Pascal run time library. Copyright (c) 1999-2000 by Michael Van Canneyt, member of the Free Pascal development team. See the file COPYING.FPC, included in this distribution, for details about the copyright. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. **********************************************************************} {Darwin version of the syscalls required to implement SysLinux.} {No debugging for syslinux include !} {$IFDEF SYS_LINUX} {$UNDEF SYSCALL_DEBUG} {$ENDIF SYS_LINUX} {***************************************************************************** --- Main:The System Call Self --- *****************************************************************************} Procedure Do_SysCall( callnr:longint;var regs : SysCallregs );assembler; { This function puts the registers in place, does the call, and then copies back the registers as they are after the SysCall. } {$ifdef cpupowerpc} {$define fpc_syscall_ok} asm { load the registers... } lwz r5, 12(r4) lwz r6, 16(r4) lwz r7, 20(r4) lwz r8, 24(r4) lwz r9, 28(r4) mr r0, r3 lwz r3, 4(r4) stw r4, regs lwz r4, 8(r4) { Go ! } sc { Put back the registers... } lwz r8, regs stw r3, 4(r8) stw r4, 8(r8) stw r5, 12(r8) stw r6, 16(r8) stw r7, 20(r8) end; {$endif cpupowerpc} {$ifndef fpc_syscall_ok} {$error Cannot decide which processor you have!} asm end; {$endif not fpc_syscall_ok} {$IFDEF SYSCALL_DEBUG} Const DoSysCallDebug : Boolean = False; var LastCnt, LastR0, LastCall : longint; DebugTxt : string[20]; {$ENDIF} Function SysCall( callnr:longint;var regs : SysCallregs ):longint; { This function serves as an interface to do_SysCall. If the SysCall returned a negative number, it returns -1, and puts the SysCall result in errno. Otherwise, it returns the SysCall return value } begin do_SysCall(callnr,regs); if regs.reg1<0 then begin {$IFDEF SYSCALL_DEBUG} If DoSysCallDebug then debugtxt:=' syscall error: '; {$endif} ErrNo:=-regs.reg1; SysCall:=-1; end else begin {$IFDEF SYSCALL_DEBUG} if DoSysCallDebug then debugtxt:=' syscall returned: '; {$endif} SysCall:=regs.reg1; errno:=0 end; {$IFDEF SYSCALL_DEBUG} if DoSysCallDebug then begin inc(lastcnt); if (callnr<>lastcall) or (regs.reg1<>lastR0) then begin if lastcnt>1 then writeln(sys_nr_txt[lastcall],debugtxt,lasteax,' (',lastcnt,'x)'); lastcall:=callnr; lasteax:=regs.reg1; lastcnt:=0; writeln(sys_nr_txt[lastcall],debugtxt,lasteax); end; end; {$endif} end; Function Sys_Time:longint; VAR tv : timeval; tz : timezone; retval : longint; begin Retval:=do_syscall(116,longint(@tv),longint(@tz)); If retval=-1 then sys_time:=-1 else sys_time:=tv.sec; end; Function Sys_Time:longint; var tv : timeval; tz : timezone; regs : SysCallregs; retval: longint; begin regs.reg2:=@tv; regs.reg3:=@tz; retval:=SysCall(SYS_gettimeofday,regs); if retval = -1 then Sys_Time := -1 else Sys_Time := tv.sec; end; {***************************************************************************** --- File:File handling related calls --- *****************************************************************************} Function Sys_Open(f:pchar;flags:longint;mode:integer):longint; var regs : SysCallregs; Begin regs.reg2:=longint(f); regs.reg3:=flags; regs.reg4:=mode; Sys_Open:=SysCall(SysCall_nr_open,regs); End; Function Sys_Close(f:longint):longint; var regs : SysCallregs; begin regs.reg2:=f; Sys_Close:=SysCall(SysCall_nr_close,regs); end; Function Sys_Lseek(F:longint;Off:longint;Whence:longint):longint; var regs : SysCallregs; begin {Lseek's offset is 64-bit, the highword is the 0} regs.reg2:=f; { strange, even on the PPC, the order of the low/high dword in the } { registers is in "little endian" here (JM) } regs.reg3:=off; regs.reg4:=0; regs.reg5:=whence Sys_Lseek:=do_syscall(syscall_nr_lseek,regs); end; Function Sys_Read(f:longint;buffer:pchar;count:longint):longint; var regs : SysCallregs; begin regs.reg2:=f; regs.reg3:=longint(buffer); regs.reg4:=count; Sys_Read:=SysCall(SysCall_nr_read,regs); end; Function Sys_Write(f:longint;buffer:pchar;count:longint):longint; var regs : SysCallregs; begin regs.reg2:=f; regs.reg3:=longint(buffer); regs.reg4:=count; Sys_Write:=SysCall(SysCall_nr_write,regs); end; Function Sys_Unlink(Filename:pchar):longint; var regs : SysCallregs; begin regs.reg2:=longint(filename); Sys_Unlink:=SysCall(SysCall_nr_unlink,regs); end; Function Sys_fstat(fd : longint;var Info:stat):Longint; var regs : SysCallregs; begin regs.reg2:=fd; regs.reg3:=longint(@Info); Sys_fStat:=SysCall(SysCall_nr_fstat,regs); end; Function Sys_Rename(Oldname,Newname:pchar):longint; var regs : SysCallregs; begin regs.reg2:=longint(oldname); regs.reg3:=longint(newname); Sys_Rename:=SysCall(SysCall_nr_rename,regs); end; Function Sys_Stat(Filename:pchar;var Buffer: stat):longint; { We need this for getcwd } var regs : SysCallregs; begin regs.reg2:=longint(filename); regs.reg3:=longint(@buffer); Sys_Stat:=SysCall(SysCall_nr_stat,regs); end; Function Sys_Symlink(oldname,newname:pchar):longint; { We need this for erase } var regs : SysCallregs; begin regs.reg2:=longint(oldname); regs.reg3:=longint(newname); Sys_symlink:=SysCall(SysCall_nr_symlink,regs); end; Function Sys_ReadLink(name,linkname:pchar;maxlen:longint):longint; var regs : SysCallRegs; begin regs.reg2:=longint(name); regs.reg3:=longint(linkname); regs.reg4:=maxlen; Sys_ReadLink:=SysCall(Syscall_nr_readlink,regs); end; {***************************************************************************** --- Directory:Directory related calls --- *****************************************************************************} Function Sys_Chdir(Filename:pchar):longint; var regs : SysCallregs; begin regs.reg2:=longint(filename); Sys_ChDir:=SysCall(SysCall_nr_chdir,regs); end; Function Sys_Mkdir(Filename:pchar;mode:longint):longint; var regs : SysCallregs; begin regs.reg2:=longint(filename); regs.reg3:=mode; Sys_MkDir:=SysCall(SysCall_nr_mkdir,regs); end; Function Sys_Rmdir(Filename:pchar):longint; var regs : SysCallregs; begin regs.reg2:=longint(filename); Sys_Rmdir:=SysCall(SysCall_nr_rmdir,regs); end; {***************************************************************************** --- Process:Process & program handling - related calls --- *****************************************************************************} Function sys_GetPid:LongInt; { Get Process ID. } var regs : SysCallregs; begin Sys_GetPid:=SysCall(SysCall_nr_getpid,regs); end; Procedure Sys_Exit(ExitCode:longint); var regs : SysCallregs; begin regs.reg2:=exitcode; SysCall(SysCall_nr_exit,regs) end; Procedure SigAction(Signum:longint;Act,OldAct:PSigActionRec ); { Change action of process upon receipt of a signal. Signum specifies the signal (all except SigKill and SigStop). If Act is non-nil, it is used to specify the new action. If OldAct is non-nil the previous action is saved there. } Var sr : Syscallregs; begin sr.reg2:=Signum; sr.reg3:=Longint(act); sr.reg4:=Longint(oldact); SysCall(Syscall_nr_sigaction,sr); {$ifdef linuxunit} LinuxError:=Errno; {$endif} end; (*=================== MOVED from syslinux.inc ========================*) Function Sys_FTruncate(Handle,Pos:longint):longint; //moved from sysunix.inc Do_Truncate var sr : syscallregs; begin sr.reg2:=Handle; sr.reg3:=Pos; sr.reg4:=0; Sys_FTruncate:=syscall(syscall_nr_ftruncate,sr); end; Function Sys_ReadDir(p:pdir):pdirent; { Different from Linux, Readdir on BSD is based on Getdents/getdirentries, due to the absense of the readdir syscall. } function readbuffer:longint; var retval :longint; dummy :longint; begin retval:=do_syscall(syscall_nr_getdirentries,longint(p^.fd), longint(@p^.buf^),DIRBLKSIZ,longint(@dummy)); p^.rewind:=longint(p^.buf); if retval=0 then begin p^.rewind:=0; p^.loc:=0; end else P^.loc:=retval; readbuffer:=retval; end; var l : pdirent; novalid : boolean; begin if (p^.buf=nil) or (p^.loc=0) THEN exit(nil); if p^.loc=-1 then {First readdir on this pdir. Initial fill of buffer} begin if readbuffer()=0 Then {nothing to be read} exit(nil) end; l:=nil; repeat novalid:=false; if (pdirent(p^.rewind)^.reclen<>0) then begin {valid direntry?} if pdirent(p^.rewind)^.ino<>0 then l:=pdirent(p^.rewind); inc(p^.rewind,pdirent(p^.rewind)^.reclen); if p^.rewind>=(longint(p^.buf)+dirblksiz) then novalid:=true; end else novalid:=true; if novalid then begin {block entirely searched or reclen=0} if p^.loc<>0 then {blocks left?} if readbuffer()<>0 then {succesful read?} novalid:=false; end; until (l<>nil) or novalid; if novalid then l:=nil; Sys_ReadDir:=l; end; Function Sys_mmap(adr,len,prot,flags,fdes,off:longint):longint; // moved from sysunix.inc, used in sbrk var sr: syscallregs; begin sr.reg2:=adr; sr.reg3:=len; sr.reg4:=prot; sr.reg5:=flags; sr.reg6:=fdes; sr.reg7:=off; sr.reg8:=0; Sys_mmap:=do_syscall(syscall_nr_mmap,sr); end; { Interface to Unix ioctl call. Performs various operations on the filedescriptor Handle. Ndx describes the operation to perform. Data points to data needed for the Ndx function. The structure of this data is function-dependent. } Function Sys_IOCtl(Handle,Ndx: Longint;Data: Pointer):LongInt; // This was missing here, instead hardcoded in Do_IsDevice var sr: SysCallRegs; begin sr.reg2:=Handle; sr.reg3:=Ndx; sr.reg4:=Longint(Data); Sys_IOCtl:=SysCall(Syscall_nr_ioctl,sr); end; { $Log$ Revision 1.4 2003-08-21 22:25:17 olle - removed parameter from fpc_iocheck Revision 1.3 2002/09/08 15:29:23 jonas + added sys_readdir code from OpenBSD in fixes branch Revision 1.2 2002/09/07 16:01:17 peter * old logs removed and tabs fixed Revision 1.1 2002/09/06 18:35:59 jonas * implemented most syscalls, except readdir because the getdents syscall is declared obsolete in Darwin... }