mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Updated organization file functions, env naming.
This commit is contained in:
committed by
Christoffer Lerno
parent
0ab0f727ad
commit
68f6cb1286
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
75
lib/std/io/os/file_nolibc.c3
Normal file
75
lib/std/io/os/file_nolibc.c3
Normal 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
115
lib/std/io/os/fileinfo.c3
Normal 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
|
||||
}
|
||||
@@ -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?;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
@@ -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
48
lib/std/io/os/ls.c3
Normal 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;
|
||||
};
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
60
lib/std/io/os/rmtree.c3
Normal 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)!;
|
||||
}
|
||||
30
lib/std/io/os/temp_directory.c3
Normal file
30
lib/std/io/os/temp_directory.c3
Normal 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");
|
||||
}
|
||||
Reference in New Issue
Block a user