authorgravatar for 58830309+g-w1@users.noreply.github.comg-w1 <58830309+g-w1@users.noreply.github.com> 2020-11-18 02:42:35-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-11-18 08:42:35+01:00
loga0226ab05b50341622ace8314bdad3da7cd7e35d
treef200ba0b5dd6aacde4428b13f19f5c6ab5743b45
parent238718b93abfe97bd5531103cf39714ec66fd86e
signature Signed by PGP key 4AEE18F83AFDEB23

std: openDirAbsolute and accessAbsolute (#7082)

* add more abosolutes * added wrong files * adding 2 tests and changing the function signatures because of lazy analysis not checking them * fix a bug that got uncovered by lazy eval * Add compile error when using WASI with openDirAbsolute and accessAbsolute * typo

3 files changed, 99 insertions(+), 5 deletions(-)

lib/std/fs.zig+62-2
......@@ -1883,11 +1883,41 @@ pub fn cwd() Dir {
18831883 }
18841884}
18851885
1886/// Opens a directory at the given path. The directory is a system resource that remains
1887/// open until `close` is called on the result.
1888/// See `openDirAbsoluteZ` for a function that accepts a null-terminated path.
1889///
1890/// Asserts that the path parameter has no null bytes.
1891pub fn openDirAbsolute(absolute_path: []const u8, flags: Dir.OpenDirOptions) File.OpenError!Dir {
1892 if (builtin.os.tag == .wasi) {
1893 @compileError("WASI doesn't have the concept of an absolute directory; use openDir instead for WASI.");
1894 }
1895 assert(path.isAbsolute(absolute_path));
1896 return cwd().openDir(absolute_path, flags);
1897}
1898
1899/// Same as `openDirAbsolute` but the path parameter is null-terminated.
1900pub fn openDirAbsoluteZ(absolute_path_c: [*:0]const u8, flags: Dir.OpenDirOptions) File.OpenError!Dir {
1901 if (builtin.os.tag == .wasi) {
1902 @compileError("WASI doesn't have the concept of an absolute directory; use openDir instead for WASI.");
1903 }
1904 assert(path.isAbsoluteZ(absolute_path_c));
1905 return cwd().openDirZ(absolute_path_c, flags);
1906}
1907/// Same as `openDirAbsolute` but the path parameter is null-terminated.
1908pub fn openDirAbsoluteW(absolute_path_c: [*:0]const u16, flags: Dir.OpenDirOptions) File.OpenError!Dir {
1909 if (builtin.os.tag == .wasi) {
1910 @compileError("WASI doesn't have the concept of an absolute directory; use openDir instead for WASI.");
1911 }
1912 assert(path.isAbsoluteWindowsW(absolute_path_c));
1913 return cwd().openDirW(absolute_path_c, flags);
1914}
1915
18861916/// Opens a file for reading or writing, without attempting to create a new file, based on an absolute path.
18871917/// Call `File.close` to release the resource.
18881918/// Asserts that the path is absolute. See `Dir.openFile` for a function that
18891919/// operates on both absolute and relative paths.
1890/// Asserts that the path parameter has no null bytes. See `openFileAbsoluteC` for a function
1920/// Asserts that the path parameter has no null bytes. See `openFileAbsoluteZ` for a function
18911921/// that accepts a null-terminated path.
18921922pub fn openFileAbsolute(absolute_path: []const u8, flags: File.OpenFlags) File.OpenError!File {
18931923 assert(path.isAbsolute(absolute_path));
......@@ -1908,6 +1938,36 @@ pub fn openFileAbsoluteW(absolute_path_w: []const u16, flags: File.OpenFlags) Fi
19081938 return cwd().openFileW(absolute_path_w, flags);
19091939}
19101940
1941/// Test accessing `path`.
1942/// `path` is UTF8-encoded.
1943/// Be careful of Time-Of-Check-Time-Of-Use race conditions when using this function.
1944/// For example, instead of testing if a file exists and then opening it, just
1945/// open it and handle the error for file not found.
1946/// See `accessAbsoluteZ` for a function that accepts a null-terminated path.
1947pub fn accessAbsolute(absolute_path: []const u8, flags: File.OpenFlags) Dir.AccessError!void {
1948 if (builtin.os.tag == .wasi) {
1949 @compileError("WASI doesn't have the concept of an absolute path; use access instead for WASI.");
1950 }
1951 assert(path.isAbsolute(absolute_path));
1952 try cwd().access(absolute_path, flags);
1953}
1954/// Same as `accessAbsolute` but the path parameter is null-terminated.
1955pub fn accessAbsoluteZ(absolute_path: [*:0]const u8, flags: File.OpenFlags) Dir.AccessError!void {
1956 if (builtin.os.tag == .wasi) {
1957 @compileError("WASI doesn't have the concept of an absolute path; use access instead for WASI.");
1958 }
1959 assert(path.isAbsoluteZ(absolute_path));
1960 try cwd().accessZ(absolute_path, flags);
1961}
1962/// Same as `accessAbsolute` but the path parameter is WTF-16 encoded.
1963pub fn accessAbsoluteW(absolute_path: [*:0]const 16, flags: File.OpenFlags) Dir.AccessError!void {
1964 if (builtin.os.tag == .wasi) {
1965 @compileError("WASI doesn't have the concept of an absolute path; use access instead for WASI.");
1966 }
1967 assert(path.isAbsoluteWindowsW(absolute_path));
1968 try cwd().accessW(absolute_path, flags);
1969}
1970
19111971/// Creates, opens, or overwrites a file with write access, based on an absolute path.
19121972/// Call `File.close` to release the resource.
19131973/// Asserts that the path is absolute. See `Dir.createFile` for a function that
......@@ -2252,7 +2312,7 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {
22522312 const PATH = std.os.getenvZ("PATH") orelse return error.FileNotFound;
22532313 var path_it = mem.tokenize(PATH, &[_]u8{path.delimiter});
22542314 while (path_it.next()) |a_path| {
2255 var resolved_path_buf: [MAX_PATH_BYTES-1:0]u8 = undefined;
2315 var resolved_path_buf: [MAX_PATH_BYTES - 1:0]u8 = undefined;
22562316 const resolved_path = std.fmt.bufPrintZ(&resolved_path_buf, "{s}/{s}", .{
22572317 a_path,
22582318 os.argv[0],
lib/std/fs/test.zig+34
......@@ -49,6 +49,40 @@ fn testReadLink(dir: Dir, target_path: []const u8, symlink_path: []const u8) !vo
4949 testing.expect(mem.eql(u8, target_path, given));
5050}
5151
52test "accessAbsolute" {
53 if (builtin.os.tag == .wasi) return error.SkipZigTest;
54
55 var tmp = tmpDir(.{});
56 defer tmp.cleanup();
57
58 var arena = ArenaAllocator.init(testing.allocator);
59 defer arena.deinit();
60 const base_path = blk: {
61 const relative_path = try fs.path.join(&arena.allocator, &[_][]const u8{ "zig-cache", "tmp", tmp.sub_path[0..] });
62 break :blk try fs.realpathAlloc(&arena.allocator, relative_path);
63 };
64
65 try fs.accessAbsolute(base_path, .{});
66}
67
68test "openDirAbsolute" {
69 if (builtin.os.tag == .wasi) return error.SkipZigTest;
70
71 var tmp = tmpDir(.{});
72 defer tmp.cleanup();
73
74 try tmp.dir.makeDir("subdir");
75 var arena = ArenaAllocator.init(testing.allocator);
76 defer arena.deinit();
77 const base_path = blk: {
78 const relative_path = try fs.path.join(&arena.allocator, &[_][]const u8{ "zig-cache", "tmp", tmp.sub_path[0..], "subdir" });
79 break :blk try fs.realpathAlloc(&arena.allocator, relative_path);
80 };
81
82 var dir = try fs.openDirAbsolute(base_path, .{});
83 defer dir.close();
84}
85
5286test "readLinkAbsolute" {
5387 if (builtin.os.tag == .wasi) return error.SkipZigTest;
5488
lib/std/os.zig+3-3
......@@ -4453,11 +4453,11 @@ pub fn sched_getaffinity(pid: pid_t) SchedGetAffinityError!cpu_set_t {
44534453
44544454/// Used to convert a slice to a null terminated slice on the stack.
44554455/// TODO https://github.com/ziglang/zig/issues/287
4456pub fn toPosixPath(file_path: []const u8) ![PATH_MAX - 1:0]u8 {
4456pub fn toPosixPath(file_path: []const u8) ![MAX_PATH_BYTES - 1:0]u8 {
44574457 if (std.debug.runtime_safety) assert(std.mem.indexOfScalar(u8, file_path, 0) == null);
4458 var path_with_null: [PATH_MAX - 1:0]u8 = undefined;
4458 var path_with_null: [MAX_PATH_BYTES - 1:0]u8 = undefined;
44594459 // >= rather than > to make room for the null byte
4460 if (file_path.len >= PATH_MAX) return error.NameTooLong;
4460 if (file_path.len >= MAX_PATH_BYTES) return error.NameTooLong;
44614461 mem.copy(u8, &path_with_null, file_path);
44624462 path_with_null[file_path.len] = 0;
44634463 return path_with_null;