Replace File.exists with File.access

This commit is contained in:
Marc Tiehuis 2018-04-13 21:27:09 +12:00
parent b946982e90
commit 03bec631bd
7 changed files with 77 additions and 6 deletions

View File

@ -175,7 +175,7 @@ fn cmdBuild(allocator: &Allocator, args: []const []const u8) !void {
const build_file_abs = try os.path.resolve(allocator, ".", build_file);
defer allocator.free(build_file_abs);
const build_file_exists = os.File.exists(allocator, build_file_abs);
const build_file_exists = os.File.access(allocator, build_file_abs, os.default_file_mode) catch false;
if (flags.present("init")) {
if (build_file_exists) {

View File

@ -28,6 +28,7 @@ pub extern "c" fn unlink(path: &const u8) c_int;
pub extern "c" fn getcwd(buf: &u8, size: usize) ?&u8;
pub extern "c" fn waitpid(pid: c_int, stat_loc: &c_int, options: c_int) c_int;
pub extern "c" fn fork() c_int;
pub extern "c" fn access(path: &const u8, mode: c_uint) c_int;
pub extern "c" fn pipe(fds: &c_int) c_int;
pub extern "c" fn mkdir(path: &const u8, mode: c_uint) c_int;
pub extern "c" fn symlink(existing: &const u8, new: &const u8) c_int;

View File

@ -41,6 +41,11 @@ pub const SA_64REGSET = 0x0200; /// signal handler with SA_SIGINFO args with 64
pub const O_LARGEFILE = 0x0000;
pub const O_PATH = 0x0000;
pub const F_OK = 0;
pub const X_OK = 1;
pub const W_OK = 2;
pub const R_OK = 4;
pub const O_RDONLY = 0x0000; /// open for reading only
pub const O_WRONLY = 0x0001; /// open for writing only
pub const O_RDWR = 0x0002; /// open for reading and writing
@ -209,6 +214,10 @@ pub fn fork() usize {
return errnoWrap(c.fork());
}
pub fn access(path: &const u8, mode: u32) usize {
return errnoWrap(c.access(path, mode));
}
pub fn pipe(fds: &[2]i32) usize {
comptime assert(i32.bit_count == c_int.bit_count);
return errnoWrap(c.pipe(@ptrCast(&c_int, fds)));

View File

@ -85,12 +85,45 @@ pub const File = struct {
};
}
pub fn exists(allocator: &mem.Allocator, path: []const u8) bool {
if (openRead(allocator, path)) |*file| {
file.close();
pub fn access(allocator: &mem.Allocator, path: []const u8, file_mode: os.FileMode) !bool {
const path_with_null = try std.cstr.addNullByte(allocator, path);
defer allocator.free(path_with_null);
if (is_posix) {
// mode is ignored and is always F_OK for now
const result = posix.access(path_with_null.ptr, posix.F_OK);
const err = posix.getErrno(result);
if (err > 0) {
return switch (err) {
posix.EACCES => error.PermissionDenied,
posix.EROFS => error.PermissionDenied,
posix.ELOOP => error.PermissionDenied,
posix.ETXTBSY => error.PermissionDenied,
posix.ENOTDIR => error.NotFound,
posix.ENOENT => error.NotFound,
posix.ENAMETOOLONG => error.NameTooLong,
posix.EINVAL => error.BadMode,
posix.EFAULT => error.BadPathName,
posix.EIO => error.Io,
posix.ENOMEM => error.SystemResources,
else => os.unexpectedErrorPosix(err),
};
}
return true;
} else |_| {
return false;
} else if (is_windows) {
if (os.windows.PathFileExists(path_with_null.ptr)) {
return true;
}
const err = windows.GetLastError();
return switch (err) {
windows.ERROR.FILE_NOT_FOUND => error.NotFound,
windows.ERROR.ACCESS_DENIED => error.PermissionDenied,
else => os.unexpectedErrorWindows(err),
};
} else {
@compileError("TODO implement access for this OS");
}
}

View File

@ -38,6 +38,11 @@ pub const MAP_STACK = 0x20000;
pub const MAP_HUGETLB = 0x40000;
pub const MAP_FILE = 0;
pub const F_OK = 0;
pub const X_OK = 1;
pub const W_OK = 2;
pub const R_OK = 4;
pub const WNOHANG = 1;
pub const WUNTRACED = 2;
pub const WSTOPPED = 2;
@ -705,6 +710,10 @@ pub fn pread(fd: i32, buf: &u8, count: usize, offset: usize) usize {
return syscall4(SYS_pread, usize(fd), @ptrToInt(buf), count, offset);
}
pub fn access(path: &const u8, mode: u32) usize {
return syscall2(SYS_access, @ptrToInt(path), mode);
}
pub fn pipe(fd: &[2]i32) usize {
return pipe2(fd, 0);
}

View File

@ -23,3 +23,20 @@ test "makePath, put some files in it, deleteTree" {
assert(err == error.PathNotFound);
}
}
test "access file" {
if (builtin.os == builtin.Os.windows) {
return;
}
try os.makePath(a, "os_test_tmp");
if (os.File.access(a, "os_test_tmp/file.txt", os.default_file_mode)) |ok| {
unreachable;
} else |err| {
assert(err == error.NotFound);
}
try io.writeFile(a, "os_test_tmp/file.txt", "");
assert((try os.File.access(a, "os_test_tmp/file.txt", os.default_file_mode)) == true);
try os.deleteTree(a, "os_test_tmp");
}

View File

@ -78,6 +78,8 @@ pub extern "kernel32" stdcallcc fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem
pub extern "kernel32" stdcallcc fn MoveFileExA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR,
dwFlags: DWORD) BOOL;
pub extern "kernel32" stdcallcc fn PathFileExists(pszPath: ?LPCTSTR) BOOL;
pub extern "kernel32" stdcallcc fn ReadFile(in_hFile: HANDLE, out_lpBuffer: &c_void,
in_nNumberOfBytesToRead: DWORD, out_lpNumberOfBytesRead: &DWORD,
in_out_lpOverlapped: ?&OVERLAPPED) BOOL;