authorgravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2018-04-13 21:27:09+12:00
committergravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2018-04-13 21:27:09+12:00
log03bec631bd493dc157d0c071363c967caf7f57ac
tree79690b762f7ab14d6f9da6fc76be474e62d33a9f
parentb946982e90c88d0c23cfb2e819f58ce8ff9af617

Replace File.exists with File.access


7 files changed, 77 insertions(+), 6 deletions(-)

src-self-hosted/main.zig+1-1
......@@ -175,7 +175,7 @@ fn cmdBuild(allocator: &Allocator, args: []const []const u8) !void {
175175 const build_file_abs = try os.path.resolve(allocator, ".", build_file);
176176 defer allocator.free(build_file_abs);
177177
178 const build_file_exists = os.File.exists(allocator, build_file_abs);
178 const build_file_exists = os.File.access(allocator, build_file_abs, os.default_file_mode) catch false;
179179
180180 if (flags.present("init")) {
181181 if (build_file_exists) {
std/c/index.zig+1
......@@ -28,6 +28,7 @@ pub extern "c" fn unlink(path: &const u8) c_int;
2828pub extern "c" fn getcwd(buf: &u8, size: usize) ?&u8;
2929pub extern "c" fn waitpid(pid: c_int, stat_loc: &c_int, options: c_int) c_int;
3030pub extern "c" fn fork() c_int;
31pub extern "c" fn access(path: &const u8, mode: c_uint) c_int;
3132pub extern "c" fn pipe(fds: &c_int) c_int;
3233pub extern "c" fn mkdir(path: &const u8, mode: c_uint) c_int;
3334pub extern "c" fn symlink(existing: &const u8, new: &const u8) c_int;
std/os/darwin.zig+9
......@@ -41,6 +41,11 @@ pub const SA_64REGSET = 0x0200; /// signal handler with SA_SIGINFO args with 64
4141pub const O_LARGEFILE = 0x0000;
4242pub const O_PATH = 0x0000;
4343
44pub const F_OK = 0;
45pub const X_OK = 1;
46pub const W_OK = 2;
47pub const R_OK = 4;
48
4449pub const O_RDONLY = 0x0000; /// open for reading only
4550pub const O_WRONLY = 0x0001; /// open for writing only
4651pub const O_RDWR = 0x0002; /// open for reading and writing
......@@ -209,6 +214,10 @@ pub fn fork() usize {
209214 return errnoWrap(c.fork());
210215}
211216
217pub fn access(path: &const u8, mode: u32) usize {
218 return errnoWrap(c.access(path, mode));
219}
220
212221pub fn pipe(fds: &[2]i32) usize {
213222 comptime assert(i32.bit_count == c_int.bit_count);
214223 return errnoWrap(c.pipe(@ptrCast(&c_int, fds)));
std/os/file.zig+38-5
......@@ -85,12 +85,45 @@ pub const File = struct {
8585 };
8686 }
8787
88 pub fn exists(allocator: &mem.Allocator, path: []const u8) bool {
89 if (openRead(allocator, path)) |*file| {
90 file.close();
88 pub fn access(allocator: &mem.Allocator, path: []const u8, file_mode: os.FileMode) !bool {
89 const path_with_null = try std.cstr.addNullByte(allocator, path);
90 defer allocator.free(path_with_null);
91
92 if (is_posix) {
93 // mode is ignored and is always F_OK for now
94 const result = posix.access(path_with_null.ptr, posix.F_OK);
95 const err = posix.getErrno(result);
96 if (err > 0) {
97 return switch (err) {
98 posix.EACCES => error.PermissionDenied,
99 posix.EROFS => error.PermissionDenied,
100 posix.ELOOP => error.PermissionDenied,
101 posix.ETXTBSY => error.PermissionDenied,
102 posix.ENOTDIR => error.NotFound,
103 posix.ENOENT => error.NotFound,
104
105 posix.ENAMETOOLONG => error.NameTooLong,
106 posix.EINVAL => error.BadMode,
107 posix.EFAULT => error.BadPathName,
108 posix.EIO => error.Io,
109 posix.ENOMEM => error.SystemResources,
110 else => os.unexpectedErrorPosix(err),
111 };
112 }
91113 return true;
92 } else |_| {
93 return false;
114 } else if (is_windows) {
115 if (os.windows.PathFileExists(path_with_null.ptr)) {
116 return true;
117 }
118
119 const err = windows.GetLastError();
120 return switch (err) {
121 windows.ERROR.FILE_NOT_FOUND => error.NotFound,
122 windows.ERROR.ACCESS_DENIED => error.PermissionDenied,
123 else => os.unexpectedErrorWindows(err),
124 };
125 } else {
126 @compileError("TODO implement access for this OS");
94127 }
95128 }
96129
std/os/linux/index.zig+9
......@@ -38,6 +38,11 @@ pub const MAP_STACK = 0x20000;
3838pub const MAP_HUGETLB = 0x40000;
3939pub const MAP_FILE = 0;
4040
41pub const F_OK = 0;
42pub const X_OK = 1;
43pub const W_OK = 2;
44pub const R_OK = 4;
45
4146pub const WNOHANG = 1;
4247pub const WUNTRACED = 2;
4348pub const WSTOPPED = 2;
......@@ -705,6 +710,10 @@ pub fn pread(fd: i32, buf: &u8, count: usize, offset: usize) usize {
705710 return syscall4(SYS_pread, usize(fd), @ptrToInt(buf), count, offset);
706711}
707712
713pub fn access(path: &const u8, mode: u32) usize {
714 return syscall2(SYS_access, @ptrToInt(path), mode);
715}
716
708717pub fn pipe(fd: &[2]i32) usize {
709718 return pipe2(fd, 0);
710719}
std/os/test.zig+17
......@@ -23,3 +23,20 @@ test "makePath, put some files in it, deleteTree" {
2323 assert(err == error.PathNotFound);
2424 }
2525}
26
27test "access file" {
28 if (builtin.os == builtin.Os.windows) {
29 return;
30 }
31
32 try os.makePath(a, "os_test_tmp");
33 if (os.File.access(a, "os_test_tmp/file.txt", os.default_file_mode)) |ok| {
34 unreachable;
35 } else |err| {
36 assert(err == error.NotFound);
37 }
38
39 try io.writeFile(a, "os_test_tmp/file.txt", "");
40 assert((try os.File.access(a, "os_test_tmp/file.txt", os.default_file_mode)) == true);
41 try os.deleteTree(a, "os_test_tmp");
42}
std/os/windows/index.zig+2
......@@ -78,6 +78,8 @@ pub extern "kernel32" stdcallcc fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem
7878pub extern "kernel32" stdcallcc fn MoveFileExA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR,
7979 dwFlags: DWORD) BOOL;
8080
81pub extern "kernel32" stdcallcc fn PathFileExists(pszPath: ?LPCTSTR) BOOL;
82
8183pub extern "kernel32" stdcallcc fn ReadFile(in_hFile: HANDLE, out_lpBuffer: &c_void,
8284 in_nNumberOfBytesToRead: DWORD, out_lpNumberOfBytesRead: &DWORD,
8385 in_out_lpOverlapped: ?&OVERLAPPED) BOOL;