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 {...@@ -175,7 +175,7 @@ fn cmdBuild(allocator: &Allocator, args: []const []const u8) !void {
175 const build_file_abs = try os.path.resolve(allocator, ".", build_file);175 const build_file_abs = try os.path.resolve(allocator, ".", build_file);
176 defer allocator.free(build_file_abs);176 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
180 if (flags.present("init")) {180 if (flags.present("init")) {
181 if (build_file_exists) {181 if (build_file_exists) {
std/c/index.zig+1
...@@ -28,6 +28,7 @@ pub extern "c" fn unlink(path: &const u8) c_int;...@@ -28,6 +28,7 @@ pub extern "c" fn unlink(path: &const u8) c_int;
28pub extern "c" fn getcwd(buf: &u8, size: usize) ?&u8;28pub extern "c" fn getcwd(buf: &u8, size: usize) ?&u8;
29pub extern "c" fn waitpid(pid: c_int, stat_loc: &c_int, options: c_int) c_int;29pub extern "c" fn waitpid(pid: c_int, stat_loc: &c_int, options: c_int) c_int;
30pub extern "c" fn fork() c_int;30pub extern "c" fn fork() c_int;
31pub extern "c" fn access(path: &const u8, mode: c_uint) c_int;
31pub extern "c" fn pipe(fds: &c_int) c_int;32pub extern "c" fn pipe(fds: &c_int) c_int;
32pub extern "c" fn mkdir(path: &const u8, mode: c_uint) c_int;33pub extern "c" fn mkdir(path: &const u8, mode: c_uint) c_int;
33pub extern "c" fn symlink(existing: &const u8, new: &const u8) c_int;34pub 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...@@ -41,6 +41,11 @@ pub const SA_64REGSET = 0x0200; /// signal handler with SA_SIGINFO args with 64
41pub const O_LARGEFILE = 0x0000;41pub const O_LARGEFILE = 0x0000;
42pub const O_PATH = 0x0000;42pub 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
44pub const O_RDONLY = 0x0000; /// open for reading only49pub const O_RDONLY = 0x0000; /// open for reading only
45pub const O_WRONLY = 0x0001; /// open for writing only50pub const O_WRONLY = 0x0001; /// open for writing only
46pub const O_RDWR = 0x0002; /// open for reading and writing51pub const O_RDWR = 0x0002; /// open for reading and writing
...@@ -209,6 +214,10 @@ pub fn fork() usize {...@@ -209,6 +214,10 @@ pub fn fork() usize {
209 return errnoWrap(c.fork());214 return errnoWrap(c.fork());
210}215}
211216
217pub fn access(path: &const u8, mode: u32) usize {
218 return errnoWrap(c.access(path, mode));
219}
220
212pub fn pipe(fds: &[2]i32) usize {221pub fn pipe(fds: &[2]i32) usize {
213 comptime assert(i32.bit_count == c_int.bit_count);222 comptime assert(i32.bit_count == c_int.bit_count);
214 return errnoWrap(c.pipe(@ptrCast(&c_int, fds)));223 return errnoWrap(c.pipe(@ptrCast(&c_int, fds)));
std/os/file.zig+38-5
...@@ -85,12 +85,45 @@ pub const File = struct {...@@ -85,12 +85,45 @@ pub const File = struct {
85 };85 };
86 }86 }
8787
88 pub fn exists(allocator: &mem.Allocator, path: []const u8) bool {88 pub fn access(allocator: &mem.Allocator, path: []const u8, file_mode: os.FileMode) !bool {
89 if (openRead(allocator, path)) |*file| {89 const path_with_null = try std.cstr.addNullByte(allocator, path);
90 file.close();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 }
91 return true;113 return true;
92 } else |_| {114 } else if (is_windows) {
93 return false;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");
94 }127 }
95 }128 }
96129
std/os/linux/index.zig+9
...@@ -38,6 +38,11 @@ pub const MAP_STACK = 0x20000;...@@ -38,6 +38,11 @@ pub const MAP_STACK = 0x20000;
38pub const MAP_HUGETLB = 0x40000;38pub const MAP_HUGETLB = 0x40000;
39pub const MAP_FILE = 0;39pub 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
41pub const WNOHANG = 1;46pub const WNOHANG = 1;
42pub const WUNTRACED = 2;47pub const WUNTRACED = 2;
43pub const WSTOPPED = 2;48pub const WSTOPPED = 2;
...@@ -705,6 +710,10 @@ pub fn pread(fd: i32, buf: &u8, count: usize, offset: usize) usize {...@@ -705,6 +710,10 @@ pub fn pread(fd: i32, buf: &u8, count: usize, offset: usize) usize {
705 return syscall4(SYS_pread, usize(fd), @ptrToInt(buf), count, offset);710 return syscall4(SYS_pread, usize(fd), @ptrToInt(buf), count, offset);
706}711}
707712
713pub fn access(path: &const u8, mode: u32) usize {
714 return syscall2(SYS_access, @ptrToInt(path), mode);
715}
716
708pub fn pipe(fd: &[2]i32) usize {717pub fn pipe(fd: &[2]i32) usize {
709 return pipe2(fd, 0);718 return pipe2(fd, 0);
710}719}
std/os/test.zig+17
...@@ -23,3 +23,20 @@ test "makePath, put some files in it, deleteTree" {...@@ -23,3 +23,20 @@ test "makePath, put some files in it, deleteTree" {
23 assert(err == error.PathNotFound);23 assert(err == error.PathNotFound);
24 }24 }
25}25}
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...@@ -78,6 +78,8 @@ pub extern "kernel32" stdcallcc fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem
78pub extern "kernel32" stdcallcc fn MoveFileExA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR,78pub extern "kernel32" stdcallcc fn MoveFileExA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR,
79 dwFlags: DWORD) BOOL;79 dwFlags: DWORD) BOOL;
8080
81pub extern "kernel32" stdcallcc fn PathFileExists(pszPath: ?LPCTSTR) BOOL;
82
81pub extern "kernel32" stdcallcc fn ReadFile(in_hFile: HANDLE, out_lpBuffer: &c_void,83pub extern "kernel32" stdcallcc fn ReadFile(in_hFile: HANDLE, out_lpBuffer: &c_void,
82 in_nNumberOfBytesToRead: DWORD, out_lpNumberOfBytesRead: &DWORD,84 in_nNumberOfBytesToRead: DWORD, out_lpNumberOfBytesRead: &DWORD,
83 in_out_lpOverlapped: ?&OVERLAPPED) BOOL;85 in_out_lpOverlapped: ?&OVERLAPPED) BOOL;