unit vfile;

{$mode ObjFPC}{$H+}
{$CALLING SysV_ABI_CDecl}

interface

uses
 sys_event,
 vstat,
 vuio,
 vnode,
 kern_id;

const
 // configurable pathname variables
 _PC_LINK_MAX        =1;
 _PC_MAX_CANON       =2;
 _PC_MAX_INPUT       =3;
 _PC_NAME_MAX        =4;
 _PC_PATH_MAX        =5;
 _PC_PIPE_BUF        =6;
 _PC_CHOWN_RESTRICTED=7;
 _PC_NO_TRUNC        =8;
 _PC_VDISABLE        =9;
 _POSIX_VDISABLE     =$ff;

 _PC_ASYNC_IO        =53;
 _PC_PRIO_IO         =54;
 _PC_SYNC_IO         =55;

 _PC_ALLOC_SIZE_MIN    =10;
 _PC_FILESIZEBITS      =12;
 _PC_REC_INCR_XFER_SIZE=14;
 _PC_REC_MAX_XFER_SIZE =15;
 _PC_REC_MIN_XFER_SIZE =16;
 _PC_REC_XFER_ALIGN    =17;
 _PC_SYMLINK_MAX       =18;

 _PC_ACL_EXTENDED=59;
 _PC_ACL_PATH_MAX=60;
 _PC_CAP_PRESENT =61;
 _PC_INF_PRESENT =62;
 _PC_MAC_PRESENT =63;
 _PC_ACL_NFS4    =64;

 // access function
 F_OK=0; // test for existence of file
 X_OK=$01; // test for execute or search permission
 W_OK=$02; // test for write permission
 R_OK=$04; // test for read permission

 // whence values for lseek(2)
 SEEK_SET =0; // set file offset to offset
 SEEK_CUR =1; // set file offset to current plus offset
 SEEK_END =2; // set file offset to EOF plus offset
 SEEK_DATA=3; // set file offset to next data past offset
 SEEK_HOLE=4; // set file offset to next hole past offset

 // whence values for lseek(2); renamed by POSIX 1003.1
 L_SET =SEEK_SET;
 L_INCR=SEEK_CUR;
 L_XTND=SEEK_END;

 DTYPE_VNODE     = 1; { file }
 DTYPE_SOCKET    = 2; { communications endpoint }
 DTYPE_PIPE      = 3; { pipe }
 DTYPE_FIFO      = 4; { fifo (named pipe) }
 DTYPE_KQUEUE    = 5; { event queue }
 DTYPE_CRYPTO    = 6; { crypto }
 DTYPE_MQUEUE    = 7; { posix message queue }
 DTYPE_SHM       = 8; { swap-backed shared memory }
 DTYPE_SEM       = 9; { posix semaphore }
 DTYPE_PTS       =10; { pseudo teletype master device }
 DTYPE_DEV       =11; { Device specific fd type }
 DTYPE_CAPABILITY=12; { capability }
 DTYPE_PROCDESC  =13; { process descriptor }
 DTYPE_JITSHM    =14; { shared memory for JIT compiler }
 DTYPE_IPCSOCKET =15; { unix domain socket }
 DTYPE_PHYSHM    =16; { PS4 physical shared memory }
 DTYPE_BLOCKPOOL =17; { PlayStation blockpool }

 FOF_OFFSET  =$01; { Use the offset in uio argument }
 FOF_NOLOCK  =$02; { Do not take FOFFSET_LOCK }
 FOF_NEXTOFF =$04; { Also update f_nextoff }
 FOF_NOUPDATE=$10; { Do not update f_offset }

 DFLAG_PASSABLE=$01; { may be passed via unix sockets. }
 DFLAG_SEEKABLE=$02; { seekable / nonsequential }

 STDIN_FILENO =0; // standard input file descriptor
 STDOUT_FILENO=1; // standard output file descriptor
 STDERR_FILENO=2; // standard error file descriptor

type
 mode_t=Integer;
 uid_t =Integer;
 gid_t =Integer;

 pp_file=^p_file;
 p_file=^t_file;

 fo_rdwr_t    =function(fp:p_file;uio:p_uio;flags:Integer):Integer;
 fo_truncate_t=function(fp:p_file;length:Int64):Integer;
 fo_ioctl_t   =function(fp:p_file;com:QWORD;data:Pointer):Integer;
 fo_poll_t    =function(fp:p_file;events:Integer):Integer;
 fo_kqfilter_t=function(fp:p_file;kn:p_knote):Integer;
 fo_stat_t    =function(fp:p_file;sb:p_stat):Integer;
 fo_close_t   =function(fp:p_file):Integer;
 fo_chmod_t   =function(fp:p_file;mode:mode_t):Integer;
 fo_chown_t   =function(fp:p_file;uid:uid_t;gid:gid_t):Integer;

 fo_flags_t=type Integer;

 p_fileops=^fileops;
 fileops=packed record
  fo_read    :fo_rdwr_t    ;
  fo_write   :fo_rdwr_t    ;
  fo_truncate:fo_truncate_t;
  fo_ioctl   :fo_ioctl_t   ;
  fo_poll    :fo_poll_t    ;
  fo_kqfilter:fo_kqfilter_t;
  fo_stat    :fo_stat_t    ;
  fo_close   :fo_close_t   ;
  fo_chmod   :fo_chmod_t   ;
  fo_chown   :fo_chown_t   ;
  fo_flags   :fo_flags_t; { DFLAG_* below }
 end;

 p_fadvise_info=^fadvise_info;
 fadvise_info=packed record
  fa_advice   :Integer; { (f) FADV_* type. }
  fa_start    :Int64  ; { (f) Region start. }
  fa_end      :Int64  ; { (f) Region end. }
  fa_prevstart:Int64  ; { (f) Previous NOREUSE start. }
  fa_prevend  :Int64  ; { (f) Previous NOREUSE end. }
 end;

 t_file=object
  desc          :t_id_desc;
  //
  f_data        :Pointer  ; { file descriptor specific data }
  f_ops         :p_fileops; { File operations }
  f_vnode       :p_vnode  ; { NULL or applicable vnode }
  f_type        :Word     ; { descriptor type }
  f_vnread_flags:Word     ; { (f) Sleep lock for f_offset }
  f_flag        :DWORD    ; { see fcntl.h }
  f_count       :DWORD    ; { reference count }
  {
   *  DTYPE_VNODE specific fields.
   }
  f_seqcount:Integer; { Count of sequential accesses. }
  f_exclose :Integer;
  f_nextoff :Int64;   { next expected read/write offset. }
  f_vnun    :Pointer;
  {
   *  DFLAG_SEEKABLE specific fields
   }
  f_offset:Int64;
  {
   * Mandatory Access control information.
   }
  //f_label:Pointer; { Place-holder for MAC label. }
  //
  property f_cdevpriv:Pointer read f_vnun write f_vnun;
  property f_advice  :Pointer read f_vnun write f_vnun;
 end;

const
 FOFFSET_LOCKED      =$1;
 FOFFSET_LOCK_WAITING=$2;
 FDEVFS_VNODE        =$4;

//extern fileops vnops;
//extern fileops badfileops;
//extern fileops socketops;
//extern int maxfiles;  { kernel limit on number of open files }
//extern int maxfilesperproc; { per process limit on number of open files }

var
 openfiles:Integer=0; { actual number of open files }

 {
  * The module initialization routine for POSIX asynchronous I/O will
  * set this to the version of AIO that it implements.  (Zero means
  * that it is not implemented.)  This value is used here by pathconf()
  * and in kern_descrip.c by fpathconf().
  }
 async_io_version:Integer=0;

function fo_read(fp:p_file;uio:p_uio;flags:Integer):Integer;
function fo_write(fp:p_file;uio:p_uio;flags:Integer):Integer;
function fo_truncate(fp:p_file;length:Int64):Integer;
function fo_ioctl(fp:p_file;com:QWORD;data:Pointer):Integer;
function fo_poll(fp:p_file;events:Integer):Integer;
function fo_stat(fp:p_file;sb:p_stat):Integer;
function fo_close(fp:p_file):Integer;
function fo_kqfilter(fp:p_file;kn:p_knote):Integer;
function fo_chmod(fp:p_file;mode:mode_t):Integer;
function fo_chown(fp:p_file;uid:uid_t;gid:gid_t):Integer;

implementation

{
 fhold(fp) (refcount_acquire(&(fp)^.f_count))
 fdrop(fp, td) (refcount_release(&(fp)^.f_count) ? _fdrop((fp), (td)) : _fnoop())
}

function fo_read(fp:p_file;uio:p_uio;flags:Integer):Integer;
begin
 Exit(fp^.f_ops^.fo_read(fp,uio,flags));
end;

function fo_write(fp:p_file;uio:p_uio;flags:Integer):Integer;
begin
 Exit(fp^.f_ops^.fo_write(fp,uio,flags));
end;

function fo_truncate(fp:p_file;length:Int64):Integer;
begin
 Exit(fp^.f_ops^.fo_truncate(fp,length));
end;

function fo_ioctl(fp:p_file;com:QWORD;data:Pointer):Integer;
begin
 Exit(fp^.f_ops^.fo_ioctl(fp,com,data));
end;

function fo_poll(fp:p_file;events:Integer):Integer;
begin
 Exit(fp^.f_ops^.fo_poll(fp,events));
end;

function fo_stat(fp:p_file;sb:p_stat):Integer;
begin
 Exit(fp^.f_ops^.fo_stat(fp,sb));
end;

function fo_close(fp:p_file):Integer;
begin
 Exit(fp^.f_ops^.fo_close(fp));
end;

function fo_kqfilter(fp:p_file;kn:p_knote):Integer;
begin
 Exit(fp^.f_ops^.fo_kqfilter(fp,kn));
end;

function fo_chmod(fp:p_file;mode:mode_t):Integer;
begin
 Exit(fp^.f_ops^.fo_chmod(fp,mode));
end;

function fo_chown(fp:p_file;uid:uid_t;gid:gid_t):Integer;
begin
 Exit(fp^.f_ops^.fo_chown(fp,uid,gid));
end;




end.

