PreviousUpNext

15.4.1120  src/lib/std/src/posix-1003.1b/posix-file.pkg

## posix-file.pkg

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



# Package for POSIX 1003.1 file system operations
# This is a subpackage of the POSIX 1003.1 based
# 'Posix' package
#
#     src/lib/std/src/posix-1003.1b/posix-1003-1b.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



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



stipulate
    package host_unt =  host_unt_guts;                                                  # host_unt_guts                         is from   src/lib/std/src/bind-sysword-32.pkg
    #
    # 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/bind-int-32.pkg
    #
    package one_word_unt    =  one_word_unt_guts;                                       # one_word_unt_guts                     is from   src/lib/std/src/one-word-unt-guts.pkg
    package time    =  time_guts;                                                       # time_guts                             is from   src/lib/std/src/time-guts.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
herein

    package posix_file # : Posix_File                                                   # Posix_File                            is from   src/lib/std/src/posix-1003.1b/posix-file.api
    {

        my (|) =  host_unt::bitwise_or;
        my (&) =  host_unt::bitwise_and;

   #    infix val  | & ;

                                                                                        # host_int                              is from   src/lib/std/src/posix-1003.1b/posix-prelude.pkg
        fun cfun  fun_name
            =
            ci::find_c_function { lib_name => "posix_filesys",  fun_name };


        osval =   cfun "osval":   String -> host_int::Int;                              # osval                                 def in    src/c/lib/posix-file-system/osval.c

        w_osval = host_unt::from_int o osval;

        User_Id  =  host_unt::Unt;
        Group_Id =  host_unt::Unt;

        File_Descriptor = host_int::Int;


        fun fd_to_int  fd
            =
            fd;


        fun int_to_fd  fd
            =
            fd;


                                                            # winix_types                               is from   src/lib/std/src/posix/winix-types.pkg

        #  Conversions between winix::io::Io_Descriptor values and Posix file descriptors. 
        #
        fun fd_to_iod  fd
            =
            winix_types::io::int_to_iod  fd;


        fun iod_to_fd iod
            =
            winix_types::io::iod_to_fd  iod;

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

        include posix_common;

        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 FAIL ("posix_file::omodeFromUnt: unknown mode " + (one_word_unt::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 = runtime::Chunk;  #  the underlying C DIRSTREAM 

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

        opendir'   =  cfun "opendir"  :  String -> Ckit_Dirstream;              # opendir       def in    src/c/lib/posix-file-system/opendir.c
        readdir'   =  cfun "readdir"  :  Ckit_Dirstream -> String;              # readdir       def in    src/c/lib/posix-file-system/readdir.c
        rewinddir' =  cfun "rewinddir":  Ckit_Dirstream -> Void  ;              # rewinddir     def in    src/c/lib/posix-file-system/rewinddir.c
        closedir'  =  cfun "closedir" :  Ckit_Dirstream -> Void  ;              # closedir      def in    src/c/lib/posix-file-system/closedir.c

        fun open_directory_stream  path
            =
            DIRECTORY_STREAM
              {
                dir_strm =>  opendir' path,
                is_open  =>  REF( TRUE )
              };


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

            read_directory_entry (DIRECTORY_STREAM { dir_strm, ... } )
                =>
                case (readdir' dir_strm)
                    #
                    ""   =>  NULL;
                    name =>  THE name;
                esac;
        end;


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

            rewind_directory_stream (DIRECTORY_STREAM { dir_strm, ... } )
                =>
               rewinddir' dir_strm;
        end;


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

            close_directory_stream (DIRECTORY_STREAM { dir_strm, is_open } )
                =>
                {   is_open :=  FALSE;
                    #
                    closedir'  dir_strm;
                };
        end;

        change_directory  =  cfun "chdir" :  String -> Void;                    # chdir         def in    src/c/lib/posix-file-system/chdir.c
        current_directory =  cfun "getcwd":  Void -> String;                    # getcwd        def in    src/c/lib/posix-file-system/getcwd.c

        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  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 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;

        };

        openf' =  cfun "openf":  (String, host_unt::Unt, host_unt::Unt) -> host_int::Int;                       # openf                 def in    src/c/lib/posix-file-system/openf.c

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


        mkstemp' =  cfun "mkstemp":  Void -> host_int::Int;                                                     # Opens a temporary file and returns the fd -- see man 3 mkfstemp
                                                                                                                # mkstemp               def in    src/c/lib/posix-file-system/mkstemp.c

        fun mkstemp ()
            =
            int_to_fd (mkstemp' ());


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

                int_to_fd (openf' (fname, flags, s::to_unt mode));
            };


        fun creat (fname, mode)
            =
            int_to_fd (openf'(fname, o::crflags, s::to_unt mode));


        umask' =  cfun "umask":   host_unt::Unt -> host_unt::Unt;                                               # umask                 def in    src/c/lib/posix-file-system/umask.c
        #
        fun umask mode
            =
            s::from_unt (umask' (s::to_unt mode));

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

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

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

        mkdir' =   cfun "mkdir":   (String, host_unt::Unt) -> Void;                                             # mkdir                 def in    src/c/lib/posix-file-system/mkdir.c
        #
        fun mkdir (dirname, mode)
            =
            mkdir'(dirname, s::to_unt mode);

        make_named_pipe' =   cfun "mkfifo":   (String, host_unt::Unt) -> Void;                                  # mkfifo                def in    src/c/lib/posix-file-system/mkfifo.c
        #
        fun make_named_pipe (name, mode)
            =
            make_named_pipe'( name, s::to_unt mode );

        unlink     =  cfun "unlink"   :  String -> Void   ;                                                     # unlink                def in    src/c/lib/posix-file-system/unlink.c
        rmdir      =  cfun "rmdir"    :  String -> Void   ;                                                     # rmdir                 def in    src/c/lib/posix-file-system/rmdir.c
        readlink   =  cfun "readlink" :  String -> String ;                                                     # readlink              def in    src/c/lib/posix-file-system/readlink.c

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

        Device = host_unt::Unt;
        fun dev_to_unt (i) = i;
        fun unt_to_dev i = i;

        Inode = host_unt::Unt;
        fun ino_to_unt (i) = i;
        fun unt_to_ino i = i;

        package stat {
            #
            Stat = { ftype:  host_int::Int,
                     mode:   s::Flags,
                     inode:  Int,
                     dev:    Int,
                     nlink:  Int,
                     uid:    host_unt::Unt,
                     gid:    host_unt::Unt,
                     size:   file_position::Int,
                     atime:  time::Time,
                     mtime:  time::Time,
                     ctime:  time::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
          =
          ( (host_int::Int,             #  file type 
             host_unt::Unt,             #  mode 
             host_unt::Unt,             #  inode 
             host_unt::Unt,             #  Devno 
             host_unt::Unt,             #  nlink 
             host_unt::Unt,             #  uid 
             host_unt::Unt,             #  gid 
             tagged_int::Int,           #  size 
             one_word_int::Int,         #  Atime 
             one_word_int::Int,         #  mtime 
             one_word_int::Int)         #  Ctime 
          );

        fun mk_stat (sr:  Statrep)
            =
              {
                ftype =>                  (#1 sr),
                mode  => s::from_unt      (#2 sr),
                inode => host_unt::to_int (#3 sr),
                dev   => host_unt::to_int (#4 sr),
                nlink => host_unt::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 => time::from_seconds (one_word_int_guts::to_multiword_int (#9 sr)),
                mtime => time::from_seconds (one_word_int_guts::to_multiword_int (#10 sr)),
                ctime => time::from_seconds (one_word_int_guts::to_multiword_int (#11 sr))
              };

        stat'  =   cfun "stat" :          String -> Statrep;                            # stat          def in    src/c/lib/posix-file-system/stat.c
        lstat' =   cfun "lstat":          String -> Statrep;                            # lstat         def in    src/c/lib/posix-file-system/stat.c
        fstat' =   cfun "fstat":   host_int::Int -> Statrep;                            # fstat         def in    src/c/lib/posix-file-system/stat.c

        fun stat  fname =  mk_stat (stat' fname);
        fun lstat fname =  mk_stat (lstat' fname);                                      # POSIX 1003.1a 

        fun fstat fd
            =
            mk_stat (fstat' 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 l
                =>
                {   fun amtoi (MAY_READ,    v) =>   a_read  | v;
                        amtoi (MAY_WRITE,   v) =>   a_write | v;
                        amtoi (MAY_EXECUTE, v) =>   a_exec  | v;
                    end;

                    list::fold_left
                        amtoi
                        a_file
                        l;
                };
        end;

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


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


        fchmod' =  cfun "fchmod":   (host_int::Int, host_unt::Unt) -> Void;                                     # fchmod        def in    src/c/lib/posix-file-system/fchmod.c
        #
        fun fchmod (fd, m)
            =
            fchmod'(fd, s::to_unt m);


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


        fchown' =  cfun "fchown":   (host_int::Int, host_unt::Unt, host_unt::Unt) -> Void;                      # fchown        def in    src/c/lib/posix-file-system/fchown.c
        #
        fun fchown (fd, uid, gid)
            =
            fchown'(fd_to_int fd, uid, gid);


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

            utime (file, THE { actime, modtime } )
                =>
                {   atime =  one_word_int_guts::from_multiword_int  (time::to_seconds  actime);
                    mtime =  one_word_int_guts::from_multiword_int  (time::to_seconds  modtime);
                    #
                    utime'(file, atime, mtime);
                };
        end;

        pathconf   =   cfun  "pathconf":   (String,        String) -> Null_Or( host_unt::Unt );                 # pathconf      def in    src/c/lib/posix-file-system/pathconf.c
        fpathconf' =   cfun "fpathconf":   (host_int::Int, String) -> Null_Or( host_unt::Unt );                 # fpathconf     def in    src/c/lib/posix-file-system/pathconf.c

        fun fpathconf (fd, s)
            =
            fpathconf' (fd, s);

    };                          #  package posix_file 
end;



Comments and suggestions to: bugs@mythryl.org

PreviousUpNext