File_Sys.sa
Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
-------------------------> GNU Sather - sourcefile <-------------------------
-- Copyright (C) 2000 by K Hopper, University of Waikato, New Zealand --
-- This file is part of the GNU Sather library. It is free software; you may --
-- redistribute and/or modify it under the terms of the GNU Library General --
-- Public License (LGPL) as published by the Free Software Foundation; --
-- either version 2 of the license, or (at your option) any later version. --
-- This library is distributed in the hope that it will be useful, but --
-- WITHOUT ANY WARRANTY without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See Doc/LGPL for more details. --
-- The license text is also available from: Free Software Foundation, Inc., --
-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
--------------> Please email comments to <bug-sather@gnu.org> <--------------
class FILE_SYS < $OPSYS_FILE_SYS
class FILE_SYS < $OPSYS_FILE_SYS is
-- This class provides abstract file system operations using the
-- underlying OS primitives. It provides an intermediate interface between
-- the required library standard functionality and the underlying operating
-- system, so that there is a common syntactic interface to the public
-- routines defined in this class.
-- This version is defined for Posix conformant unix implementations!
-- Reference should be made to Posix specifications for further detail.
-- Version 1.1 Apr 97. Copyright K Hopper, U of Waikato
-- Development History
-- -------------------
-- Date Who By Detail
-- ---- ------ ------
-- 7 Nov 96 kh Original
-- 5 Apr 97 kh Name changed and body filled out
private const Raw_Read : CARD := UNICODE::LATIN_SMALL_LETTER_R.card ;
private const Raw_Binary : CARD := UNICODE::LATIN_SMALL_LETTER_B.card ;
private const Line_Max : CARD := 1023 ; -- unix max!
private shared Mode_Names : ARRAY{STR} ;
private check_modes is
-- This routine is provided to read the mode name strings if this has
-- not already been done.
if void(Mode_Names) then Mode_Names := LIBCHARS::default.file_modes; end;
end ;
raw_open(name : STR) : REFERENCE
pre (name.size > 0)
post true
is
-- This routine attempts to open the named file and return the Operating
-- System specific handle to the file. If unsuccessful then void is
-- returned.
mode : CODE_STR := CODE_STR::create(name.index_lib) +
CHAR_CODE::create(Raw_Read,name.index_lib) +
CHAR_CODE::create(Raw_Binary,name.index_lib) ;
return OS_FILESYS::fopen(name.array_ptr,mode.tgt_str.array_ptr)
end ;
open(name : STR, mode : FILE_MODES) : REFERENCE
pre (name.size > 0) and ~mode.is_nil
post true
is
-- This routine attempts to open the named file and return the Operating
-- System specific handle to the file. If unsuccessful then void is
-- returned.
check_modes ;
return OS_FILESYS::fopen(name.array_ptr,Mode_Names[mode.card - 1].array_ptr)
end ;
create_file(name : STR, mode : FILE_MODES) : REFERENCE
pre (name.size > 0) and ~mode.is_nil
post true
is
-- This routine attempts to create the named file and return the
-- Operating System specific handle to the file. If unsuccessful then
-- void is returned. For this OS this is merely a wrapper for open!
return open(name,mode)
end ;
rename_file(old_name : STR, new_name : STR ) : BOOL
pre exists(old_name) and ~void(new_name) -- and its directory is writable!
post true
is
-- This routine returns true if and only if the attempt to rename
-- the file having the old name was successful.
return OS_FILESYS::rename(old_name.array_ptr,new_name.array_ptr) = INT::zero
end ;
delete_file(name : STR ) : BOOL
pre (name.size > 0) and exists(name) -- and directory is writable
post ~exists(name)
is
-- This routine deletes the named file, returning true if and only if
-- deletion has been successful.
OS_FILESYS::unlink(name.array_ptr) ;
return OS_FILESYS::access(name.array_ptr,0) /= INT::zero
end ;
create_tempfile : REFERENCE
pre true
post ~void(result)
is
-- This routine attempts to create a temporary file and return the
-- Operating System specific handle to the file. If unsuccessful then
-- void is returned.
return OS_FILESYS::tmpfile
end ;
error(fyle : REFERENCE ) : BOOL is
-- This predicate returns true if and only if the latest file operation
-- resulted in an error.
return FUDGE_FILESYS::fyle_error(fyle)
end ;
clearerr(fyle : REFERENCE)
pre ~void(fyle)
post true
is
-- This routine sets the error number to void for the indicated file.
OS_FILESYS::fclearerr(fyle)
end ;
error_msg(fyle : REFERENCE ) : STR
pre ~void(fyle) and error(fyle)
post ~void(result)
is
-- This routine returns an operating system specific string error
-- message using the current repertoire and encoding. This may or may not
-- include the name by which the file is known.
return STR::create_from_external_string(FUDGE_FILESYS::error_message)
end ;
close(fyle : REFERENCE)
pre ~void(fyle)
post true
is
-- This routine closes fyle in an operating system dependent manner.
OS_FILESYS::fclose(fyle)
end ;
open_throw_back : REFERENCE
pre true
post ~void(result)
is
-- This routine attempts to set up the throwback mechanism for error
-- reporting. If this is successfully done then the channel identity is
-- returned, otherwise void.
return void -- temporary fudge!!
end ;
throw(chan : REFERENCE, fyle_ident : STR, msg : STR, warn_only : BOOL )
pre ~void(fyle_ident) and ~void(msg)
post true
is
-- This routine sends the throw-back messsage to the given channel in
-- respect of the given file (identified by its OS dependent name).
end ;
close_throw_back(chan : REFERENCE)
pre ~void(chan)
post true
is
-- This routine closes the throwback channel in an operating system
-- dependent manner.
-- temporary fudge
end ;
exists(name : STR) : BOOL is
-- This predicate returns true if and only if the named file/directory
-- actually exists.
return OS_FILESYS::access(name.array_ptr,0) = INT::zero
end ;
flush(fyle : REFERENCE)
pre ~void(fyle)
post true -- and buffers are empty
is
-- This routine flushes the file buffers as necessary, clearing input
-- buffers and making sure that output buffers have been written out by
-- the underlying operating system.
OS_FILESYS::fflush(fyle)
end ;
flush(chan : REFERENCE, direction : FLUSH_CMDS )
pre ~void(chan)
post true -- and buffers are empty
is
-- This routine flushes the buffers associated with chan in the direction
-- specified. This is identical to the above in this implementation except
-- for the standard input channel which requires a dummy read.
if direction = FLUSH_CMDS::In_Buffer then
dummy : FBINSTR := FBINSTR::create(Line_Max) ;
loc_ref : REFERENCE := OS_FILESYS::fgets(dummy.array_ptr,Line_Max,STD_CHANS::stdin.chan)
else
OS_FILESYS::fflush(chan)
end
end ;
size(fyle : REFERENCE, out size : CARD) : BOOL
pre ~void(fyle)
post true
is
-- This routine returns true if and only if it has been possible to
-- determine the size of the given file - when the out parameter size is
-- valid, otherwise false is returned and size is not valid.
loc_current : INT := OS_FILESYS::ftell(fyle) ;
if loc_current >= INT::zero then
loc_res : INT := OS_FILESYS::fseek(fyle,INT::zero,(FILE_LOCS::End.card - 1)) ;
if loc_res >= INT::zero then
res : INT := OS_FILESYS::ftell(fyle) ;
loc_res := OS_FILESYS::fseek(fyle,loc_current,
(FILE_LOCS::Beginning.card - 1)) ;
size := res.card ;
return true
else
return false
end
else
return false
end
end ;
kind(code_val : CARD ) : FILE_KINDS
pre true
post void(result) or (result.card = code_val)
is
-- This routine provides the OS dependent mapping between the code
-- value returned by some OS service and the portable class FILE_KINDS!
return FILE_KINDS::create(code_val)
end ;
file_type(name : STR, leaf_name : STR ) : STR
pre ~void(leaf_name)
post true
is
-- This routine returns the string name of the file type as known to
-- the operating system.
sep : STR := name.index_lib.Kind_Separator.tgt_str ;
loc_index : CARD := leaf_name.search_backwards(sep[0]) ;
if loc_index.is_nil then
return STR::create
else
return leaf_name.tail(leaf_name.size - (loc_index + sep.size))
end
end ;
set_type( full_name : STR, leaf_name : STR, new_type : STR) : STR
pre ~void(leaf_name) and ~void(new_type)
post (result.size >= leaf_name.size)
is
-- This routine sets the file type of the file (in the current directory)
-- named full_name to have the required new type, returning the resultant
-- leaf name (which may or may not be the same as leaf_name)!
name_part : STR := leaf_name.head(leaf_name.size - 1 - file_type(full_name,leaf_name).size) ;
if new_type.size > 0 then
name_part := name_part + leaf_name.index_lib.Kind_Separator.tgt_str
end ;
return name_part + new_type
end ;
seek(fyle : REFERENCE, offset : INT, relative_to : FILE_LOCS ) : BOOL
pre ~void(fyle)
and ~void(relative_to)
and (((relative_to = FILE_LOCS::Beginning)
and (offset >= INT::zero))
or ((relative_to = FILE_LOCS::End)
and (offset <= INT::zero))
or (relative_to = FILE_LOCS::Current))
post true
is
-- This routine returns true if and only if it has been possible to
-- set the current file position to be offset relative to the given point,
-- otherwise false. Note the dependency on the FILE_LOCS encoding!!!
loc_res : INT := OS_FILESYS::fseek(fyle,offset,(relative_to.card - 1)) ;
return loc_res >= INT::zero
end ;
position(fyle : REFERENCE ) : CARD
pre ~void(fyle)
post true
is
-- This routine returns the file index corresponding to the current
-- position at which reading or writing will take place (in the absence of
-- any intervening seek operation)
loc_res : INT := OS_FILESYS::fseek(fyle,INT::zero,(FILE_LOCS::Current.card - 1)) ;
if loc_res < INT::zero then
return CARD::maxval
else
return loc_res.card
end
end ;
putchar(item : OCTET, chan : REFERENCE ) : BOOL
pre ~void(chan)
post true
is
-- This routine may only be used for text output of a single character
-- to the specified channel.
OS_FILESYS::fputc(item,chan) ;
return ~FUDGE_FILESYS::fyle_error(chan)
end ;
getchar(out item : OCTET, chan : REFERENCE ) : BOOL
pre ~void(chan)
post true
is
-- This routine may only be used for text input of a single octet
-- 'character' from the specified channel.
item := OS_FILESYS::fgetc(chan) ;
return ~FUDGE_FILESYS::fyle_error(chan)
end ;
channel_read(cnt : CARD, chan : REFERENCE ) : FBINSTR
pre ~void(chan)
post true
is
-- This routine reads up to the given number of octets from the indicated
-- channel into the buffer, returning true if successful.
if cnt = 0 then
return void
else
loc_buff : FBINSTR := FBINSTR::create(cnt) ;
loc_ref : REFERENCE := OS_FILESYS::fgets(loc_buff.array_ptr,cnt,chan) ;
if loc_ref.to_int < INT::zero then
return void
else
length : CARD := SATHER_ENGINE::strlen(loc_ref) ;
loc_buff.loc := length ;
return loc_buff
end
end
end ;
file_read(buff : $FSTRINGS, size : CARD, inout cnt : CARD, fyle : REFERENCE) : BOOL
pre ~void(buff) and (size > 0) and ~void(fyle)
post (buff.loc = cnt)
is
-- "cnt" in the buffer
-- This routine returns true if and only if it has been possible to read
-- something from the file specified into the buffer provided. If successful
-- then cnt is set to be the number of items read (NOT the number of bytes!).
loc_res : INT := OS_FILESYS::fread(buff.array_ptr,size,cnt,fyle) ;
if loc_res < INT::zero then
return false
else
cnt := loc_res.card ;
buff.loc := cnt ;
return true
end
end ;
file_read(buff : $FSTRINGS, size : CARD, inout cnt : CARD, offset : CARD, fyle : REFERENCE) : BOOL
pre ~void(buff) and (size > 0) and ~void(fyle) and (buff.octets >= (cnt * size))
post (buff.loc = (cnt * size))
is
-- "cnt" items in the buffer
-- "offset" in the file!
-- This routine returns true if and only if it has been possible to read
-- something from the file specified into the buffer provided starting to
-- read at the given fileoffset. If successful then cnt is set to be the
-- number of items (NOT bytes) read.
if ~seek(fyle,offset.int,FILE_LOCS::Beginning) then return false; end ;
loc_res : INT := OS_FILESYS::fread(buff.array_ptr,size,cnt,fyle);
if loc_res < INT::zero then return false
else
cnt := loc_res.card ;
buff.loc := cnt ;
return true
end
end ;
file_write( buff : REFERENCE, size : CARD, inout cnt : CARD, fyle : REFERENCE) : BOOL
pre ~void(buff) and (size > 0) and ~void(fyle)
post ~result or (cnt = initial(cnt))
is
-- "size" of the item to be written
-- "cnt" No of items to write
-- This routine returns true if and only if all of the specified output
-- data (in the buffer) has been successfully written to the given file. The
-- parameter cnt then indicates the number of items written ----- NOT the
-- number of bytes.
loc_res : INT := OS_FILESYS::fwrite(buff,size,cnt,fyle) ;
if loc_res < INT::zero then return false
else
cnt := loc_res.card ;
return true
end
end ;
file_write( buff : $STRINGS, size : CARD, inout cnt : CARD, fyle : REFERENCE) : BOOL
pre ~void(buff) and (size > 0) and ~void(fyle)
post ~result or (cnt = initial(cnt))
is
-- "size" of the item to be written
-- "cnt" No of items to write
-- This routine returns true if and only if all of the specified output
-- data (in the buffer) has been successfully written to the given file,
-- using the above routine. The parameter cnt then indicates the number of
-- items written -- NOT the number of bytes - unless the size was 1!!
return file_write(buff.array_ptr,size,inout cnt,fyle)
end ;
current_dir( path : STR ) : BOOL
pre (path.size > 0) and exists(path)
post true
is
-- This routine returns true if and only if it has been possible to
-- change the current directory to the one named by path.
return OS_FILESYS::chdir(path.array_ptr) = INT::zero
end ;
current_dir : STR
pre true
post void(result) or (result.size > 0)
is
-- This routine returns the string name of the current working directory
-- in the current repertoire and encoding. If the operation fails then void
-- is returned.
loc_res : REFERENCE := FUDGE_FILESYS::get_cwd ;
if void(loc_res) then return void
else return STR::create_from_external_string(loc_res)
end
end ;
make_dir( name : STR, access_code : ACCESS_SET ) : BOOL
pre (name.size > 0) and ~exists(name) and ~access_code.is_empty
post true
is
-- This routine returns true if and only if its attempt to create
-- a directory with the given name and access permissions was successful.
return OS_FILESYS::mkdir(name.array_ptr,CARD::create(access_code.binstr)) = INT::zero
end ;
delete_dir(name : STR) : BOOL
pre (name.size > 0) and exists(name)
post true
is
-- This routine returns true if and only if the attempt to delete
-- the named directory was successful.
return OS_FILESYS::rmdir(name.array_ptr) = INT::zero
end ;
open_dir( name : STR ) : REFERENCE
pre (name.size > 0) and exists(name)
post true
is
-- This routine returns the operating system provided handle for
-- the directory object. If the attempt was unsuccessful then void
-- is returned.
res : INT := OS_FILESYS::opendir(name.array_ptr) ;
if res = INT::zero then return void
else return REFERENCE::create_from_value(res)
end
end ;
close_dir( handle : REFERENCE ) : BOOL
pre ~void(handle)
post true
is
-- This routine returns true if and only if the attempt to close
-- the indicated directory was successful.
OS_FILESYS::closedir(handle) ;
return true
end ;
rewind_dir(handle : REFERENCE, out offset : CARD): BOOL
pre ~void(handle)
post true
is
-- This routine returns true if and only if the attempt to rewind
-- the indicated directory was successful.
-- OS_FILESYS::fclearerr(handle) ;
OS_FILESYS::rewinddir(handle) ;
offset := 0 ;
-- return ~FUDGE_FILESYS::fyle_error(handle)
return true;
end ;
read_dir(handle : REFERENCE, inout offset : CARD) : STR
pre ~void(handle)
post void(result) or ((initial(offset) + 1) = offset)
is
-- This routine returns the string provided by the operating system
-- if there is another sequential entry in the directory, otherwise void.
loc_res : REFERENCE := FUDGE_FILESYS::read_dir(handle) ;
if void(loc_res) then
return void
else
offset := offset + 1 ;
return STR::create_from_external_string(loc_res)
end
end ;
rename_dir( old_name, new_name : STR) : BOOL
pre ~void(old_name) and exists(old_name) and ~void(new_name) and ~exists(new_name)
post true
is
-- This routine returns true if and only if the attempt to rename
-- the directory having the old name was successful.
return OS_FILESYS::rename(old_name.array_ptr,new_name.array_ptr) = INT::zero
end ;
get_label(name : STR, label : REFERENCE) : BOOL
pre (name.size > 0) and exists(name)
post true
is
-- This routine fills in the file label tuple and if this was possible
-- then returns true, otherwise false and label is not set.
return (OS_FILESYS::stat(name.array_ptr,label) = INT::zero)
end ;
set_times(name : STR, utime, mtime : TIME_STAMP) : BOOL
pre (name.size > 0) and exists(name) -- and directory can be written to!
post true
is
-- This routine attempts to set the update and access times for the
-- named file, returning true if this was possible, otherwise false and no
-- change has been effected.
tim ::= TUP{TIME_STAMP,TIME_STAMP}::create(utime,mtime) ;
tim_ref : REFERENCE := REFERENCE::create_from_object(tim) ;
return OS_FILESYS::utime(name.array_ptr,tim_ref) = INT::zero
end ;
change_owner(name : STR, owner : USER, which : GROUP) : BOOL
pre (name.size > 0) and exists(name) -- and directory can be written to!
post true
is
-- This routine attempts to alter the owner and project group of the
-- named file, returning true if successful , otherwise false and no change
-- has been effected.
return (OS_FILESYS::chown(name.array_ptr,owner.card,which.card) = INT::zero)
end ;
change_access(name : STR, access_mask : ACCESS_SET) : BOOL
pre (name.size > 0) and exists(name) -- and directory can be written to!
-- and ~void(access_mask) ! ACCESS_SET is immutable!!
post true
is
-- This routine attempts to alter the access permissions for the named
-- file. The mask should have an element CLEARED if that permission is to
-- be allowed!
return (OS_FILESYS::chmod(name.array_ptr,CARD::create(access_mask.binstr)) = INT::zero)
end ;
end ; -- FILE_SYS
external C class OS_FILESYS is
-- This external class defines the interface to the underlying operating
-- system services which are defined in the corresponding c file os_filesys.
-- This version is defined for Posix conformant unix implementations!
-- Reference should be made to Posix specifications for further detail.
-- Version 1.0 Apr 97. Copyright K Hopper,U of Waikato
-- Development History
-- -------------------
-- Date Who By Detail
-- ---- ------ ------
-- 18 Apr 97 kh Original for portability.
errno : CARD ; -- This returns an OS-dependent error code number.
-- The following five routines are part of the Sather run-time
-- engine and should normally only be used in that.
fopen( name : REFERENCE, open_mode : REFERENCE) : REFERENCE ;
-- This routine attempts to open the files named for the operations
-- specified in the mode string. If void is returned the operation has
-- failed, otherwise the OS-dependent file handle is returned.
tmpfile : REFERENCE ;
-- This routine creates a temporary file in an OS-dependent manner and
-- returns the file handle to it.
fclose(fyle : REFERENCE) ;
-- This routine closes the file having the given handle.
fseek(fyle : REFERENCE, offset : INT, relative_to : CARD) : INT ;
-- This routine seeks to the given offset from the relative position
-- indicated, returning the position relative to the beginning of the file
-- if successful, otherwise -1.
ftell(fyle : REFERENCE) : INT ;
-- This routine returns the size of the file with the given handle
-- in octets or -1 if it does not exist.
fgets(buff : REFERENCE, size : CARD, chan : REFERENCE) : REFERENCE ;
-- This routine fills buff with a string of up to size octets from the
-- indicated channel returning the number of octets found or -1 if an error
-- has occurred.
fread(buff : REFERENCE, size, items : CARD, fyle : REFERENCE ) : INT ;
-- This routine attempts to read size items into buff from the given
-- file, returning the number read if successful or -1 if some error occurred.
fwrite(buff : REFERENCE, size, items : CARD, fyle : REFERENCE ) : INT ;
-- This routine attempts to write size items to the indicated file from
-- the buffer, returning the number of octets written if successful,
-- otherwise -1.
fclearerr( fyle : REFERENCE) ;
-- This routine clears the error status for the indicated file.
fputc(oct : OCTET, fyle : REFERENCE) ;
-- This routine puts a single octet into the indicated file.
fgetc(fyle : REFERENCE) : OCTET ;
-- This routine returns a single octet from the indicated file.
fflush( fyle : REFERENCE) ;
-- This routine flushes the OS buffer associated with the file
-- indicated. If the file is currently being written to then the data will
-- be sent to the file, otherwise the buffer will be emptied.
setbuffer(fyle : REFERENCE, buff : REFERENCE, size : CARD) ;
-- This routine sets buff (of the given size) for use by the operating
-- system when reading/writing from/to the indicated file.
mkdir(name : REFERENCE, permissions : CARD) : INT ;
-- This routine attempts to create a directory with the given name and
-- permissions (considered by the OS as a bit-set).
rmdir(name : REFERENCE) : INT ;
-- This routine attempts to delete the named directory, returning 0
-- if successul,
chdir(name : REFERENCE) : INT ;
-- This routine attempts to make the new current directory the one
-- named, returning zero only if successful.
opendir(name : REFERENCE) : INT ;
-- This routine attempts to open the named directory, returning a handle
-- to it. The directory is positioned at the first entry. If this fails
-- then void is returned.
closedir(handle : REFERENCE) ;
-- This routine closes the indicated directory.
rewinddir(handle : REFERENCE) ;
-- This routine rewinds the indicated directory so that the next read
-- will yield the first item (again).
unlink(name : REFERENCE) ;
-- This routine attempts to remove a file of the given name.
tempnam(dir : REFERENCE, prefix : REFERENCE) : REFERENCE ;
-- This routine attempts to return a name for the temporary file
-- indicated (which has a leaf string prefixed as given)
remove(name : REFERENCE) : INT ;
-- This routine attempts to remove the named file from the filing system.
rename( to, from : REFERENCE ) : INT ;
-- This routine attempts to rename the file called to to be called from,
-- returning zero if successful.
access( name : REFERENCE, reason : CARD) : INT ;
-- This routine determines whether or not the program has permission to
-- carry out the indicated operation on the named file. Zero is returned
-- if successful.
utime(name : REFERENCE, file_times : REFERENCE) : INT ;
-- This routine attempts to alter the modified and last accessed times
-- of the named file to be the values given, returning zero if successful.
ioctl(chan : INT, request : INT, arg : INT) : INT ;
-- This routine is the standard Unix one for performing a wide variety
-- of actions in respect of a device -- the given channel. The request code
-- may indicate that the argument is not needed, some numeric code or even
-- the address of some data structure. Zero is returned if the action is
-- successful.
stat(name : REFERENCE, tuple : REFERENCE) : INT ;
-- This routine returns the file 'label' information or void if that
-- is not available.
chown(name : REFERENCE, owner : CARD, group : CARD) : INT ;
-- This routine attempts to change the ownership of a file, returning
-- zero if successful.
chmod(name : REFERENCE, mode : CARD) : INT ;
-- This routine attempts to set the permissions for a file (mode is
-- actually an access-set mask), returning zero if successful.
end ; -- OS_FILESYS
external C class FUDGE_FILESYS is
-- This external class defines the interface to underlying operating
-- system interface routines needed by this implementation.
-- Version 1.0 Feb 99. Copyright K Hopper,U of Waikato
-- Development History
-- -------------------
-- Date Who By Detail
-- ---- ------ ------
-- 25 Feb 99 kh Original separated from OS_FILESYS
fyle_error(fyle : REFERENCE) : BOOL ;
-- This routine returns true if and only if an uncleared error has
-- occurred when performing some action on the indicated file.
error_message : REFERENCE ;
-- This returns an OS-dependent message string corresponding to the
-- most recently reported error.
get_cwd : REFERENCE ;
-- This routine returns a reference to an OS-provided buffer containing
-- the string name of the current working directory.
read_dir(handle : REFERENCE) : REFERENCE ;
-- This routine attempts to read the name of an entry in the given
-- directory, returning it as a C string, otherwise void!
end ; -- FUDGE_FILESYS