


## 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.pkgherein
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;


