# Return null in case of error
fun file_stat: nullable FileStat
do
- var stat = _file.file_stat
+ var stat = _file.as(not null).file_stat
if stat.address_is_null then return null
return new FileStat(stat)
end
# File descriptor of this file
- fun fd: Int do return _file.fileno
+ fun fd: Int do return _file.as(not null).fileno
redef fun close
do
- if _file == null then return
- if _file.address_is_null then
+ var file = _file
+ if file == null then return
+ if file.address_is_null then
if last_error != null then return
last_error = new IOError("Cannot close unopened file")
return
end
- var i = _file.io_close
+ var i = file.io_close
if i != 0 then
last_error = new IOError("Close failed due to error {sys.errno.strerror}")
end
# * `buffer_mode_none`
fun set_buffering_mode(buf_size, mode: Int) do
if buf_size <= 0 then buf_size = 512
- if _file.set_buffering_type(buf_size, mode) != 0 then
+ if _file.as(not null).set_buffering_type(buf_size, mode) != 0 then
last_error = new IOError("Error while changing buffering type for FileStream, returned error {sys.errno.strerror}")
end
end
# assert l == f.read_line
fun reopen
do
- if not eof and not _file.address_is_null then close
+ if not eof and not _file.as(not null).address_is_null then close
last_error = null
- _file = new NativeFile.io_open_read(path.to_cstring)
- if _file.address_is_null then
+ _file = new NativeFile.io_open_read(path.as(not null).to_cstring)
+ if _file.as(not null).address_is_null then
last_error = new IOError("Cannot open `{path.as(not null)}`: {sys.errno.strerror}")
end_reached = true
return
redef fun fill_buffer
do
- var nb = _file.io_read(_buffer, _buffer_capacity)
- if last_error == null and _file.ferror then
+ var nb = _file.as(not null).io_read(_buffer, _buffer_capacity)
+ if last_error == null and _file.as(not null).ferror then
last_error = new IOError("Cannot read `{path.as(not null)}`: {sys.errno.strerror}")
end_reached = true
end
self.path = path
prepare_buffer(100)
_file = new NativeFile.io_open_read(path.to_cstring)
- if _file.address_is_null then
+ if _file.as(not null).address_is_null then
last_error = new IOError("Cannot open `{path}`: {sys.errno.strerror}")
end_reached = true
end
self.path = ""
prepare_buffer(1)
_file = fd.fd_to_stream(read_only)
- if _file.address_is_null then
+ if _file.as(not null).address_is_null then
last_error = new IOError("Error: Converting fd {fd} to stream failed with '{sys.errno.strerror}'")
end_reached = true
end
end
private fun native_poll_in(fd: Int): Int `{
- struct pollfd fds = {fd, POLLIN, 0};
+ struct pollfd fds = {(int)fd, POLLIN, 0};
return poll(&fds, 1, 0);
`}
end
last_error = new IOError("Cannot write to non-writable stream")
return
end
- if _file.address_is_null then
+ if _file.as(not null).address_is_null then
last_error = new IOError("Writing on a null stream")
_is_writable = false
return
end
- var err = _file.write_byte(value)
+ var err = _file.as(not null).write_byte(value)
if err != 1 then
# Big problem
last_error = new IOError("Problem writing a byte: {err}")
last_error = new IOError("Cannot write to non-writable stream")
return
end
- if _file.address_is_null then
+ if _file.as(not null).address_is_null then
last_error = new IOError("Writing on a null stream")
_is_writable = false
return
end
- var err = _file.io_write(native, from, len)
+ var err = _file.as(not null).io_write(native, from, len)
if err != len then
# Big problem
last_error = new IOError("Problem in writing : {err} {len} \n")
_file = new NativeFile.io_open_write(path.to_cstring)
self.path = path
_is_writable = true
- if _file.address_is_null then
+ if _file.as(not null).address_is_null then
last_error = new IOError("Cannot open `{path}`: {sys.errno.strerror}")
is_writable = false
end
self.path = ""
_file = fd.fd_to_stream(wipe_write)
_is_writable = true
- if _file.address_is_null then
+ if _file.as(not null).address_is_null then
last_error = new IOError("Error: Opening stream from file descriptor {fd} failed with '{sys.errno.strerror}'")
_is_writable = false
end
#
# NOTE: The `mode` specified must be compatible with the one used in the file descriptor.
private fun fd_to_stream(mode: NativeString): NativeFile `{
- return fdopen(self, mode);
+ return fdopen((int)self, mode);
`}
end
var output = dest.open_wo
while not input.eof do
- var buffer = input.read(1024)
- output.write buffer
+ var buffer = input.read_bytes(1024)
+ output.write_bytes buffer
end
input.close
return res
end
+ # Is `self` the path to an existing directory ?
+ #
+ # ~~~nit
+ # assert ".".to_path.is_dir
+ # assert not "/etc/issue".to_path.is_dir
+ # assert not "/should/not/exist".to_path.is_dir
+ # ~~~
+ fun is_dir: Bool do
+ var st = stat
+ if st == null then return false
+ return st.is_dir
+ end
+
# Delete a directory and all of its content
#
# Does not go through symbolic links and may get stuck in a cycle if there
# Create a directory (and all intermediate directories if needed)
#
+ # The optional `mode` parameter specifies the permissions of the directory,
+ # the default value is `0o777`.
+ #
# Return an error object in case of error.
#
# assert "/etc/".mkdir != null
- fun mkdir: nullable Error
+ fun mkdir(mode: nullable Int): nullable Error
do
+ mode = mode or else 0o777
+
var dirs = self.split_with("/")
var path = new FlatBuffer
if dirs.is_empty then return null
if d.is_empty then continue
path.append(d)
path.add('/')
- var res = path.to_s.to_cstring.file_mkdir
+ var res = path.to_s.to_cstring.file_mkdir(mode)
if not res and error == null then
error = new IOError("Cannot create directory `{path}`: {sys.errno.strerror}")
end
redef fun file_extension do
var its = _items
- var p = _last_byte
+ var p = last_byte
var c = its[p]
var st = _first_byte
while p >= st and c != '.'.ascii do
c = its[p]
end
if p <= st then return null
- var ls = _last_byte
- return new FlatString.with_infos(its, ls - p, p + 1, ls)
+ var ls = last_byte
+ return new FlatString.with_infos(its, ls - p, p + 1)
end
redef fun basename(extension) do
- var l = _last_byte
+ var l = last_byte
var its = _items
var min = _first_byte
var sl = '/'.ascii
if l == min then return "/"
var ns = l
while ns >= min and its[ns] != sl do ns -= 1
- var bname = new FlatString.with_infos(its, l - ns, ns + 1, l)
+ var bname = new FlatString.with_infos(its, l - ns, ns + 1)
return if extension != null then bname.strip_extension(extension) else bname
end
return stat_element;
`}
- private fun file_mkdir: Bool `{ return !mkdir(self, 0777); `}
+ private fun file_mkdir(mode: Int): Bool `{ return !mkdir(self, mode); `}
private fun rmdir: Bool `{ return !rmdir(self); `}
fun flush: Int `{ return fflush(self); `}
# Used to specify how the buffering will be handled for the current stream.
- fun set_buffering_type(buf_length: Int, mode: Int): Int `{
- return setvbuf(self, NULL, mode, buf_length);
+ fun set_buffering_type(buf_length, mode: Int): Int `{
+ return setvbuf(self, NULL, (int)mode, buf_length);
`}
new io_open_read(path: NativeString) `{ return fopen(path, "r"); `}
int first_polled_fd = -1;
int result;
- in_len = Array_of_Int_length( in_fds );
- out_len = Array_of_Int_length( out_fds );
+ in_len = (int)Array_of_Int_length( in_fds );
+ out_len = (int)Array_of_Int_length( out_fds );
total_len = in_len + out_len;
c_fds = malloc( sizeof(struct pollfd) * total_len );
/* input streams */
for ( i=0; i<in_len; i ++ ) {
- int fd;
- fd = Array_of_Int__index( in_fds, i );
+ int fd = (int)Array_of_Int__index( in_fds, i );
c_fds[i].fd = fd;
c_fds[i].events = POLLIN;
/* output streams */
for ( i=0; i<out_len; i ++ ) {
- int fd;
- fd = Array_of_Int__index( out_fds, i );
+ int fd = (int)Array_of_Int__index( out_fds, i );
c_fds[i].fd = fd;
c_fds[i].events = POLLOUT;