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