Updated organization file functions, env naming.

This commit is contained in:
Christoffer Lerno
2023-06-23 22:59:57 +02:00
committed by Christoffer Lerno
parent 0ab0f727ad
commit 68f6cb1286
43 changed files with 751 additions and 561 deletions

View File

@@ -4,7 +4,7 @@ import libc;
macro void! native_chdir(Path path)
{
$switch
$case POSIX_LIBC:
$case env::POSIX:
if (posix::chdir(path.as_zstr()))
{
switch (libc::errno())
@@ -17,7 +17,7 @@ macro void! native_chdir(Path path)
default: return IoError.GENERAL_ERROR?;
}
}
$case WIN32_LIBC:
$case env::WIN32:
@pool()
{
// TODO improve with better error handling.

View File

@@ -1,42 +1,44 @@
module std::io::os;
module std::io::os @if(env::LIBC);
import libc;
def FopenFn = fn void*!(String, String);
def FreopenFn = fn void*!(void*, String, String);
def FcloseFn = fn void!(void*);
def FseekFn = fn void!(void*, isz, Seek);
def FtellFn = fn usz!(void*);
def FwriteFn = fn usz!(void*, char[] buffer);
def FreadFn = fn usz!(void*, char[] buffer);
FopenFn native_fopen_fn @weak @if(!$defined(native_fopen_fn));
FcloseFn native_fclose_fn @weak @if(!$defined(native_fclose_fn));
FreopenFn native_freopen_fn @weak @if(!$defined(native_freopen_fn));
FseekFn native_fseek_fn @weak @if(!$defined(native_fseek_fn));
FtellFn native_ftell_fn @weak @if(!$defined(native_ftell_fn));
FwriteFn native_fwrite_fn @weak @if(!$defined(native_fwrite_fn));
FreadFn native_fread_fn @weak @if(!$defined(native_fread_fn));
/**
* @require mode.len > 0
* @require filename.len > 0
**/
fn void*! native_fopen(String filename, String mode) @inline
{
$if !env::COMPILER_LIBC_AVAILABLE:
if (native_fopen_fn) return native_fopen_fn(filename, mode);
unreachable("Tried to call fopen without support.");
$else
@pool()
{
@pool()
{
$if env::WIN32:
void* file = libc::_wfopen(filename.to_temp_utf16(), filename.to_temp_utf16())!;
$else
void* file = libc::fopen(filename.zstr_tcopy(), mode.zstr_tcopy());
$endif
return file ?: file_open_errno()?;
};
$endif
};
}
fn void! native_remove(String filename)
{
@pool()
{
$if env::WIN32:
CInt result = libc::_wremove(filename.to_temp_utf16())!;
$else
CInt result = libc::remove(filename.zstr_tcopy());
$endif
if (result)
{
switch (libc::errno())
{
case errno::ENOENT:
return IoError.FILE_NOT_FOUND?;
case errno::EACCES:
default:
return IoError.FILE_CANNOT_DELETE?;
}
}
};
}
/**
@@ -45,61 +47,37 @@ fn void*! native_fopen(String filename, String mode) @inline
**/
fn void*! native_freopen(void* file, String filename, String mode) @inline
{
$if !env::COMPILER_LIBC_AVAILABLE:
if (native_freopen_fn) return native_freopen_fn(file, filename, mode);
unreachable("Tried to call freopen without support.");
$else
@pool()
{
$if env::os_is_win32():
@pool()
{
$if env::WIN32:
file = libc::_wfreopen(filename.to_temp_utf16(), mode.to_temp_utf16(), file)!;
$else
file = libc::freopen(filename.zstr_tcopy(), mode.zstr_tcopy(), file);
$endif
return file ?: file_open_errno()?;
};
$endif
};
}
fn void! native_fseek(void* file, isz offset, Seek seek_mode) @inline
{
$if !env::COMPILER_LIBC_AVAILABLE:
if (native_fseek_fn) return native_fseek_fn(file, offset, seek_mode);
unreachable("Tried to call fseek without support.");
$else
if (libc::fseek(file, (SeekIndex)offset, (CInt)seek_mode)) return file_seek_errno()?;
$endif
if (libc::fseek(file, (SeekIndex)offset, (CInt)seek_mode)) return file_seek_errno()?;
}
fn usz! native_ftell(CFile file) @inline
{
$if !env::COMPILER_LIBC_AVAILABLE:
if (native_ftell_fn) return native_ftell_fn(file);
unreachable("Tried to call ftell without support.");
$else
long index = libc::ftell(file);
return index >= 0 ? (usz)index : file_seek_errno()?;
$endif
long index = libc::ftell(file);
return index >= 0 ? (usz)index : file_seek_errno()?;
}
fn usz! native_fwrite(CFile file, char[] buffer) @inline
{
$if !env::COMPILER_LIBC_AVAILABLE:
if (native_fwrite_fn) return native_fwrite_fn(file, buffer);
unreachable("Tried to call fwrite without support.");
$else
return libc::fwrite(buffer.ptr, 1, buffer.len, file);
$endif
return libc::fwrite(buffer.ptr, 1, buffer.len, file);
}
fn usz! native_fread(CFile file, char[] buffer) @inline
{
$if !env::COMPILER_LIBC_AVAILABLE:
if (native_fread_fn) return native_fread_fn(file, buffer);
unreachable("Tried to call fread without support.");
$else
return libc::fread(buffer.ptr, 1, buffer.len, file);
$endif
return libc::fread(buffer.ptr, 1, buffer.len, file);
}
macro anyfault file_open_errno() @local
@@ -149,5 +127,3 @@ macro anyfault file_seek_errno() @local
}
}
// Posix functions
extern fn CInt access(ZString path, CInt mode) @if(POSIX_LIBC);

View File

@@ -0,0 +1,75 @@
module std::io::os @if(env::NO_LIBC);
import libc;
def FopenFn = fn void*!(String, String);
def FreopenFn = fn void*!(void*, String, String);
def FcloseFn = fn void!(void*);
def FseekFn = fn void!(void*, isz, Seek);
def FtellFn = fn usz!(void*);
def FwriteFn = fn usz!(void*, char[] buffer);
def FreadFn = fn usz!(void*, char[] buffer);
def RemoveFn = fn void!(String);
FopenFn native_fopen_fn @weak @if(!$defined(native_fopen_fn));
FcloseFn native_fclose_fn @weak @if(!$defined(native_fclose_fn));
FreopenFn native_freopen_fn @weak @if(!$defined(native_freopen_fn));
FseekFn native_fseek_fn @weak @if(!$defined(native_fseek_fn));
FtellFn native_ftell_fn @weak @if(!$defined(native_ftell_fn));
FwriteFn native_fwrite_fn @weak @if(!$defined(native_fwrite_fn));
FreadFn native_fread_fn @weak @if(!$defined(native_fread_fn));
RemoveFn native_remove_fn @weak @if(!$defined(native_remove_fn));
/**
* @require mode.len > 0
* @require filename.len > 0
**/
fn void*! native_fopen(String filename, String mode) @inline
{
if (native_fopen_fn) return native_fopen_fn(filename, mode);
unreachable("Tried to call fopen without support.");
}
/**
* Delete a file.
*
* @require filename.len > 0
**/
fn void! native_remove(String filename) @inline
{
if (native_remove_fn) return native_remove_fn(filename);
unreachable("Tried to call remove without support.");
}
/**
* @require mode.len > 0
* @require filename.len > 0
**/
fn void*! native_freopen(void* file, String filename, String mode) @inline
{
if (native_freopen_fn) return native_freopen_fn(file, filename, mode);
unreachable("Tried to call freopen without support.");
}
fn void! native_fseek(void* file, isz offset, Seek seek_mode) @inline
{
if (native_fseek_fn) return native_fseek_fn(file, offset, seek_mode);
unreachable("Tried to call fseek without support.");
}
fn usz! native_ftell(CFile file) @inline
{
if (native_ftell_fn) return native_ftell_fn(file);
unreachable("Tried to call ftell without support.");
}
fn usz! native_fwrite(CFile file, char[] buffer) @inline
{
if (native_fwrite_fn) return native_fwrite_fn(file, buffer);
unreachable("Tried to call fwrite without support.");
}
fn usz! native_fread(CFile file, char[] buffer) @inline
{
if (native_fread_fn) return native_fread_fn(file, buffer);
unreachable("Tried to call fread without support.");
}

115
lib/std/io/os/fileinfo.c3 Normal file
View File

@@ -0,0 +1,115 @@
module std::io::os @if(env::LIBC);
import libc;
fn void! native_stat(Stat* stat, String path) @if(env::DARWIN || env::LINUX)
{
@pool()
{
$if env::DARWIN || env::LINUX:
int res = libc::stat(path.zstr_tcopy(), stat);
$else
unreachable("Stat unimplemented");
int res = 0;
$endif
if (res != 0)
{
switch (libc::errno())
{
case errno::EBADF:
return IoError.FILE_NOT_VALID?;
case errno::EFAULT:
unreachable("Invalid stat");
case errno::EIO:
return IoError.GENERAL_ERROR?;
case errno::EACCES:
return IoError.NO_PERMISSION?;
case errno::ELOOP:
return IoError.NO_PERMISSION?;
case errno::ENAMETOOLONG:
return IoError.NAME_TOO_LONG?;
case errno::ENOENT:
return IoError.FILE_NOT_FOUND?;
case errno::ENOTDIR:
return IoError.FILE_NOT_DIR?;
case errno::EOVERFLOW:
return IoError.GENERAL_ERROR?;
default:
return IoError.UNKNOWN_ERROR?;
}
}
};
}
fn usz! native_file_size(String path) @if(env::WIN32)
{
@pool()
{
Char16[] path16 = path.to_temp_utf16()!;
Win32_FILE_ATTRIBUTE_DATA data;
win32::getFileAttributesExW(path16, Win32_GET_FILEEX_INFO_LEVELS.STANDARD, &data);
Win32_LARGE_INTEGER size;
size.lowPart = data.nFileSizeLow;
size.highPart = data.nFileSizeHigh;
return (usz)size.quadPart;
};
}
fn usz! native_file_size(String path) @if(!env::WIN32 && !env::DARWIN)
{
File f = file::open(path, "r")!;
defer (void)f.close();
return f.seek(0, Seek.END)!;
}
fn usz! native_file_size(String path) @if(env::DARWIN)
{
Stat stat;
native_stat(&stat, path)!;
return stat.st_size;
}
fn bool native_file_or_dir_exists(String path)
{
$switch
$case env::DARWIN:
$case env::LINUX:
Stat stat;
return @ok(native_stat(&stat, path));
$case env::WIN32:
@pool()
{
return (bool)win32::pathFileExistsW(path.to_temp_utf16()) ?? false;
};
$case env::POSIX:
@pool()
{
return posix::access(path.zstr_tcopy(), 0 /* F_OK */) != -1;
};
$default:
unreachable("Not supported");
$endswitch
}
fn bool native_is_file(String path)
{
$switch
$case env::DARWIN:
$case env::LINUX:
Stat stat;
return @ok(native_stat(&stat, path)) && stat.st_mode & libc::S_IFREG;
$default:
File! f = file::open(path, "r");
defer (void)f.close();
return @ok(f);
$endswitch
}
fn bool native_is_dir(String path)
{
$if env::DARWIN || env::LINUX:
Stat stat;
return @ok(native_stat(&stat, path)) && stat.st_mode & libc::S_IFDIR;
$else
return native_file_or_dir_exists(path) && !native_is_file(path);
$endif
}

View File

@@ -1,98 +0,0 @@
module std::io::file::os @if(DARWIN_LIBC);
import libc;
struct DarwinTimespec @private
{
long tv_sec;
long tv_nsec;
}
struct Darwin64Stat @private
{
int st_dev;
ushort st_mode;
ushort st_nlink;
ulong st_ino;
uint st_uid;
uint st_gid;
int st_rdev;
DarwinTimespec st_atimespec; // time of last access
DarwinTimespec st_mtimespec; // time of last data modification
DarwinTimespec st_ctimespec; // time of last status change
DarwinTimespec st_birthtimespec; // time of file creation(birth)
long st_size;
long st_blocks;
int st_blocksize;
uint st_flags;
uint st_gen;
int st_lspare;
long[2] st_qspare;
}
extern fn int _stat(ZString str, Darwin64Stat* stat) @extern("stat64");
const S_IFMT = 0o170000; // type of file mask
const S_IFIFO = 0o010000; // named pipe (fifo)
const S_IFCHR = 0o020000; // character special
const S_IFDIR = 0o040000; // directory
const S_IFBLK = 0o060000; // block special
const S_IFREG = 0o100000; // regular
const S_IFLNK = 0o120000; // symbolic link
const S_IFSOCK = 0o140000; // socket
fn usz! native_file_size(String path)
{
Darwin64Stat stat;
read_stat(&stat, path)!;
return stat.st_size;
}
fn bool native_file_or_dir_exists(String path)
{
Darwin64Stat stat;
return @ok(read_stat(&stat, path));
}
fn bool native_is_file(String path)
{
Darwin64Stat stat;
return @ok(read_stat(&stat, path)) && stat.st_mode & S_IFREG;
}
fn bool native_is_dir(String path)
{
Darwin64Stat stat;
return @ok(read_stat(&stat, path)) && stat.st_mode & S_IFDIR;
}
fn void! read_stat(Darwin64Stat* stat, String path) @local
{
@pool()
{
int res = _stat(path.zstr_tcopy(), stat);
if (res != 0)
{
switch (libc::errno())
{
case errno::EBADF:
return IoError.FILE_NOT_VALID?;
case errno::EFAULT:
unreachable("Invalid stat");
case errno::EIO:
return IoError.GENERAL_ERROR?;
case errno::EACCES:
return IoError.NO_PERMISSION?;
case errno::ELOOP:
return IoError.NO_PERMISSION?;
case errno::ENAMETOOLONG:
return IoError.NAME_TOO_LONG?;
case errno::ENOENT:
return IoError.FILE_NOT_FOUND?;
case errno::ENOTDIR:
return IoError.FILE_NOT_DIR?;
case errno::EOVERFLOW:
return IoError.GENERAL_ERROR?;
default:
return IoError.UNKNOWN_ERROR?;
}
}
};
}

View File

@@ -1,144 +0,0 @@
module std::io::file::os;
const USE_DARWIN_INODE64 = env::os_is_darwin() && env::ARCH_TYPE == X86_64;
extern fn NativeDirentry* readdir(void*) @extern("readdir") @if(!USE_DARWIN_INODE64) ;
extern fn NativeDirentry* readdir(void*) @extern("readdir$INODE64") @if(USE_DARWIN_INODE64);
struct NativeDirentry
{
usz ino;
usz seekoff @if(env::os_is_darwin());
isz seekoff @if(!env::os_is_darwin());
ushort reclen;
ushort namelen @if(env::os_is_darwin());
char type;
char[1024] name @if(env::os_is_darwin());
char[*] name @if(!env::os_is_darwin());
}
module std::io::file::os @if(!env::WIN32);
// native_temp_directory, for non Win32
fn Path! native_temp_directory(Allocator* using = mem::heap())
{
foreach (String env : { "TMPDIR", "TMP", "TEMP", "TEMPDIR" })
{
String tmpdir = env::get_var(env) ?? "";
if (tmpdir) return path::new(tmpdir, using);
}
return path::new("/tmp", using);
}
module std::io::file::os @if(env::COMPILER_LIBC_AVAILABLE && !env::os_is_win32());
extern fn void* opendir(ZString);
extern fn void closedir(void*);
extern fn int remove(ZString);
const DT_UNKNOWN = 0;
const DT_FIFO = 1;
const DT_CHR = 2;
const DT_DIR = 4;
const DT_BLK = 6;
const DT_REG = 8;
const DT_LNK = 10;
const DT_SOCK = 12;
const DT_WHT = 14;
fn PathList! native_ls(Path dir, bool no_dirs, bool no_symlinks, String mask, Allocator* using)
{
PathList list;
list.init(.using = using);
void* directory = opendir(dir.as_str() ? dir.as_zstr() : (ZString)".");
defer if (directory) closedir(directory);
if (!directory) return (path::is_dir(dir) ? IoError.CANNOT_READ_DIR : IoError.FILE_NOT_DIR)?;
NativeDirentry* entry;
while ((entry = readdir(directory)))
{
String name = ((ZString)&entry.name).as_str();
if (!name || name == "." || name == "..") continue;
if (entry.type == DT_LNK && no_symlinks) continue;
if (entry.type == DT_DIR && no_dirs) continue;
Path path = path::new(name.copy(using), using)!!;
list.append(path);
}
return list;
}
/**
* @require dir.as_str()
**/
fn void! native_rmtree(Path dir)
{
void* directory = opendir(dir.as_zstr());
defer if (directory) closedir(directory);
if (!directory) return path::is_dir(dir) ? IoError.CANNOT_READ_DIR? : IoError.FILE_NOT_DIR?;
NativeDirentry* entry;
while ((entry = readdir(directory)))
{
@pool()
{
String name = ((ZString)&entry.name).as_str();
if (!name || name == "." || name == "..") continue;
Path new_path = dir.tappend(name)!;
if (entry.type == DT_DIR)
{
native_rmtree(new_path)!;
continue;
}
if (remove(new_path.as_zstr()))
{
// TODO improve
return IoError.GENERAL_ERROR?;
}
};
}
os::native_rmdir(dir)!;
}
module std::io::file::os @if(!env::os_is_darwin() && !env::os_is_win32());
fn usz! native_file_size(String path)
{
File f = file::open(path, "r")!;
defer (void)f.close();
return f.seek(0, Seek.END)!;
}
fn bool native_file_or_dir_exists(String path)
{
$if POSIX_LIBC:
@pool()
{
return os::access(path.zstr_tcopy(), 0 /* F_OK */) != -1;
};
$else
unreachable("Tried to call file_or_dir_exists without support.");
return false;
$endif
}
fn bool native_is_file(String path)
{
$if POSIX_LIBC:
File! f = file::open(path, "r");
defer (void)f.close();
return @ok(f);
$else
unreachable("Tried to call is_file without support.");
return false;
$endif
}
fn bool native_is_dir(String path)
{
$if POSIX_LIBC:
return native_file_or_dir_exists(path) && !native_is_file(path);
$else
unreachable("Tried to call is_dir without support.");
return false;
$endif
}

View File

@@ -1,103 +0,0 @@
module std::io::file::os @if(env::WIN32);
import std::os::win32;
fn usz! native_file_size(String path)
{
@pool()
{
Char16[] path16 = path.to_temp_utf16()!;
Win32_FILE_ATTRIBUTE_DATA data;
win32::getFileAttributesExW(path16, Win32_GET_FILEEX_INFO_LEVELS.STANDARD, &data);
Win32_LARGE_INTEGER size;
size.lowPart = data.nFileSizeLow;
size.highPart = data.nFileSizeHigh;
return (usz)size.quadPart;
};
}
fn bool native_file_or_dir_exists(String path)
{
@pool()
{
return (bool)win32::pathFileExistsW(path.to_temp_utf16()) ?? false;
};
}
fn bool native_is_file(String path)
{
File! f = file::open(path, "r");
defer (void)f.close();
return @ok(f);
}
fn bool native_is_dir(String path)
{
return native_file_or_dir_exists(path) && !native_is_file(path);
}
fn void! native_rmtree(Path path)
{
Win32_WIN32_FIND_DATAW find_data;
String s = path.as_str().tconcat("\\*");
Win32_HANDLE find = win32::findFirstFileW(s.to_utf16(mem::temp()), &find_data)!;
if (find == win32::INVALID_HANDLE_VALUE) return IoError.CANNOT_READ_DIR?;
defer win32::findClose(find);
do
{
String filename = string::from_zutf16(&find_data.cFileName, mem::temp())!;
if (filename == "." || filename == "..") continue;
Path file_path = path.tappend(filename)!;
if (find_data.dwFileAttributes & win32::FILE_ATTRIBUTE_DIRECTORY)
{
native_rmtree(file_path)!;
}
else
{
win32::deleteFileW(file_path.as_str().to_utf16(mem::temp()));
}
} while (win32::findNextFileW(find, &find_data) != 0);
os::native_rmdir(path)!;
}
fn Path! native_temp_directory(Allocator* using = mem::heap())
{
@stack_mem(256; Allocator* mem)
{
Win32_DWORD len = win32::getTempPathW(0, null);
if (!len) return IoError.GENERAL_ERROR?;
Char16[] buff = malloc(Char16, len + 1, .using = mem);
if (!win32::getTempPathW(len, buff)) return IoError.GENERAL_ERROR?;
return path::new(string::from_utf16(buff[:len], .using = mem), using);
};
}
fn PathList! native_ls(Path dir, bool no_dirs, bool no_symlinks, String mask, Allocator* using)
{
PathList list;
list.init(.using = using);
@stack_mem(1024; Allocator* mem)
{
Char16* result = dir.as_str().concat(`\*`).to_utf16(.using = mem)!!;
list.append(path::new("test"));
Win32_WIN32_FIND_DATAW find_data;
Win32_HANDLE find = win32::findFirstFileW(result, &find_data);
if (find == win32::INVALID_HANDLE_VALUE) return IoError.CANNOT_READ_DIR?;
defer win32::findClose(find);
do
{
if (no_dirs && (find_data.dwFileAttributes & win32::FILE_ATTRIBUTE_DIRECTORY)) continue;
@stack_mem(480; Allocator* mem2)
{
String filename = string::from_zutf16(&find_data.cFileName, mem2)!;
if (filename == ".." || filename == ".") continue;
list.append(path::new(filename, using));
};
} while (win32::findNextFileW(find, &find_data));
return list;
};
}

View File

@@ -4,7 +4,7 @@ import libc;
macro String! getcwd(Allocator* using = mem::heap())
{
$switch
$case WIN32_LIBC:
$case env::WIN32:
const DEFAULT_BUFFER = 256;
Char16[DEFAULT_BUFFER] buffer;
Char16 *res = win32::_wgetcwd(&buffer, DEFAULT_BUFFER);
@@ -19,7 +19,7 @@ macro String! getcwd(Allocator* using = mem::heap())
Char16[] str16 = res[:win32::wcslen(res)];
return string::from_utf16(str16, using);
$case POSIX_LIBC:
$case env::POSIX:
const usz DEFAULT_BUFFER = 256;
char[DEFAULT_BUFFER] buffer;
ZString res = posix::getcwd(&buffer, DEFAULT_BUFFER);

48
lib/std/io/os/ls.c3 Normal file
View File

@@ -0,0 +1,48 @@
module std::io::file::os @if(env::POSIX);
fn PathList! native_ls(Path dir, bool no_dirs, bool no_symlinks, String mask, Allocator* using)
{
PathList list;
list.init(.using = using);
DIRPtr directory = posix::opendir(dir.as_str() ? dir.as_zstr() : (ZString)".");
defer if (directory) posix::closedir(directory);
if (!directory) return (path::is_dir(dir) ? IoError.CANNOT_READ_DIR : IoError.FILE_NOT_DIR)?;
Posix_dirent* entry;
while ((entry = posix::readdir(directory)))
{
String name = ((ZString)&entry.name).as_str();
if (!name || name == "." || name == "..") continue;
if (entry.d_type == posix::DT_LNK && no_symlinks) continue;
if (entry.d_type == posix::DT_DIR && no_dirs) continue;
Path path = path::new(name.copy(using), using)!!;
list.append(path);
}
return list;
}
module std::io::os @if(env::WIN32);
fn PathList! native_ls(Path dir, bool no_dirs, bool no_symlinks, String mask, Allocator* using)
{
PathList list;
list.init(.using = using);
@stack_mem(1024; Allocator* mem)
{
Char16* result = dir.as_str().concat(`\*`).to_utf16(.using = mem)!!;
Win32_WIN32_FIND_DATAW find_data;
Win32_HANDLE find = win32::findFirstFileW(result, &find_data);
if (find == win32::INVALID_HANDLE_VALUE) return IoError.CANNOT_READ_DIR?;
defer win32::findClose(find);
do
{
if (no_dirs && (find_data.dwFileAttributes & win32::FILE_ATTRIBUTE_DIRECTORY)) continue;
@stack_mem(480; Allocator* mem2)
{
String filename = string::from_zutf16(&find_data.cFileName, mem2)!;
if (filename == ".." || filename == ".") continue;
list.append(path::new(filename, using));
};
} while (win32::findNextFileW(find, &find_data));
return list;
};
}

View File

@@ -8,7 +8,7 @@ import std::os::posix;
macro bool! native_mkdir(Path path, MkdirPermissions permissions)
{
$switch
$case POSIX_LIBC:
$case env::POSIX:
if (!posix::mkdir(path.as_zstr(), permissions == NORMAL ? 0o777 : 0o700)) return true;
switch (libc::errno())
{
@@ -25,7 +25,7 @@ macro bool! native_mkdir(Path path, MkdirPermissions permissions)
case errno::ENOTDIR: return IoError.FILE_NOT_FOUND?;
default: return IoError.GENERAL_ERROR?;
}
$case WIN32_LIBC:
$case env::WIN32:
@pool()
{
// TODO security attributes

View File

@@ -7,7 +7,7 @@ import std::os::posix;
macro bool! native_rmdir(Path path)
{
$switch
$case POSIX_LIBC:
$case env::POSIX:
if (!posix::rmdir(path.as_zstr())) return true;
switch (libc::errno())
{
@@ -23,7 +23,7 @@ macro bool! native_rmdir(Path path)
case errno::ELOOP: return IoError.SYMLINK_FAILED?;
default: return IoError.GENERAL_ERROR?;
}
$case WIN32_LIBC:
$case env::WIN32:
@pool()
{
if (win32::removeDirectoryW(path.as_str().to_temp_utf16()!!)) return true;

60
lib/std/io/os/rmtree.c3 Normal file
View File

@@ -0,0 +1,60 @@
module std::io::file::os @if(env::POSIX);
import libc;
/**
* @require dir.as_str()
**/
fn void! native_rmtree(Path dir)
{
DIRPtr directory = posix::opendir(dir.as_zstr());
defer if (directory) posix::closedir(directory);
if (!directory) return path::is_dir(dir) ? IoError.CANNOT_READ_DIR? : IoError.FILE_NOT_DIR?;
Posix_dirent* entry;
while ((entry = posix::readdir(directory)))
{
@pool()
{
String name = ((ZString)&entry.name).as_str();
if (!name || name == "." || name == "..") continue;
Path new_path = dir.tappend(name)!;
if (entry.d_type == posix::DT_DIR)
{
native_rmtree(new_path)!;
continue;
}
if (libc::remove(new_path.as_zstr()))
{
// TODO improve
return IoError.GENERAL_ERROR?;
}
};
}
os::native_rmdir(dir)!;
}
module std::io::os @if(env::WIN32);
fn void! native_rmtree(Path path)
{
Win32_WIN32_FIND_DATAW find_data;
String s = path.as_str().tconcat("\\*");
Win32_HANDLE find = win32::findFirstFileW(s.to_utf16(mem::temp()), &find_data)!;
if (find == win32::INVALID_HANDLE_VALUE) return IoError.CANNOT_READ_DIR?;
defer win32::findClose(find);
do
{
String filename = string::from_zutf16(&find_data.cFileName, mem::temp())!;
if (filename == "." || filename == "..") continue;
Path file_path = path.tappend(filename)!;
if (find_data.dwFileAttributes & win32::FILE_ATTRIBUTE_DIRECTORY)
{
native_rmtree(file_path)!;
}
else
{
win32::deleteFileW(file_path.as_str().to_utf16(mem::temp()));
}
} while (win32::findNextFileW(find, &find_data) != 0);
os::native_rmdir(path)!;
}

View File

@@ -0,0 +1,30 @@
module std::io::os @if(env::LIBC);
fn Path! native_temp_directory(Allocator* using = mem::heap()) @if(!env::WIN32)
{
foreach (String env : { "TMPDIR", "TMP", "TEMP", "TEMPDIR" })
{
String tmpdir = env::get_var(env) ?? "";
if (tmpdir) return path::new(tmpdir, using);
}
return path::new("/tmp", using);
}
fn Path! native_temp_directory(Allocator* using = mem::heap()) @if(env::WIN32)
{
@stack_mem(256; Allocator* mem)
{
Win32_DWORD len = win32::getTempPathW(0, null);
if (!len) return IoError.GENERAL_ERROR?;
Char16[] buff = malloc(Char16, len + 1, .using = mem);
if (!win32::getTempPathW(len, buff)) return IoError.GENERAL_ERROR?;
return path::new(string::from_utf16(buff[:len], .using = mem), using);
};
}
module std::io::os @if(env::NO_LIBC);
macro Path! native_temp_directory(Allocator* using = mem::heap())
{
unreachable("Not available");
}