PreviousUpNext

15.4.1182  src/lib/std/src/psx/posix-file.pkg

## posix-file.pkg
#
# Package for POSIX 1003.1 file system operations
# This is a subpackage of the POSIX 1003.1 based
# 'Posix' package
#
#     src/lib/std/src/psx/posixlib.pkg
#
# An alternative portable (cross-platform)
# filesystem interface is defined and implemented in:
#
#     src/lib/std/src/winix/winix-file.api
#     src/lib/std/src/posix/winix-file.pkg

# Compiled by:
#     src/lib/std/src/standard-core.sublib






###               "Let him choose out of my files,
###                his projects to accomplish."
###
###                      -- William Shakespeare, "Coriolanus"



stipulate
    #
    # At some point I think the Unts should all become Ints
    # -- having unsigneds floating around is mainly a pain:
    #    package host_int =       int_guts;                                             # int_guts                              is from   src/lib/std/src/int-guts.pkg
    #
    package hi  =  host_int;                                                            # host_int                              is from   src/lib/std/src/psx/host-int.pkg
    package hug =  host_unt_guts;                                                       # host_unt_guts                         is from   src/lib/std/src/bind-sysword-32.pkg
    package i1w =  one_word_int;                                                        # one_word_int                          is from   src/lib/std/types-only/basis-structs.pkg
    package iwg =  one_word_int_guts;                                                   # one_word_int_guts                     is from   src/lib/std/src/one-word-int-guts.pkg
    package uwg =  one_word_unt_guts;                                                   # one_word_unt_guts                     is from   src/lib/std/src/one-word-unt-guts.pkg
    package tg  =  time_guts;                                                           # time_guts                             is from   src/lib/std/src/time-guts.pkg
    package ti  =  tagged_int;                                                          # tagged_int                            is from   src/lib/std/types-only/basis-structs.pkg
    package pc  =  posix_common;                                                        # posix_common                          is from   src/lib/std/src/posix/posix-common.pkg
    package rt  =  runtime;                                                             # runtime                               is from   src/lib/core/init/runtime.pkg
    package wt  =  winix_types;                                                         # winix_types                           is from   src/lib/std/src/posix/winix-types.pkg
    #                                                                                   # winix_types                           is from   src/lib/std/src/win32/winix-types.pkg
    #
    package ci      =  mythryl_callable_c_library_interface;                            # mythryl_callable_c_library_interface  is from   src/lib/std/src/unsafe/mythryl-callable-c-library-interface.pkg
    #
    fun cfun  fun_name
        =
        ci::find_c_function'' { lib_name => "posix_filesys",  fun_name };
herein

    package posix_file # : Posix_File                                                   # Posix_File                            is from   src/lib/std/src/psx/posix-file.api
    {
        (|) =  hug::bitwise_or;
        (&) =  hug::bitwise_and;

   #    infix my  | & ;

        (cfun "osval")                                                                  # osval                                 def in    src/c/lib/posix-file-system/osval.c
            ->
            (      osval3__syscall:    String -> hi::Int,                               # The '3's here are just to avoid duplicate-definitions complaints when this pkg gets included into the posix package.
                   osval3__ref,
              set__osval3__ref
            );

        fun osval string
            =
            *osval3__ref  string;

        w_osval =  hug::from_int o osval;

        User_Id  =  hug::Unt;
        Group_Id =  hug::Unt;

        File_Descriptor =  hi::Int;


        fun fd_to_int  fd  =  fd;
        fun int_to_fd  fd  =  fd;


        #  Conversions between winix__premicrothread::io::Iod values and Posix file descriptors. 
        #
        fun fd_to_iod  fd
            =
            wt::io::int_to_iod  fd;


        fun iod_to_fd  iod
            =
            wt::io::iod_to_fd  iod;

        o_rdonly =  w_osval "O_RDONLY";
        o_wronly =  w_osval "O_WRONLY";
        o_rdwr   =  w_osval "O_RDWR";

        Open_Mode ==  pc::Open_Mode;

        fun omode_from_unt  omode
            =
            if   (omode == o_rdonly)   O_RDONLY;
            elif (omode == o_wronly)   O_WRONLY;
            elif (omode == o_rdwr  )   O_RDWR;
            else                       raise exception DIE ("posix_file::omodeFromUnt: unknown mode " + (uwg::to_string omode));
            fi;

        fun omode_to_unt O_RDONLY =>  o_rdonly;
            omode_to_unt O_WRONLY =>  o_wronly;
            omode_to_unt O_RDWR   =>  o_rdwr;
        end;

        fun uid_to_unt i =  i;
        fun unt_to_uid i =  i;
        fun gid_to_unt i =  i;
        fun unt_to_gid i =  i;

        Ckit_Dirstream = rt::Chunk;  #  the underlying C DIRSTREAM 

        Directory_Stream
            =
            DIRECTORY_STREAM 
              {
                dirstream:  Ckit_Dirstream,
                is_open:   Ref( Bool )
              };


        (cfun "opendir")                                                                        # opendir       def in    src/c/lib/posix-file-system/opendir.c
            ->
            (      opendir__syscall:    String -> Ckit_Dirstream,
                   opendir__ref,
              set__opendir__ref
            );
        


        (cfun "readdir")                                                                        # readdir       def in    src/c/lib/posix-file-system/readdir.c
            ->
            (      readdir__syscall:    Ckit_Dirstream -> String,
                   readdir__ref,
              set__readdir__ref
            );



        (cfun "rewinddir")                                                                      # rewinddir     def in    src/c/lib/posix-file-system/rewinddir.c
            ->
            (      rewinddir__syscall:    Ckit_Dirstream -> Void,
                   rewinddir__ref,
              set__rewinddir__ref
            );




        (cfun "closedir")                                                                       # closedir      def in    src/c/lib/posix-file-system/closedir.c
            ->
            (      closedir__syscall:    Ckit_Dirstream -> Void,
                   closedir__ref,
              set__closedir__ref
            );



        fun open_directory_stream  path
            =
            DIRECTORY_STREAM
              {
                dirstream =>  *opendir__ref  path,
                is_open   =>  REF( TRUE )
              };


        fun read_directory_entry (DIRECTORY_STREAM { dirstream, is_open => REF FALSE } )
                =>
                raise exception rt::RUNTIME_EXCEPTION ("readdir on closed directory stream", NULL);

            read_directory_entry (DIRECTORY_STREAM { dirstream, ... } )
                =>
                case (*readdir__ref  dirstream)
                    #
                    ""   =>  NULL;
                    name =>  THE name;
                esac;
        end;


        fun rewind_directory_stream (DIRECTORY_STREAM { dirstream, is_open => REF FALSE } )
                =>
                raise exception rt::RUNTIME_EXCEPTION("rewinddir on closed directory stream", NULL);

            rewind_directory_stream (DIRECTORY_STREAM d)
                =>
                *rewinddir__ref  d.dirstream;
        end;


        fun close_directory_stream (DIRECTORY_STREAM { dirstream, is_open => REF FALSE } )
                =>
                ();

            close_directory_stream (DIRECTORY_STREAM { dirstream, is_open } )
                =>
                {   is_open :=  FALSE;
                    #
                    *closedir__ref  dirstream;
                };
        end;


        (cfun "chdir")                                                                  # chdir         def in    src/c/lib/posix-file-system/chdir.c
            ->
            (      change_directory__syscall:    String -> Void,
                   change_directory__ref,
              set__change_directory__ref
            );


        fun change_directory string
            =
            *change_directory__ref  string;


        (cfun "getcwd")                                                                 # getcwd        def in    src/c/lib/posix-file-system/getcwd.c
            ->
            (      current_directory__syscall:    Void -> String,
                   current_directory__ref,
              set__current_directory__ref
            );


        fun current_directory ()
            =
            *current_directory__ref (); 

        stdin  =  int_to_fd  0;
        stdout =  int_to_fd  1;
        stderr =  int_to_fd  2;

        package s {
            #
            stipulate
                package bf =  bit_flags_g ();
            herein
                include package  bf;
                #
                Mode = Flags;
            end;

            irwxu =  from_unt (w_osval "irwxu");
            irusr =  from_unt (w_osval "irusr");
            iwusr =  from_unt (w_osval "iwusr");
            ixusr =  from_unt (w_osval "ixusr");
            irwxg =  from_unt (w_osval "irwxg");
            irgrp =  from_unt (w_osval "irgrp");
            iwgrp =  from_unt (w_osval "iwgrp");
            ixgrp =  from_unt (w_osval "ixgrp");
            irwxo =  from_unt (w_osval "irwxo");
            iroth =  from_unt (w_osval "iroth");
            iwoth =  from_unt (w_osval "iwoth");
            ixoth =  from_unt (w_osval "ixoth");
            isuid =  from_unt (w_osval "isuid");
            isgid =  from_unt (w_osval "isgid");
        };

        mode_0755 = s::flags
                        [
                          s::irusr, s::iwusr, s::ixusr,
                          s::irgrp,           s::ixgrp,
                          s::iroth,           s::ixoth
                        ];

        mode_0700 = s::flags
                        [
                          s::irusr, s::iwusr, s::ixusr
                        ];

        mode_0666 = s::flags
                        [
                          s::irusr, s::iwusr,
                          s::irgrp, s::iwgrp,
                          s::iroth, s::iwoth
                        ];

        mode_0644 = s::flags
                        [
                          s::irusr, s::iwusr,
                          s::irgrp,
                          s::iroth
                        ];


        mode_0600 = s::flags
                        [
                          s::irusr, s::iwusr
                        ];


        package o {
            #
            stipulate
                package bf = bit_flags_g ();                                                    # bit_flags_g           def in    src/lib/std/src/bit-flags-g.pkg
            herein
                include package   bf;
            end;

            append   =  from_unt (w_osval "O_APPEND");
            dsync    =  from_unt (w_osval "O_DSYNC");
            excl     =  from_unt (w_osval "O_EXCL");
            noctty   =  from_unt (w_osval "O_NOCTTY");
            nonblock =  from_unt (w_osval "O_NONBLOCK");
            rsync    =  from_unt (w_osval "O_RSYNC");
            sync     =  from_unt (w_osval "O_SYNC");

            o_trunc  =  w_osval "O_TRUNC";
            trunc    =  from_unt  o_trunc;

            o_creat  =  w_osval "O_CREAT";
            crflags  =  o_wronly | o_creat | o_trunc;

        };

        (cfun "openf")                                                                          # openf                 def in    src/c/lib/posix-file-system/openf.c
            ->
            (      openf__syscall:    (String, hug::Unt, hug::Unt) -> hi::Int,
                   openf__ref,
              set__openf__ref
            );


        fun openf (fname, omode, flags)
            =
            int_to_fd (*openf__ref (fname, o::to_unt flags | (omode_to_unt omode), 0u0));


        (cfun "mkstemp")                                                                        # mkstemp               def in    src/c/lib/posix-file-system/mkstemp.c 
            ->
            (      mkstemp__syscall:    Void -> hi::Int,
                   mkstemp__ref,
              set__mkstemp__ref
            );

                                                                                                #
        fun mkstemp ()                                                                          # Opens a temporary file and returns the fd -- see man 3 mkfstemp
            =
            int_to_fd (*mkstemp__ref ());


        fun createf (fname, omode, oflags, mode)
            =
            {   flags = o::o_creat
                      | o::to_unt  oflags
                      | omode_to_unt  omode
                      ;

                int_to_fd (*openf__ref (fname, flags, s::to_unt mode));
            };


        fun creat (fname, mode)
            =
            int_to_fd (*openf__ref (fname, o::crflags, s::to_unt mode));


        (cfun "umask")                                                                                          # umask                 def in    src/c/lib/posix-file-system/umask.c
            ->
            (      umask__syscall:    hug::Unt -> hug::Unt,
                   umask__ref,
              set__umask__ref
            );
        #
        fun umask mode
            =
            s::from_unt (*umask__ref  (s::to_unt  mode));

        (cfun "link")                                                                                           # link                  def in    src/c/lib/posix-file-system/link.c
            ->
            (      link__syscall:    (String, String) -> Void,
                   link__ref,
              set__link__ref
            );
        #
        fun link { old, new }
            =
            *link__ref (old, new);


        (cfun "rename")                                                                                         # rename                def in    src/c/lib/posix-file-system/rename.c
            ->
            (      rename__syscall:    (String, String) -> Void,
                   rename__ref,
              set__rename__ref
            );
        #
        fun rename { from, to }
            =
            *rename__ref (from, to);

        (cfun "symlink")                                                                                        # symlink               def in    src/c/lib/posix-file-system/symlink.c
            ->
            (      symlink__syscall:    (String, String) -> Void,
                   symlink__ref,
              set__symlink__ref
            );
        #
        fun symlink { old, new }
            =
            *symlink__ref (old, new);

        (cfun "mkdir")                                                                                          # mkdir                 def in    src/c/lib/posix-file-system/mkdir.c
            ->
            (      mkdir__syscall:    (String, hug::Unt) -> Void,
                   mkdir__ref,
              set__mkdir__ref
            );

        #
        fun mkdir (dirname, mode)
            =
            *mkdir__ref  (dirname,  s::to_unt mode);


        (cfun "mkfifo")                                                                                         # mkfifo                def in    src/c/lib/posix-file-system/mkfifo.c
            ->
            (      make_named_pipe__syscall:    (String, hug::Unt) -> Void,
                   make_named_pipe__ref,
              set__make_named_pipe__ref
            );

        #
        fun make_named_pipe (name, mode)
            =
            *make_named_pipe__ref  (name,  s::to_unt mode);


        (cfun "unlink")                                                                                         # unlink                def in    src/c/lib/posix-file-system/unlink.c
            ->
            (      unlink__syscall:    String -> Void,
                   unlink__ref,
              set__unlink__ref
            );

        fun unlink string
            =
            *unlink__ref  string;

        (cfun "rmdir")                                                                                          # rmdir                 def in    src/c/lib/posix-file-system/rmdir.c
            ->
            (      rmdir__syscall:    String -> Void,
                   rmdir__ref,
              set__rmdir__ref
            );


        fun rmdir  string
            =
            *rmdir__ref  string;


        (cfun "readlink")                                                                                       # readlink              def in    src/c/lib/posix-file-system/readlink.c
            ->
            (      readlink__syscall:    String -> String,
                   readlink__ref,
              set__readlink__ref
            );


        fun readlink string
            =
            *readlink__ref  string;


        (cfun "ftruncate")                                                                                      # ftruncate             def in    src/c/lib/posix-file-system/ftruncate.c
            ->
            (      ftruncate__syscall:    (hi::Int, tagged_int_guts::Int) -> Void,
                   ftruncate__ref,
              set__ftruncate__ref
            );
        #
        fun ftruncate (fd, len)
            =
            *ftruncate__ref (fd, len);

        Device = hug::Unt;

        fun dev_to_unt  i =  i;
        fun unt_to_dev  i =  i;

        Inode = hug::Unt;

        fun ino_to_unt  i =  i;
        fun unt_to_ino  i =  i;

        package stat {
            #
            Stat = { ftype:  hi::Int,
                     mode:   s::Flags,
                     inode:  Int,
                     dev:    Int,
                     nlink:  Int,
                     uid:    hug::Unt,
                     gid:    hug::Unt,
                     size:   file_position::Int,
                     atime:  tg::Time,
                     mtime:  tg::Time,
                     ctime:  tg::Time
                   };

            # The following assumes the C stat functions pull the
            # file type from the mode field and return the
            # integer below corresponding to the file type.

            fun is_directory  (s: Stat) =  (s.ftype == 0x4000);
            fun is_char_dev   (s: Stat) =  (s.ftype == 0x2000);
            fun is_block_dev  (s: Stat) =  (s.ftype == 0x6000);
            fun is_file       (s: Stat) =  (s.ftype == 0x8000);
            fun is_pipe       (s: Stat) =  (s.ftype == 0x1000);
            fun is_symlink    (s: Stat) =  (s.ftype == 0xA000);
            fun is_socket     (s: Stat) =  (s.ftype == 0xC000);

            fun mode  (s: Stat) =  s.mode;
            fun inode (s: Stat) =  s.inode;
            fun dev   (s: Stat) =  s.dev;
            fun nlink (s: Stat) =  s.nlink;
            fun uid   (s: Stat) =  s.uid;
            fun gid   (s: Stat) =  s.gid;
            fun size  (s: Stat) =  s.size;
            fun atime (s: Stat) =  s.atime;
            fun mtime (s: Stat) =  s.mtime;
            fun ctime (s: Stat) =  s.ctime;
        };                                                                      # package stat

        # This layout needs to track src/c/lib/posix-file-system/stat.c 
        Statrep
          =
          ( (hi::Int,           #  file type 
             hug::Unt,          #  mode 
             hug::Unt,          #  inode 
             hug::Unt,          #  Devno 
             hug::Unt,          #  nlink 
             hug::Unt,          #  uid 
             hug::Unt,          #  gid 
             ti::Int,           #  size 
             i1w::Int,          #  Atime 
             i1w::Int,          #  mtime 
             i1w::Int)          #  Ctime 
          );

        fun mk_stat (sr:  Statrep)
            =
              {
                ftype =>                  (#1 sr),
                mode  => s::from_unt      (#2 sr),
                inode => hug::to_int (#3 sr),
                dev   => hug::to_int (#4 sr),
                nlink => hug::to_int (#5 sr),   # Probably should be an int in the run-time too.  XXX BUGGO FIXME
                uid =>                    (#6 sr),
                gid =>                    (#7 sr),
                size =>                   (#8 sr),
                atime => tg::from_seconds (iwg::to_multiword_int (#9 sr)),
                mtime => tg::from_seconds (iwg::to_multiword_int (#10 sr)),
                ctime => tg::from_seconds (iwg::to_multiword_int (#11 sr))
              };

        (cfun "stat")                                                                   # stat          def in    src/c/lib/posix-file-system/stat.c
            ->
            (      stat__syscall:    String -> Statrep,
                   stat__ref,
              set__stat__ref
            );


        (cfun "lstat")                                                                  # lstat         def in    src/c/lib/posix-file-system/stat.c
            ->
            (      lstat__syscall:   String -> Statrep,
                   lstat__ref,
              set__lstat__ref
            );


        (cfun "fstat")                                                                  # fstat         def in    src/c/lib/posix-file-system/stat.c
            ->
            (      fstat__syscall:    hi::Int -> Statrep,
                   fstat__ref,
              set__fstat__ref
            );

        fun stat  fname =  mk_stat (*stat__ref   fname);
        fun lstat fname =  mk_stat (*lstat__ref  fname);                                # POSIX 1003.1a 

        fun fstat fd
            =
            mk_stat  (*fstat__ref  fd);

        Access_Mode
            =
            MAY_READ | MAY_WRITE | MAY_EXECUTE;

        a_read  =  w_osval "MAY_READ";          #  R_OK 
        a_write =  w_osval "MAY_WRITE";         #  W_OK 
        a_exec  =  w_osval "MAY_EXECUTE";       #  X_OK 
        a_file  =  w_osval "FILE_EXISTS";       #  F_OK 

        fun amode_to_unt [] =>   a_file;
            #
            amode_to_unt list
                =>
                fold_forward  amtoi  a_file  list
                where
                    fun amtoi (MAY_READ,    v) =>   a_read  | v;
                        amtoi (MAY_WRITE,   v) =>   a_write | v;
                        amtoi (MAY_EXECUTE, v) =>   a_exec  | v;
                    end;
                end;

            
        end;

        (cfun "access")                                                                                 # access        def in    src/c/lib/posix-file-system/access.c
            ->
            (      access__syscall:    (String, hug::Unt) -> Bool,
                   access__ref,
              set__access__ref
            );
        #
        fun access (fname, aml)
            =
            *access__ref  (fname,  amode_to_unt aml);


        (cfun "chmod")                                                                                  # chmod         def in    src/c/lib/posix-file-system/chmod.c
            ->
            (      chmod__syscall:    (String, hug::Unt) -> Void,
                   chmod__ref,
              set__chmod__ref
            );
        #
        fun chmod (fname, m)
            =
            *chmod__ref  (fname,  s::to_unt m);


        (cfun "fchmod")                                                                                 # fchmod        def in    src/c/lib/posix-file-system/fchmod.c
            ->
            (      fchmod__syscall:   (hi::Int, hug::Unt) -> Void,
                   fchmod__ref,
              set__fchmod__ref
            );
        #
        fun fchmod (fd, m)
            =
            *fchmod__ref  (fd,  s::to_unt m);


        (cfun "chown")                                                                                  # chown         def in    src/c/lib/posix-file-system/chown.c
            ->
            (      chown__syscall:    (String, hug::Unt, hug::Unt) -> Void,
                   chown__ref,
              set__chown__ref
            );
        #
        fun chown (fname, uid, gid)
            =
            *chown__ref  (fname, uid, gid);


        (cfun "fchown")                                                                                 # fchown        def in    src/c/lib/posix-file-system/fchown.c
            ->
            (      fchown__syscall:    (hi::Int, hug::Unt, hug::Unt) -> Void,
                   fchown__ref,
              set__fchown__ref
            );
        #
        fun fchown (fd, uid, gid)
            =
            *fchown__ref  (fd_to_int fd,  uid,  gid);


        (cfun "utime")                                                                                  # utime         def in    src/c/lib/posix-file-system/utime.c
            ->
            (      utime__syscall:    (String, i1w::Int, i1w::Int) -> Void,
                   utime__ref,
              set__utime__ref
            );
        #
        fun utime (file, NULL)
                =>
                *utime__ref (file, -1, 0);

            utime (file, THE { actime, modtime } )
                =>
                {   atime =  iwg::from_multiword_int  (tg::to_seconds  actime);
                    mtime =  iwg::from_multiword_int  (tg::to_seconds  modtime);
                    #
                    *utime__ref  (file, atime, mtime);
                };
        end;

        (cfun "pathconf")                                                                               # pathconf      def in    src/c/lib/posix-file-system/pathconf.c
            ->
            (      pathconf__syscall:    (String,  String) -> Null_Or( hug::Unt ),
                   pathconf__ref,
              set__pathconf__ref
            );

        fun pathconf args
            =
            *pathconf__ref  args;


        (cfun "fpathconf")                                                                              # fpathconf     def in    src/c/lib/posix-file-system/pathconf.c
            ->
            (      fpathconf__syscall:    (hi::Int, String) -> Null_Or( hug::Unt ),
                   fpathconf__ref,
              set__fpathconf__ref
            );

        fun fpathconf (fd, s)
            =
            *fpathconf__ref (fd, s);

    };                          #  package posix_file 
end;



Comments and suggestions to: bugs@mythryl.org

PreviousUpNext