redef var is_writable = false
# Write `len` bytes from `native`.
- private fun write_native(native: NativeString, from, len: Int)
+ private fun write_native(native: CString, from, len: Int)
do
if last_error != null then return
if not _is_writable then
# Creates a file stream from a file descriptor `fd` using the file access `mode`.
#
# NOTE: The `mode` specified must be compatible with the one used in the file descriptor.
- private fun fd_to_stream(mode: NativeString): NativeFile `{
+ private fun fd_to_stream(mode: CString): NativeFile `{
return fdopen((int)self, mode);
`}
end
# Constant for read-only file streams
-private fun read_only: NativeString do return once "r".to_cstring
+private fun read_only: CString do return once "r".to_cstring
# Constant for write-only file streams
#
# If a stream is opened on a file with this method,
# it will wipe the previous file if any.
# Else, it will create the file.
-private fun wipe_write: NativeString do return once "w".to_cstring
+private fun wipe_write: CString do return once "w".to_cstring
###############################################################################
return st.is_dir
end
- # Delete a directory and all of its content
+ # Recursively delete a directory and all of its content
#
# Does not go through symbolic links and may get stuck in a cycle if there
# is a cycle in the file system.
#
- # `last_error` is updated to contains the error information on error, and null on success.
- # The method does not stop on the first error and try to remove most file and directories.
+ # `last_error` is updated with the first encountered error, or null on success.
+ # The method does not stop on the first error and tries to remove the most files and directories.
#
# ~~~
# var path = "/does/not/exists/".to_path
# path.rmdir
# assert path.last_error != null
+ #
+ # path = "/tmp/path/to/create".to_path
+ # path.to_s.mkdir
+ # assert path.exists
+ # path.rmdir
+ # assert path.last_error == null
# ~~~
fun rmdir
do
- last_error = null
+ var first_error = null
for file in self.files do
var stat = file.link_stat
if stat == null then
- last_error = file.last_error
+ if first_error == null then first_error = file.last_error
continue
end
if stat.is_dir then
else
file.delete
end
- if last_error == null then last_error = file.last_error
+ if first_error == null then first_error = file.last_error
end
# Delete the directory itself if things are fine
- if last_error == null then
- if path.to_cstring.rmdir then
- last_error = new IOError("Cannot remove `{self}`: {sys.errno.strerror}")
+ if first_error == null then
+ if not path.to_cstring.rmdir then
+ first_error = new IOError("Cannot remove `{self}`: {sys.errno.strerror}")
end
end
+ self.last_error = first_error
end
redef fun ==(other) do return other isa Path and simplified.path == other.simplified.path
do
for i in substrings do s.write_native(i.to_cstring, 0, i.byte_length)
end
-end
-redef class String
# return true if a file with this names exists
fun file_exists: Bool do return to_cstring.file_exists
+end
+redef class String
# The status of a file. see POSIX stat(2).
fun file_stat: nullable FileStat
do
path.add('/')
end
var error: nullable Error = null
- for d in dirs do
+ for i in [0 .. dirs.length - 1[ do
+ var d = dirs[i]
if d.is_empty then continue
path.append(d)
path.add('/')
- var res = path.to_s.to_cstring.file_mkdir(mode)
+ if path.file_exists then continue
+ var res = path.to_cstring.file_mkdir(mode)
if not res and error == null then
error = new IOError("Cannot create directory `{path}`: {sys.errno.strerror}")
end
end
+ var res = self.to_cstring.file_mkdir(mode)
+ if not res and error == null then
+ error = new IOError("Cannot create directory `{path}`: {sys.errno.strerror}")
+ end
return error
end
end
end
-redef class NativeString
+redef class CString
private fun file_exists: Bool `{
#ifdef _WIN32
DWORD attribs = GetFileAttributesA(self);
private fun file_chdir: Bool `{ return !chdir(self); `}
- private fun file_realpath: NativeString `{
+ private fun file_realpath: CString `{
#ifdef _WIN32
DWORD len = GetFullPathName(self, 0, NULL, NULL);
char *buf = malloc(len+1); // FIXME don't leak memory
# Instance of this class are standard FILE * pointers
private extern class NativeFile `{ FILE* `}
- fun io_read(buf: NativeString, len: Int): Int `{
+ fun io_read(buf: CString, len: Int): Int `{
return fread(buf, 1, len, self);
`}
- fun io_write(buf: NativeString, from, len: Int): Int `{
+ fun io_write(buf: CString, from, len: Int): Int `{
return fwrite(buf+from, 1, len, self);
`}
return setvbuf(self, NULL, (int)mode, buf_length);
`}
- new io_open_read(path: NativeString) `{ return fopen(path, "r"); `}
+ new io_open_read(path: CString) `{ return fopen(path, "r"); `}
- new io_open_write(path: NativeString) `{ return fopen(path, "w"); `}
+ new io_open_write(path: CString) `{ return fopen(path, "w"); `}
new native_stdin `{ return stdin; `}
private extern class NativeDir `{ DIR* `}
# Open a directory
- new opendir(path: NativeString) `{ return opendir(path); `}
+ new opendir(path: CString) `{ return opendir(path); `}
# Close a directory
fun closedir `{ closedir(self); `}
# Read the next directory entry
- fun readdir: NativeString `{
+ fun readdir: CString `{
struct dirent *de;
de = readdir(self);
if (!de) return NULL;
# Return the working (current) directory
fun getcwd: String do return native_getcwd.to_s
-private fun native_getcwd: NativeString `{ return getcwd(NULL, 0); `}
+private fun native_getcwd: CString `{ return getcwd(NULL, 0); `}