authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-30 15:14:04-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-30 15:35:27-05:00
log413f9a5cfc9e867e3bc69b47b38c62b52a52d5e9
tree527b612cd0b7de432ed0738cf8c181a8f37dfb93
parentd039fed831cfc219821b58f1d819d79ad49dc652
signaturelock-open Commit is signed but in an unrecognized format.

move `std.fs.Dir.cwd` to `std.fs.cwd`

update to non-deprecated std.fs APIs throughout the codebase Related: #3811

15 files changed, 224 insertions(+), 88 deletions(-)

lib/std/build.zig+1-1
......@@ -2416,7 +2416,7 @@ fn findVcpkgRoot(allocator: *Allocator) !?[]const u8 {
24162416 const path_file = try fs.path.join(allocator, [_][]const u8{ appdata_path, "vcpkg.path.txt" });
24172417 defer allocator.free(path_file);
24182418
2419 const file = fs.File.openRead(path_file) catch return null;
2419 const file = fs.cwd().openFile(path_file, .{}) catch return null;
24202420 defer file.close();
24212421
24222422 const size = @intCast(usize, try file.getEndPos());
lib/std/debug.zig+2-2
......@@ -1131,7 +1131,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
11311131}
11321132
11331133fn printLineFromFileAnyOs(out_stream: var, line_info: LineInfo) !void {
1134 var f = try File.openRead(line_info.file_name);
1134 var f = try fs.cwd().openFile(line_info.file_name, .{});
11351135 defer f.close();
11361136 // TODO fstat and make sure that the file has the correct size
11371137
......@@ -2089,7 +2089,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
20892089 const ofile_path = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + ofile.n_strx));
20902090
20912091 gop.kv.value = MachOFile{
2092 .bytes = try std.fs.Dir.cwd().readFileAllocAligned(
2092 .bytes = try std.fs.cwd().readFileAllocAligned(
20932093 di.ofiles.allocator,
20942094 ofile_path,
20952095 maxInt(usize),
lib/std/fs.zig+137-35
......@@ -13,8 +13,6 @@ pub const File = @import("fs/file.zig").File;
1313
1414pub const symLink = os.symlink;
1515pub const symLinkC = os.symlinkC;
16pub const deleteFile = os.unlink;
17pub const deleteFileC = os.unlinkC;
1816pub const rename = os.rename;
1917pub const renameC = os.renameC;
2018pub const renameW = os.renameW;
......@@ -88,13 +86,15 @@ pub fn updateFile(source_path: []const u8, dest_path: []const u8) !PrevStatus {
8886/// If any of the directories do not exist for dest_path, they are created.
8987/// TODO https://github.com/ziglang/zig/issues/2885
9088pub fn updateFileMode(source_path: []const u8, dest_path: []const u8, mode: ?File.Mode) !PrevStatus {
91 var src_file = try File.openRead(source_path);
89 const my_cwd = cwd();
90
91 var src_file = try my_cwd.openFile(source_path, .{});
9292 defer src_file.close();
9393
9494 const src_stat = try src_file.stat();
9595 check_dest_stat: {
9696 const dest_stat = blk: {
97 var dest_file = File.openRead(dest_path) catch |err| switch (err) {
97 var dest_file = my_cwd.openFile(dest_path, .{}) catch |err| switch (err) {
9898 error.FileNotFound => break :check_dest_stat,
9999 else => |e| return e,
100100 };
......@@ -157,7 +157,7 @@ pub fn updateFileMode(source_path: []const u8, dest_path: []const u8, mode: ?Fil
157157/// in the same directory as dest_path.
158158/// Destination file will have the same mode as the source file.
159159pub fn copyFile(source_path: []const u8, dest_path: []const u8) !void {
160 var in_file = try File.openRead(source_path);
160 var in_file = try cwd().openFile(source_path, .{});
161161 defer in_file.close();
162162
163163 const mode = try in_file.mode();
......@@ -180,7 +180,7 @@ pub fn copyFile(source_path: []const u8, dest_path: []const u8) !void {
180180/// merged and readily available,
181181/// there is a possibility of power loss or application termination leaving temporary files present
182182pub fn copyFileMode(source_path: []const u8, dest_path: []const u8, mode: File.Mode) !void {
183 var in_file = try File.openRead(source_path);
183 var in_file = try cwd().openFile(source_path, .{});
184184 defer in_file.close();
185185
186186 var atomic_file = try AtomicFile.init(dest_path, mode);
......@@ -206,8 +206,6 @@ pub const AtomicFile = struct {
206206
207207 /// dest_path must remain valid for the lifetime of AtomicFile
208208 /// call finish to atomically replace dest_path with contents
209 /// TODO once we have null terminated pointers, use the
210 /// openWriteNoClobberN function
211209 pub fn init(dest_path: []const u8, mode: File.Mode) InitError!AtomicFile {
212210 const dirname = path.dirname(dest_path);
213211 var rand_buf: [12]u8 = undefined;
......@@ -224,15 +222,19 @@ pub const AtomicFile = struct {
224222
225223 tmp_path_buf[tmp_path_len] = 0;
226224
225 const my_cwd = cwd();
226
227227 while (true) {
228228 try crypto.randomBytes(rand_buf[0..]);
229229 b64_fs_encoder.encode(tmp_path_buf[dirname_component_len..tmp_path_len], rand_buf);
230230
231 const file = File.openWriteNoClobberC(@ptrCast([*:0]u8, &tmp_path_buf), mode) catch |err| switch (err) {
231 // TODO https://github.com/ziglang/zig/issues/3770 to clean up this @ptrCast
232 const file = my_cwd.createFileC(
233 @ptrCast([*:0]u8, &tmp_path_buf),
234 .{ .mode = mode, .exclusive = true },
235 ) catch |err| switch (err) {
232236 error.PathAlreadyExists => continue,
233 // TODO zig should figure out that this error set does not include PathAlreadyExists since
234 // it is handled in the above switch
235 else => return err,
237 else => |e| return e,
236238 };
237239
238240 return AtomicFile{
......@@ -248,7 +250,7 @@ pub const AtomicFile = struct {
248250 pub fn deinit(self: *AtomicFile) void {
249251 if (!self.finished) {
250252 self.file.close();
251 deleteFileC(@ptrCast([*:0]u8, &self.tmp_path_buf)) catch {};
253 cwd().deleteFileC(@ptrCast([*:0]u8, &self.tmp_path_buf)) catch {};
252254 self.finished = true;
253255 }
254256 }
......@@ -350,12 +352,12 @@ pub fn deleteTree(full_path: []const u8) !void {
350352 CannotDeleteRootDirectory,
351353 }.CannotDeleteRootDirectory;
352354
353 var dir = try Dir.cwd().openDirList(dirname);
355 var dir = try cwd().openDirList(dirname);
354356 defer dir.close();
355357
356358 return dir.deleteTree(path.basename(full_path));
357359 } else {
358 return Dir.cwd().deleteTree(full_path);
360 return cwd().deleteTree(full_path);
359361 }
360362}
361363
......@@ -657,17 +659,6 @@ pub const Dir = struct {
657659 }
658660 }
659661
660 /// Returns an handle to the current working directory that is open for traversal.
661 /// Closing the returned `Dir` is checked illegal behavior. Iterating over the result is illegal behavior.
662 /// On POSIX targets, this function is comptime-callable.
663 pub fn cwd() Dir {
664 if (builtin.os == .windows) {
665 return Dir{ .fd = os.windows.peb().ProcessParameters.CurrentDirectory.Handle };
666 } else {
667 return Dir{ .fd = os.AT_FDCWD };
668 }
669 }
670
671662 pub const OpenError = error{
672663 FileNotFound,
673664 NotDir,
......@@ -683,12 +674,12 @@ pub const Dir = struct {
683674 DeviceBusy,
684675 } || os.UnexpectedError;
685676
686 /// Deprecated; call `Dir.cwd().openDirList` directly.
677 /// Deprecated; call `cwd().openDirList` directly.
687678 pub fn open(dir_path: []const u8) OpenError!Dir {
688679 return cwd().openDirList(dir_path);
689680 }
690681
691 /// Deprecated; call `Dir.cwd().openDirListC` directly.
682 /// Deprecated; call `cwd().openDirListC` directly.
692683 pub fn openC(dir_path_c: [*:0]const u8) OpenError!Dir {
693684 return cwd().openDirListC(dir_path_c);
694685 }
......@@ -700,7 +691,9 @@ pub const Dir = struct {
700691
701692 /// Opens a file for reading or writing, without attempting to create a new file.
702693 /// Call `File.close` to release the resource.
694 /// Asserts that the path parameter has no null bytes.
703695 pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File {
696 if (std.debug.runtime_safety) for (sub_path) |byte| assert(byte != 0);
704697 if (builtin.os == .windows) {
705698 const path_w = try os.windows.sliceToPrefixedFileW(sub_path);
706699 return self.openFileW(&path_w, flags);
......@@ -737,7 +730,9 @@ pub const Dir = struct {
737730
738731 /// Creates, opens, or overwrites a file with write access.
739732 /// Call `File.close` on the result when done.
733 /// Asserts that the path parameter has no null bytes.
740734 pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File {
735 if (std.debug.runtime_safety) for (sub_path) |byte| assert(byte != 0);
741736 if (builtin.os == .windows) {
742737 const path_w = try os.windows.sliceToPrefixedFileW(sub_path);
743738 return self.createFileW(&path_w, flags);
......@@ -865,7 +860,10 @@ pub const Dir = struct {
865860 /// list the contents of a directory, open it with `openDirList`.
866861 ///
867862 /// Call `close` on the result when done.
863 ///
864 /// Asserts that the path parameter has no null bytes.
868865 pub fn openDirTraverse(self: Dir, sub_path: []const u8) OpenError!Dir {
866 if (std.debug.runtime_safety) for (sub_path) |byte| assert(byte != 0);
869867 if (builtin.os == .windows) {
870868 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
871869 return self.openDirTraverseW(&sub_path_w);
......@@ -880,7 +878,10 @@ pub const Dir = struct {
880878 /// same and may be more efficient.
881879 ///
882880 /// Call `close` on the result when done.
881 ///
882 /// Asserts that the path parameter has no null bytes.
883883 pub fn openDirList(self: Dir, sub_path: []const u8) OpenError!Dir {
884 if (std.debug.runtime_safety) for (sub_path) |byte| assert(byte != 0);
884885 if (builtin.os == .windows) {
885886 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
886887 return self.openDirListW(&sub_path_w);
......@@ -995,9 +996,12 @@ pub const Dir = struct {
995996 pub const DeleteFileError = os.UnlinkError;
996997
997998 /// Delete a file name and possibly the file it refers to, based on an open directory handle.
999 /// Asserts that the path parameter has no null bytes.
9981000 pub fn deleteFile(self: Dir, sub_path: []const u8) DeleteFileError!void {
999 const sub_path_c = try os.toPosixPath(sub_path);
1000 return self.deleteFileC(&sub_path_c);
1001 os.unlinkat(self.fd, sub_path, 0) catch |err| switch (err) {
1002 error.DirNotEmpty => unreachable, // not passing AT_REMOVEDIR
1003 else => |e| return e,
1004 };
10011005 }
10021006
10031007 /// Same as `deleteFile` except the parameter is null-terminated.
......@@ -1008,6 +1012,14 @@ pub const Dir = struct {
10081012 };
10091013 }
10101014
1015 /// Same as `deleteFile` except the parameter is WTF-16 encoded.
1016 pub fn deleteFileW(self: Dir, sub_path_w: [*:0]const u16) DeleteFileError!void {
1017 os.unlinkatW(self.fd, sub_path_w, 0) catch |err| switch (err) {
1018 error.DirNotEmpty => unreachable, // not passing AT_REMOVEDIR
1019 else => |e| return e,
1020 };
1021 }
1022
10111023 pub const DeleteDirError = error{
10121024 DirNotEmpty,
10131025 FileNotFound,
......@@ -1026,7 +1038,9 @@ pub const Dir = struct {
10261038
10271039 /// Returns `error.DirNotEmpty` if the directory is not empty.
10281040 /// To delete a directory recursively, see `deleteTree`.
1041 /// Asserts that the path parameter has no null bytes.
10291042 pub fn deleteDir(self: Dir, sub_path: []const u8) DeleteDirError!void {
1043 if (std.debug.runtime_safety) for (sub_path) |byte| assert(byte != 0);
10301044 if (builtin.os == .windows) {
10311045 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
10321046 return self.deleteDirW(&sub_path_w);
......@@ -1054,7 +1068,9 @@ pub const Dir = struct {
10541068
10551069 /// Read value of a symbolic link.
10561070 /// The return value is a slice of `buffer`, from index `0`.
1071 /// Asserts that the path parameter has no null bytes.
10571072 pub fn readLink(self: Dir, sub_path: []const u8, buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
1073 if (std.debug.runtime_safety) for (sub_path) |byte| assert(byte != 0);
10581074 const sub_path_c = try os.toPosixPath(sub_path);
10591075 return self.readLinkC(&sub_path_c, buffer);
10601076 }
......@@ -1265,8 +1281,94 @@ pub const Dir = struct {
12651281 }
12661282 }
12671283 }
1284
1285 /// Writes content to the file system, creating a new file if it does not exist, truncating
1286 /// if it already exists.
1287 pub fn writeFile(self: Dir, sub_path: []const u8, data: []const u8) !void {
1288 var file = try self.createFile(sub_path, .{});
1289 defer file.close();
1290 try file.write(data);
1291 }
12681292};
12691293
1294/// Returns an handle to the current working directory that is open for traversal.
1295/// Closing the returned `Dir` is checked illegal behavior. Iterating over the result is illegal behavior.
1296/// On POSIX targets, this function is comptime-callable.
1297pub fn cwd() Dir {
1298 if (builtin.os == .windows) {
1299 return Dir{ .fd = os.windows.peb().ProcessParameters.CurrentDirectory.Handle };
1300 } else {
1301 return Dir{ .fd = os.AT_FDCWD };
1302 }
1303}
1304
1305/// Opens a file for reading or writing, without attempting to create a new file, based on an absolute path.
1306/// Call `File.close` to release the resource.
1307/// Asserts that the path is absolute. See `Dir.openFile` for a function that
1308/// operates on both absolute and relative paths.
1309/// Asserts that the path parameter has no null bytes. See `openFileAbsoluteC` for a function
1310/// that accepts a null-terminated path.
1311pub fn openFileAbsolute(absolute_path: []const u8, flags: File.OpenFlags) File.OpenError!File {
1312 assert(path.isAbsolute(absolute_path));
1313 return cwd().openFile(absolute_path, flags);
1314}
1315
1316/// Same as `openFileAbsolute` but the path parameter is null-terminated.
1317pub fn openFileAbsoluteC(absolute_path_c: [*:0]const u8, flags: File.OpenFlags) File.OpenError!File {
1318 assert(path.isAbsoluteC(absolute_path_c));
1319 return cwd().openFileC(absolute_path_c, flags);
1320}
1321
1322/// Same as `openFileAbsolute` but the path parameter is WTF-16 encoded.
1323pub fn openFileAbsoluteW(absolute_path_w: [*:0]const u16, flags: File.OpenFlags) File.OpenError!File {
1324 assert(path.isAbsoluteW(absolute_path_w));
1325 return cwd().openFileW(absolute_path_w, flags);
1326}
1327
1328/// Creates, opens, or overwrites a file with write access, based on an absolute path.
1329/// Call `File.close` to release the resource.
1330/// Asserts that the path is absolute. See `Dir.createFile` for a function that
1331/// operates on both absolute and relative paths.
1332/// Asserts that the path parameter has no null bytes. See `createFileAbsoluteC` for a function
1333/// that accepts a null-terminated path.
1334pub fn createFileAbsolute(absolute_path: []const u8, flags: File.CreateFlags) File.OpenError!File {
1335 assert(path.isAbsolute(absolute_path));
1336 return cwd().createFile(absolute_path, flags);
1337}
1338
1339/// Same as `createFileAbsolute` but the path parameter is null-terminated.
1340pub fn createFileAbsoluteC(absolute_path_c: [*:0]const u8, flags: File.CreateFlags) File.OpenError!File {
1341 assert(path.isAbsoluteC(absolute_path_c));
1342 return cwd().createFileC(absolute_path_c, flags);
1343}
1344
1345/// Same as `createFileAbsolute` but the path parameter is WTF-16 encoded.
1346pub fn createFileAbsoluteW(absolute_path_w: [*:0]const u16, flags: File.CreateFlags) File.OpenError!File {
1347 assert(path.isAbsoluteW(absolute_path_w));
1348 return cwd().createFileW(absolute_path_w, flags);
1349}
1350
1351/// Delete a file name and possibly the file it refers to, based on an absolute path.
1352/// Asserts that the path is absolute. See `Dir.deleteFile` for a function that
1353/// operates on both absolute and relative paths.
1354/// Asserts that the path parameter has no null bytes.
1355pub fn deleteFileAbsolute(absolute_path: []const u8) DeleteFileError!void {
1356 assert(path.isAbsolute(absolute_path));
1357 return cwd().deleteFile(absolute_path);
1358}
1359
1360/// Same as `deleteFileAbsolute` except the parameter is null-terminated.
1361pub fn deleteFileAbsoluteC(absolute_path_c: [*:0]const u8) DeleteFileError!void {
1362 assert(path.isAbsoluteC(absolute_path_c));
1363 return cwd().deleteFileC(absolute_path_c);
1364}
1365
1366/// Same as `deleteFileAbsolute` except the parameter is WTF-16 encoded.
1367pub fn deleteFileAbsoluteW(absolute_path_w: [*:0]const u16) DeleteFileError!void {
1368 assert(path.isAbsoluteW(absolute_path_w));
1369 return cwd().deleteFileW(absolute_path_w);
1370}
1371
12701372pub const Walker = struct {
12711373 stack: std.ArrayList(StackItem),
12721374 name_buffer: std.Buffer,
......@@ -1339,7 +1441,7 @@ pub const Walker = struct {
13391441pub fn walkPath(allocator: *Allocator, dir_path: []const u8) !Walker {
13401442 assert(!mem.endsWith(u8, dir_path, path.sep_str));
13411443
1342 var dir = try Dir.cwd().openDirList(dir_path);
1444 var dir = try cwd().openDirList(dir_path);
13431445 errdefer dir.close();
13441446
13451447 var name_buffer = try std.Buffer.init(allocator, dir_path);
......@@ -1373,18 +1475,18 @@ pub const OpenSelfExeError = os.OpenError || os.windows.CreateFileError || SelfE
13731475
13741476pub fn openSelfExe() OpenSelfExeError!File {
13751477 if (builtin.os == .linux) {
1376 return File.openReadC("/proc/self/exe");
1478 return openFileAbsoluteC("/proc/self/exe", .{});
13771479 }
13781480 if (builtin.os == .windows) {
13791481 const wide_slice = selfExePathW();
13801482 const prefixed_path_w = try os.windows.wToPrefixedFileW(wide_slice);
1381 return Dir.cwd().openReadW(&prefixed_path_w);
1483 return cwd().openReadW(&prefixed_path_w);
13821484 }
13831485 var buf: [MAX_PATH_BYTES]u8 = undefined;
13841486 const self_exe_path = try selfExePath(&buf);
13851487 buf[self_exe_path.len] = 0;
1386 // TODO avoid @ptrCast here using slice syntax with https://github.com/ziglang/zig/issues/3731
1387 return File.openReadC(@ptrCast([*:0]u8, self_exe_path.ptr));
1488 // TODO avoid @ptrCast here using slice syntax with https://github.com/ziglang/zig/issues/3770
1489 return openFileAbsoluteC(@ptrCast([*:0]u8, self_exe_path.ptr), .{});
13881490}
13891491
13901492test "openSelfExe" {
lib/std/fs/file.zig+10-10
......@@ -51,42 +51,42 @@ pub const File = struct {
5151
5252 /// Deprecated; call `std.fs.Dir.openFile` directly.
5353 pub fn openRead(path: []const u8) OpenError!File {
54 return std.fs.Dir.cwd().openFile(path, .{});
54 return std.fs.cwd().openFile(path, .{});
5555 }
5656
5757 /// Deprecated; call `std.fs.Dir.openFileC` directly.
5858 pub fn openReadC(path_c: [*:0]const u8) OpenError!File {
59 return std.fs.Dir.cwd().openFileC(path_c, .{});
59 return std.fs.cwd().openFileC(path_c, .{});
6060 }
6161
6262 /// Deprecated; call `std.fs.Dir.openFileW` directly.
6363 pub fn openReadW(path_w: [*]const u16) OpenError!File {
64 return std.fs.Dir.cwd().openFileW(path_w, .{});
64 return std.fs.cwd().openFileW(path_w, .{});
6565 }
6666
6767 /// Deprecated; call `std.fs.Dir.createFile` directly.
6868 pub fn openWrite(path: []const u8) OpenError!File {
69 return std.fs.Dir.cwd().createFile(path, .{});
69 return std.fs.cwd().createFile(path, .{});
7070 }
7171
7272 /// Deprecated; call `std.fs.Dir.createFile` directly.
7373 pub fn openWriteMode(path: []const u8, file_mode: Mode) OpenError!File {
74 return std.fs.Dir.cwd().createFile(path, .{ .mode = file_mode });
74 return std.fs.cwd().createFile(path, .{ .mode = file_mode });
7575 }
7676
7777 /// Deprecated; call `std.fs.Dir.createFileC` directly.
7878 pub fn openWriteModeC(path_c: [*:0]const u8, file_mode: Mode) OpenError!File {
79 return std.fs.Dir.cwd().createFileC(path_c, .{ .mode = file_mode });
79 return std.fs.cwd().createFileC(path_c, .{ .mode = file_mode });
8080 }
8181
8282 /// Deprecated; call `std.fs.Dir.createFileW` directly.
8383 pub fn openWriteModeW(path_w: [*:0]const u16, file_mode: Mode) OpenError!File {
84 return std.fs.Dir.cwd().createFileW(path_w, .{ .mode = file_mode });
84 return std.fs.cwd().createFileW(path_w, .{ .mode = file_mode });
8585 }
8686
8787 /// Deprecated; call `std.fs.Dir.createFile` directly.
8888 pub fn openWriteNoClobber(path: []const u8, file_mode: Mode) OpenError!File {
89 return std.fs.Dir.cwd().createFile(path, .{
89 return std.fs.cwd().createFile(path, .{
9090 .mode = file_mode,
9191 .exclusive = true,
9292 });
......@@ -94,7 +94,7 @@ pub const File = struct {
9494
9595 /// Deprecated; call `std.fs.Dir.createFileC` directly.
9696 pub fn openWriteNoClobberC(path_c: [*:0]const u8, file_mode: Mode) OpenError!File {
97 return std.fs.Dir.cwd().createFileC(path_c, .{
97 return std.fs.cwd().createFileC(path_c, .{
9898 .mode = file_mode,
9999 .exclusive = true,
100100 });
......@@ -102,7 +102,7 @@ pub const File = struct {
102102
103103 /// Deprecated; call `std.fs.Dir.createFileW` directly.
104104 pub fn openWriteNoClobberW(path_w: [*:0]const u16, file_mode: Mode) OpenError!File {
105 return std.fs.Dir.cwd().createFileW(path_w, .{
105 return std.fs.cwd().createFileW(path_w, .{
106106 .mode = file_mode,
107107 .exclusive = true,
108108 });
lib/std/fs/path.zig+32-1
......@@ -128,6 +128,14 @@ test "join" {
128128 testJoinPosix([_][]const u8{ "a/", "/c" }, "a/c");
129129}
130130
131pub fn isAbsoluteC(path_c: [*:0]const u8) bool {
132 if (builtin.os == .windows) {
133 return isAbsoluteWindowsC(path_c);
134 } else {
135 return isAbsolutePosixC(path_c);
136 }
137}
138
131139pub fn isAbsolute(path: []const u8) bool {
132140 if (builtin.os == .windows) {
133141 return isAbsoluteWindows(path);
......@@ -136,7 +144,7 @@ pub fn isAbsolute(path: []const u8) bool {
136144 }
137145}
138146
139pub fn isAbsoluteW(path_w: [*]const u16) bool {
147pub fn isAbsoluteW(path_w: [*:0]const u16) bool {
140148 if (path_w[0] == '/')
141149 return true;
142150
......@@ -174,10 +182,33 @@ pub fn isAbsoluteWindows(path: []const u8) bool {
174182 return false;
175183}
176184
185pub fn isAbsoluteWindowsC(path_c: [*:0]const u8) bool {
186 if (path_c[0] == '/')
187 return true;
188
189 if (path_c[0] == '\\') {
190 return true;
191 }
192 if (path_c[0] == 0 or path_c[1] == 0 or path_c[2] == 0) {
193 return false;
194 }
195 if (path_c[1] == ':') {
196 if (path_c[2] == '/')
197 return true;
198 if (path_c[2] == '\\')
199 return true;
200 }
201 return false;
202}
203
177204pub fn isAbsolutePosix(path: []const u8) bool {
178205 return path[0] == sep_posix;
179206}
180207
208pub fn isAbsolutePosixC(path_c: [*:0]const u8) bool {
209 return path_c[0] == sep_posix;
210}
211
181212test "isAbsoluteWindows" {
182213 testIsAbsoluteWindows("/", true);
183214 testIsAbsoluteWindows("//", true);
lib/std/io.zig+4-7
......@@ -61,17 +61,14 @@ pub const COutStream = @import("io/c_out_stream.zig").COutStream;
6161pub const InStream = @import("io/in_stream.zig").InStream;
6262pub const OutStream = @import("io/out_stream.zig").OutStream;
6363
64/// TODO move this to `std.fs` and add a version to `std.fs.Dir`.
64/// Deprecated; use `std.fs.Dir.writeFile`.
6565pub fn writeFile(path: []const u8, data: []const u8) !void {
66 var file = try File.openWrite(path);
67 defer file.close();
68 try file.write(data);
66 return fs.cwd().writeFile(path, data);
6967}
7068
71/// On success, caller owns returned buffer.
72/// This function is deprecated; use `std.fs.Dir.readFileAlloc`.
69/// Deprecated; use `std.fs.Dir.readFileAlloc`.
7370pub fn readFileAlloc(allocator: *mem.Allocator, path: []const u8) ![]u8 {
74 return fs.Dir.cwd().readFileAlloc(allocator, path, math.maxInt(usize));
71 return fs.cwd().readFileAlloc(allocator, path, math.maxInt(usize));
7572}
7673
7774pub fn BufferedInStream(comptime Error: type) type {
lib/std/io/test.zig+15-13
......@@ -14,12 +14,14 @@ test "write a file, read it, then delete it" {
1414 var raw_bytes: [200 * 1024]u8 = undefined;
1515 var allocator = &std.heap.FixedBufferAllocator.init(raw_bytes[0..]).allocator;
1616
17 const cwd = fs.cwd();
18
1719 var data: [1024]u8 = undefined;
1820 var prng = DefaultPrng.init(1234);
1921 prng.random.bytes(data[0..]);
2022 const tmp_file_name = "temp_test_file.txt";
2123 {
22 var file = try File.openWrite(tmp_file_name);
24 var file = try cwd.createFile(tmp_file_name, .{});
2325 defer file.close();
2426
2527 var file_out_stream = file.outStream();
......@@ -32,8 +34,8 @@ test "write a file, read it, then delete it" {
3234 }
3335
3436 {
35 // make sure openWriteNoClobber doesn't harm the file
36 if (File.openWriteNoClobber(tmp_file_name, File.default_mode)) |file| {
37 // Make sure the exclusive flag is honored.
38 if (cwd.createFile(tmp_file_name, .{ .exclusive = true })) |file| {
3739 unreachable;
3840 } else |err| {
3941 std.debug.assert(err == File.OpenError.PathAlreadyExists);
......@@ -41,7 +43,7 @@ test "write a file, read it, then delete it" {
4143 }
4244
4345 {
44 var file = try File.openRead(tmp_file_name);
46 var file = try cwd.openFile(tmp_file_name, .{});
4547 defer file.close();
4648
4749 const file_size = try file.getEndPos();
......@@ -58,7 +60,7 @@ test "write a file, read it, then delete it" {
5860 expect(mem.eql(u8, contents["begin".len .. contents.len - "end".len], data));
5961 expect(mem.eql(u8, contents[contents.len - "end".len ..], "end"));
6062 }
61 try fs.deleteFile(tmp_file_name);
63 try cwd.deleteFile(tmp_file_name);
6264}
6365
6466test "BufferOutStream" {
......@@ -274,7 +276,7 @@ test "BitOutStream" {
274276test "BitStreams with File Stream" {
275277 const tmp_file_name = "temp_test_file.txt";
276278 {
277 var file = try File.openWrite(tmp_file_name);
279 var file = try fs.cwd().createFile(tmp_file_name, .{});
278280 defer file.close();
279281
280282 var file_out = file.outStream();
......@@ -291,7 +293,7 @@ test "BitStreams with File Stream" {
291293 try bit_stream.flushBits();
292294 }
293295 {
294 var file = try File.openRead(tmp_file_name);
296 var file = try fs.cwd().openFile(tmp_file_name, .{});
295297 defer file.close();
296298
297299 var file_in = file.inStream();
......@@ -316,7 +318,7 @@ test "BitStreams with File Stream" {
316318
317319 expectError(error.EndOfStream, bit_stream.readBitsNoEof(u1, 1));
318320 }
319 try fs.deleteFile(tmp_file_name);
321 try fs.cwd().deleteFile(tmp_file_name);
320322}
321323
322324fn testIntSerializerDeserializer(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
......@@ -599,7 +601,7 @@ test "c out stream" {
599601 const out_file = std.c.fopen(filename, "w") orelse return error.UnableToOpenTestFile;
600602 defer {
601603 _ = std.c.fclose(out_file);
602 fs.deleteFileC(filename) catch {};
604 fs.cwd().deleteFileC(filename) catch {};
603605 }
604606
605607 const out_stream = &io.COutStream.init(out_file).stream;
......@@ -608,10 +610,10 @@ test "c out stream" {
608610
609611test "File seek ops" {
610612 const tmp_file_name = "temp_test_file.txt";
611 var file = try File.openWrite(tmp_file_name);
613 var file = try fs.cwd().createFile(tmp_file_name, .{});
612614 defer {
613615 file.close();
614 fs.deleteFile(tmp_file_name) catch {};
616 fs.cwd().deleteFile(tmp_file_name) catch {};
615617 }
616618
617619 try file.write([_]u8{0x55} ** 8192);
......@@ -632,10 +634,10 @@ test "File seek ops" {
632634
633635test "updateTimes" {
634636 const tmp_file_name = "just_a_temporary_file.txt";
635 var file = try File.openWrite(tmp_file_name);
637 var file = try fs.cwd().createFile(tmp_file_name, .{});
636638 defer {
637639 file.close();
638 std.fs.deleteFile(tmp_file_name) catch {};
640 std.fs.cwd().deleteFile(tmp_file_name) catch {};
639641 }
640642 var stat_old = try file.stat();
641643 // Set atime and mtime to 5s before
lib/std/net.zig+2-2
......@@ -812,7 +812,7 @@ fn linuxLookupNameFromHosts(
812812 family: os.sa_family_t,
813813 port: u16,
814814) !void {
815 const file = fs.File.openReadC("/etc/hosts") catch |err| switch (err) {
815 const file = fs.openFileAbsoluteC("/etc/hosts", .{}) catch |err| switch (err) {
816816 error.FileNotFound,
817817 error.NotDir,
818818 error.AccessDenied,
......@@ -1006,7 +1006,7 @@ fn getResolvConf(allocator: *mem.Allocator, rc: *ResolvConf) !void {
10061006 };
10071007 errdefer rc.deinit();
10081008
1009 const file = fs.File.openReadC("/etc/resolv.conf") catch |err| switch (err) {
1009 const file = fs.openFileAbsoluteC("/etc/resolv.conf", .{}) catch |err| switch (err) {
10101010 error.FileNotFound,
10111011 error.NotDir,
10121012 error.AccessDenied,
lib/std/os.zig+7-5
......@@ -798,7 +798,7 @@ pub fn execvpeC(file: [*:0]const u8, child_argv: [*:null]const ?[*:0]const u8, e
798798 path_buf[search_path.len] = '/';
799799 mem.copy(u8, path_buf[search_path.len + 1 ..], file_slice);
800800 path_buf[search_path.len + file_slice.len + 1] = 0;
801 // TODO avoid @ptrCast here using slice syntax with https://github.com/ziglang/zig/issues/3731
801 // TODO avoid @ptrCast here using slice syntax with https://github.com/ziglang/zig/issues/3770
802802 err = execveC(@ptrCast([*:0]u8, &path_buf), child_argv, envp);
803803 switch (err) {
804804 error.AccessDenied => seen_eacces = true,
......@@ -834,7 +834,7 @@ pub fn execvpe(
834834 @memcpy(arg_buf.ptr, arg.ptr, arg.len);
835835 arg_buf[arg.len] = 0;
836836
837 // TODO avoid @ptrCast using slice syntax with https://github.com/ziglang/zig/issues/3731
837 // TODO avoid @ptrCast using slice syntax with https://github.com/ziglang/zig/issues/3770
838838 argv_buf[i] = @ptrCast([*:0]u8, arg_buf.ptr);
839839 }
840840 argv_buf[argv_slice.len] = null;
......@@ -842,7 +842,7 @@ pub fn execvpe(
842842 const envp_buf = try createNullDelimitedEnvMap(allocator, env_map);
843843 defer freeNullDelimitedEnvMap(allocator, envp_buf);
844844
845 // TODO avoid @ptrCast here using slice syntax with https://github.com/ziglang/zig/issues/3731
845 // TODO avoid @ptrCast here using slice syntax with https://github.com/ziglang/zig/issues/3770
846846 const argv_ptr = @ptrCast([*:null]?[*:0]u8, argv_buf.ptr);
847847
848848 return execvpeC(argv_buf.ptr[0].?, argv_ptr, envp_buf.ptr);
......@@ -863,12 +863,12 @@ pub fn createNullDelimitedEnvMap(allocator: *mem.Allocator, env_map: *const std.
863863 @memcpy(env_buf.ptr + pair.key.len + 1, pair.value.ptr, pair.value.len);
864864 env_buf[env_buf.len - 1] = 0;
865865
866 // TODO avoid @ptrCast here using slice syntax with https://github.com/ziglang/zig/issues/3731
866 // TODO avoid @ptrCast here using slice syntax with https://github.com/ziglang/zig/issues/3770
867867 envp_buf[i] = @ptrCast([*:0]u8, env_buf.ptr);
868868 }
869869 assert(i == envp_count);
870870 }
871 // TODO avoid @ptrCast here using slice syntax with https://github.com/ziglang/zig/issues/3731
871 // TODO avoid @ptrCast here using slice syntax with https://github.com/ziglang/zig/issues/3770
872872 assert(envp_buf[envp_count] == null);
873873 return @ptrCast([*:null]?[*:0]u8, envp_buf.ptr)[0..envp_count];
874874}
......@@ -1087,7 +1087,9 @@ pub const UnlinkatError = UnlinkError || error{
10871087};
10881088
10891089/// Delete a file name and possibly the file it refers to, based on an open directory handle.
1090/// Asserts that the path parameter has no null bytes.
10901091pub fn unlinkat(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!void {
1092 if (std.debug.runtime_safety) for (file_path) |byte| assert(byte != 0);
10911093 if (builtin.os == .windows) {
10921094 const file_path_w = try windows.sliceToPrefixedFileW(file_path);
10931095 return unlinkatW(dirfd, &file_path_w, flags);
lib/std/os/linux/test.zig+3-4
......@@ -4,6 +4,7 @@ const linux = std.os.linux;
44const mem = std.mem;
55const elf = std.elf;
66const expect = std.testing.expect;
7const fs = std.fs;
78
89test "getpid" {
910 expect(linux.getpid() != 0);
......@@ -45,14 +46,12 @@ test "timer" {
4546 err = linux.epoll_wait(@intCast(i32, epoll_fd), @ptrCast([*]linux.epoll_event, &events), 8, -1);
4647}
4748
48const File = std.fs.File;
49
5049test "statx" {
5150 const tmp_file_name = "just_a_temporary_file.txt";
52 var file = try File.openWrite(tmp_file_name);
51 var file = try fs.cwd().createFile(tmp_file_name, .{});
5352 defer {
5453 file.close();
55 std.fs.deleteFile(tmp_file_name) catch {};
54 fs.cwd().deleteFile(tmp_file_name) catch {};
5655 }
5756
5857 var statx_buf: linux.Statx = undefined;
lib/std/os/test.zig+2-2
......@@ -20,7 +20,7 @@ test "makePath, put some files in it, deleteTree" {
2020 try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c" ++ fs.path.sep_str ++ "file.txt", "nonsense");
2121 try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "file2.txt", "blah");
2222 try fs.deleteTree("os_test_tmp");
23 if (fs.Dir.cwd().openDirTraverse("os_test_tmp")) |dir| {
23 if (fs.cwd().openDirTraverse("os_test_tmp")) |dir| {
2424 @panic("expected error");
2525 } else |err| {
2626 expect(err == error.FileNotFound);
......@@ -111,7 +111,7 @@ test "AtomicFile" {
111111 const content = try io.readFileAlloc(allocator, test_out_file);
112112 expect(mem.eql(u8, content, test_content));
113113
114 try fs.deleteFile(test_out_file);
114 try fs.cwd().deleteFile(test_out_file);
115115}
116116
117117test "thread local storage" {
lib/std/pdb.zig+2-1
......@@ -6,6 +6,7 @@ const mem = std.mem;
66const os = std.os;
77const warn = std.debug.warn;
88const coff = std.coff;
9const fs = std.fs;
910const File = std.fs.File;
1011
1112const ArrayList = std.ArrayList;
......@@ -469,7 +470,7 @@ pub const Pdb = struct {
469470 msf: Msf,
470471
471472 pub fn openFile(self: *Pdb, coff_ptr: *coff.Coff, file_name: []u8) !void {
472 self.in_file = try File.openRead(file_name);
473 self.in_file = try fs.cwd().openFile(file_name, .{});
473474 self.allocator = coff_ptr.allocator;
474475 self.coff = coff_ptr;
475476
src-self-hosted/main.zig+1-1
......@@ -702,7 +702,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
702702 max_src_size,
703703 ) catch |err| switch (err) {
704704 error.IsDir, error.AccessDenied => {
705 var dir = try fs.Dir.cwd().openDirList(file_path);
705 var dir = try fs.cwd().openDirList(file_path);
706706 defer dir.close();
707707
708708 var group = event.Group(FmtError!void).init(fmt.allocator);
src-self-hosted/stage1.zig+1-1
......@@ -279,7 +279,7 @@ fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void
279279 const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) {
280280 error.IsDir, error.AccessDenied => {
281281 // TODO make event based (and dir.next())
282 var dir = try fs.Dir.cwd().openDirList(file_path);
282 var dir = try fs.cwd().openDirList(file_path);
283283 defer dir.close();
284284
285285 var dir_it = dir.iterate();
test/standalone/cat/main.zig+5-3
......@@ -1,7 +1,7 @@
11const std = @import("std");
22const io = std.io;
33const process = std.process;
4const File = std.fs.File;
4const fs = std.fs;
55const mem = std.mem;
66const warn = std.debug.warn;
77const allocator = std.debug.global_allocator;
......@@ -12,6 +12,8 @@ pub fn main() !void {
1212 var catted_anything = false;
1313 const stdout_file = io.getStdOut();
1414
15 const cwd = fs.cwd();
16
1517 while (args_it.next(allocator)) |arg_or_err| {
1618 const arg = try unwrapArg(arg_or_err);
1719 if (mem.eql(u8, arg, "-")) {
......@@ -20,7 +22,7 @@ pub fn main() !void {
2022 } else if (arg[0] == '-') {
2123 return usage(exe);
2224 } else {
23 const file = File.openRead(arg) catch |err| {
25 const file = cwd.openFile(arg, .{}) catch |err| {
2426 warn("Unable to open file: {}\n", @errorName(err));
2527 return err;
2628 };
......@@ -40,7 +42,7 @@ fn usage(exe: []const u8) !void {
4042 return error.Invalid;
4143}
4244
43fn cat_file(stdout: File, file: File) !void {
45fn cat_file(stdout: fs.File, file: fs.File) !void {
4446 var buf: [1024 * 4]u8 = undefined;
4547
4648 while (true) {