last_error = null
_file = new NativeFile.io_open_read(path.to_cstring)
if _file.address_is_null then
- last_error = new IOError("Error: Opening file at '{path.as(not null)}' failed with '{sys.errno.strerror}'")
+ last_error = new IOError("Cannot open `{path.as(not null)}`: {sys.errno.strerror}")
end_reached = true
return
end
redef fun fill_buffer
do
var nb = _file.io_read(_buffer, _buffer_capacity)
+ if last_error == null and _file.ferror then
+ last_error = new IOError("Cannot read `{path.as(not null)}`: {sys.errno.strerror}")
+ end_reached = true
+ end
if nb <= 0 then
end_reached = true
nb = 0
prepare_buffer(10)
_file = new NativeFile.io_open_read(path.to_cstring)
if _file.address_is_null then
- last_error = new IOError("Error: Opening file at '{path}' failed with '{sys.errno.strerror}'")
+ last_error = new IOError("Cannot open `{path}`: {sys.errno.strerror}")
end_reached = true
end
end
end_reached = true
end
end
+
+ redef fun poll_in
+ do
+ var res = native_poll_in(fd)
+ if res == -1 then
+ last_error = new IOError(errno.to_s)
+ return false
+ else return res > 0
+ end
+
+ private fun native_poll_in(fd: Int): Int `{
+ struct pollfd fds = {fd, POLLIN, 0};
+ return poll(&fds, 1, 0);
+ `}
end
# `Stream` that can write to a File
self.path = path
_is_writable = true
if _file.address_is_null then
- last_error = new IOError("Error: Opening file at '{path}' failed with '{sys.errno.strerror}'")
+ last_error = new IOError("Cannot open `{path}`: {sys.errno.strerror}")
is_writable = false
end
end
path = "/dev/stdin"
prepare_buffer(1)
end
-
- redef fun poll_in `{
- struct pollfd fd = {0, POLLIN, 0};
- int res = poll(&fd, 1, 0);
- if (res == -1) {
- perror("Error poll stdin");
- exit(EXIT_FAILURE);
- }
- return res > 0;
- `}
end
# Standard output stream.
# var path = "/tmp/somefile".to_path
# assert path.filename == "somefile"
# ~~~
+ #
+ # The result does not depend of the file system, thus is cached for efficiency.
var filename: String = path.basename is lazy
+ # The path simplified by removing useless `.`, removing `//`, and resolving `..`
+ #
+ # ~~~
+ # var path = "somedir/./tmp/../somefile".to_path
+ # assert path.simplified.to_s == "somedir/somefile"
+ # ~~~
+ #
+ # See `String:simplify_path` for details.
+ #
+ # The result does not depend of the file system, thus is cached for efficiency.
+ var simplified: Path is lazy do
+ var res = path.simplify_path.to_path
+ res.simplified = res
+ return res
+ end
+
+ # Return the directory part of the path.
+ #
+ # ~~~
+ # var path = "/foo/bar/baz".to_path
+ # assert path.dir.to_s == "/foo/bar"
+ # assert path.dir.dir.to_s == "/foo"
+ # assert path.dir.dir.dir.to_s == "/"
+ # ~~~
+ #
+ # See `String:dirname` for details.
+ #
+ # The result does not depend of the file system, thus is cached for efficiency.
+ var dir: Path is lazy do
+ return path.dirname.to_path
+ end
+
# Last error produced by I/O operations.
#
# ~~~
end
end
- redef fun ==(other) do return other isa Path and path.simplify_path == other.path.simplify_path
- redef fun hash do return path.simplify_path.hash
+ redef fun ==(other) do return other isa Path and simplified.path == other.simplified.path
+ redef fun hash do return simplified.path.hash
end
# Information on a file
private fun write_native_to(s: FileWriter)
do
- for i in substrings do s.write_native(i.to_cstring, 0, i.length)
+ for i in substrings do s.write_native(i.to_cstring, 0, i.bytelen)
end
end
redef class FlatString
redef fun write_native_to(s)
do
- s.write_native(items, index_from, length)
+ s.write_native(items, first_byte, bytelen)
end
end
return 0;
`}
+ fun ferror: Bool `{ return ferror(self); `}
+
fun fileno: Int `{ return fileno(self); `}
# Flushes the buffer, forcing the write operation