aboutsummaryrefslogtreecommitdiff
path: root/std
diff options
context:
space:
mode:
Diffstat (limited to 'std')
-rw-r--r--std/c/index.zig1
-rw-r--r--std/os/darwin.zig9
-rw-r--r--std/os/file.zig45
-rw-r--r--std/os/linux/index.zig9
-rw-r--r--std/os/test.zig17
-rw-r--r--std/os/windows/index.zig2
6 files changed, 82 insertions, 1 deletions
diff --git a/std/c/index.zig b/std/c/index.zig
index 369ea2b358..02321f1f34 100644
--- a/std/c/index.zig
+++ b/std/c/index.zig
@@ -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;
diff --git a/std/os/darwin.zig b/std/os/darwin.zig
index 40da55315c..42b9917210 100644
--- a/std/os/darwin.zig
+++ b/std/os/darwin.zig
@@ -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)));
diff --git a/std/os/file.zig b/std/os/file.zig
index eed3a443b9..61fc2b1455 100644
--- a/std/os/file.zig
+++ b/std/os/file.zig
@@ -85,6 +85,47 @@ pub const File = struct {
};
}
+ 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 if (is_windows) {
+ if (os.windows.PathFileExists(path_with_null.ptr) == os.windows.TRUE) {
+ 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");
+ }
+ }
/// Upon success, the stream is in an uninitialized state. To continue using it,
/// you must use the open() function.
@@ -245,7 +286,9 @@ pub const File = struct {
};
}
- return stat.mode;
+ // TODO: we should be able to cast u16 to ModeError!u32, making this
+ // explicit cast not necessary
+ return os.FileMode(stat.mode);
} else if (is_windows) {
return {};
} else {
diff --git a/std/os/linux/index.zig b/std/os/linux/index.zig
index aa2a6d85da..e100af7733 100644
--- a/std/os/linux/index.zig
+++ b/std/os/linux/index.zig
@@ -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);
}
diff --git a/std/os/test.zig b/std/os/test.zig
index 9c718d5b6b..718d1ce2c8 100644
--- a/std/os/test.zig
+++ b/std/os/test.zig
@@ -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");
+}
diff --git a/std/os/windows/index.zig b/std/os/windows/index.zig
index 2709cf2a78..aa02c27f39 100644
--- a/std/os/windows/index.zig
+++ b/std/os/windows/index.zig
@@ -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;