authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-30 13:32:11-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-30 13:32:11-05:00
logd039fed831cfc219821b58f1d819d79ad49dc652
tree02874006e87e02473a3ad89c0259e55fa235b3c4
parent85e1e3b95f1f1699a842a5e889d8987692a829a4
signaturelock-open Commit is signed but in an unrecognized format.

introduce std.fs.Dir.openFile and std.fs.Dir.createFile

These functions have flags parameters which cover all the use cases. The other functions are now deprecated.

2 files changed, 144 insertions(+), 87 deletions(-)

lib/std/fs.zig+89-14
...@@ -698,29 +698,104 @@ pub const Dir = struct {...@@ -698,29 +698,104 @@ pub const Dir = struct {
698 self.* = undefined;698 self.* = undefined;
699 }699 }
700700
701 /// Call `File.close` on the result when done.701 /// Opens a file for reading or writing, without attempting to create a new file.
702 pub fn openRead(self: Dir, sub_path: []const u8) File.OpenError!File {702 /// Call `File.close` to release the resource.
703 pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File {
703 if (builtin.os == .windows) {704 if (builtin.os == .windows) {
704 const path_w = try os.windows.sliceToPrefixedFileW(sub_path);705 const path_w = try os.windows.sliceToPrefixedFileW(sub_path);
705 return self.openReadW(&path_w);706 return self.openFileW(&path_w, flags);
706 }707 }
707 const path_c = try os.toPosixPath(sub_path);708 const path_c = try os.toPosixPath(sub_path);
708 return self.openReadC(&path_c);709 return self.openFileC(&path_c, flags);
709 }710 }
710711
711 /// Call `File.close` on the result when done.712 /// Same as `openFile` but the path parameter is null-terminated.
712 pub fn openReadC(self: Dir, sub_path: [*:0]const u8) File.OpenError!File {713 pub fn openFileC(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) File.OpenError!File {
713 if (builtin.os == .windows) {714 if (builtin.os == .windows) {
714 const path_w = try os.windows.cStrToPrefixedFileW(sub_path);715 const path_w = try os.windows.cStrToPrefixedFileW(sub_path);
715 return self.openReadW(&path_w);716 return self.openFileW(&path_w, flags);
716 }717 }
717 const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0;718 const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0;
718 const flags = O_LARGEFILE | os.O_RDONLY | os.O_CLOEXEC;719 const os_flags = O_LARGEFILE | os.O_CLOEXEC | if (flags.write and flags.read)
719 const fd = try os.openatC(self.fd, sub_path, flags, 0);720 @as(u32, os.O_RDWR)
720 return File.openHandle(fd);721 else if (flags.write)
722 @as(u32, os.O_WRONLY)
723 else
724 @as(u32, os.O_RDONLY);
725 const fd = try os.openatC(self.fd, sub_path, os_flags, 0);
726 return File{ .handle = fd };
721 }727 }
722728
723 pub fn openReadW(self: Dir, sub_path_w: [*:0]const u16) File.OpenError!File {729 /// Same as `openFile` but the path parameter is WTF-16 encoded.
730 pub fn openFileW(self: Dir, sub_path_w: [*:0]const u16, flags: File.OpenFlags) File.OpenError!File {
731 const w = os.windows;
732 const access_mask = w.SYNCHRONIZE |
733 (if (flags.read) @as(u32, w.GENERIC_READ) else 0) |
734 (if (flags.write) @as(u32, w.GENERIC_WRITE) else 0);
735 return self.openFileWindows(sub_path_w, access_mask, w.FILE_OPEN);
736 }
737
738 /// Creates, opens, or overwrites a file with write access.
739 /// Call `File.close` on the result when done.
740 pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File {
741 if (builtin.os == .windows) {
742 const path_w = try os.windows.sliceToPrefixedFileW(sub_path);
743 return self.createFileW(&path_w, flags);
744 }
745 const path_c = try os.toPosixPath(sub_path);
746 return self.createFileC(&path_c, flags);
747 }
748
749 /// Same as `createFile` but the path parameter is null-terminated.
750 pub fn createFileC(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags) File.OpenError!File {
751 if (builtin.os == .windows) {
752 const path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);
753 return self.createFileW(&path_w, flags);
754 }
755 const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0;
756 const os_flags = O_LARGEFILE | os.O_CREAT | os.O_CLOEXEC |
757 (if (flags.truncate) @as(u32, os.O_TRUNC) else 0) |
758 (if (flags.read) @as(u32, os.O_RDWR) else os.O_WRONLY) |
759 (if (flags.exclusive) @as(u32, os.O_EXCL) else 0);
760 const fd = try os.openatC(self.fd, sub_path_c, os_flags, flags.mode);
761 return File{ .handle = fd };
762 }
763
764 /// Same as `createFile` but the path parameter is WTF-16 encoded.
765 pub fn createFileW(self: Dir, sub_path_w: [*:0]const u16, flags: File.CreateFlags) File.OpenError!File {
766 const w = os.windows;
767 const access_mask = w.SYNCHRONIZE | w.GENERIC_WRITE |
768 (if (flags.read) @as(u32, w.GENERIC_READ) else 0);
769 const creation = if (flags.exclusive)
770 @as(u32, w.FILE_CREATE)
771 else if (flags.truncate)
772 @as(u32, w.FILE_OVERWRITE_IF)
773 else
774 @as(u32, w.FILE_OPEN_IF);
775 return self.openFileWindows(sub_path_w, access_mask, creation);
776 }
777
778 /// Deprecated; call `openFile` directly.
779 pub fn openRead(self: Dir, sub_path: []const u8) File.OpenError!File {
780 return self.openFile(sub_path, .{});
781 }
782
783 /// Deprecated; call `openFileC` directly.
784 pub fn openReadC(self: Dir, sub_path: [*:0]const u8) File.OpenError!File {
785 return self.openFileC(sub_path, .{});
786 }
787
788 /// Deprecated; call `openFileW` directly.
789 pub fn openReadW(self: Dir, sub_path: [*:0]const u16) File.OpenError!File {
790 return self.openFileW(sub_path, .{});
791 }
792
793 pub fn openFileWindows(
794 self: Dir,
795 sub_path_w: [*:0]const u16,
796 access_mask: os.windows.ACCESS_MASK,
797 creation: os.windows.ULONG,
798 ) File.OpenError!File {
724 const w = os.windows;799 const w = os.windows;
725800
726 var result = File{ .handle = undefined };801 var result = File{ .handle = undefined };
...@@ -750,13 +825,13 @@ pub const Dir = struct {...@@ -750,13 +825,13 @@ pub const Dir = struct {
750 var io: w.IO_STATUS_BLOCK = undefined;825 var io: w.IO_STATUS_BLOCK = undefined;
751 const rc = w.ntdll.NtCreateFile(826 const rc = w.ntdll.NtCreateFile(
752 &result.handle,827 &result.handle,
753 w.GENERIC_READ | w.SYNCHRONIZE,828 access_mask,
754 &attr,829 &attr,
755 &io,830 &io,
756 null,831 null,
757 w.FILE_ATTRIBUTE_NORMAL,832 w.FILE_ATTRIBUTE_NORMAL,
758 w.FILE_SHARE_READ,833 w.FILE_SHARE_WRITE | w.FILE_SHARE_READ | w.FILE_SHARE_DELETE,
759 w.FILE_OPEN,834 creation,
760 w.FILE_NON_DIRECTORY_FILE | w.FILE_SYNCHRONOUS_IO_NONALERT,835 w.FILE_NON_DIRECTORY_FILE | w.FILE_SYNCHRONOUS_IO_NONALERT,
761 null,836 null,
762 0,837 0,
lib/std/fs/file.zig+55-73
...@@ -25,105 +25,87 @@ pub const File = struct {...@@ -25,105 +25,87 @@ pub const File = struct {
2525
26 pub const OpenError = windows.CreateFileError || os.OpenError;26 pub const OpenError = windows.CreateFileError || os.OpenError;
2727
28 /// Deprecated; call `std.fs.Dir.openRead` directly.28 /// TODO https://github.com/ziglang/zig/issues/3802
29 pub const OpenFlags = struct {
30 read: bool = true,
31 write: bool = false,
32 };
33
34 /// TODO https://github.com/ziglang/zig/issues/3802
35 pub const CreateFlags = struct {
36 /// Whether the file will be created with read access.
37 read: bool = false,
38
39 /// If the file already exists, and is a regular file, and the access
40 /// mode allows writing, it will be truncated to length 0.
41 truncate: bool = true,
42
43 /// Ensures that this open call creates the file, otherwise causes
44 /// `error.FileAlreadyExists` to be returned.
45 exclusive: bool = false,
46
47 /// For POSIX systems this is the file system mode the file will
48 /// be created with.
49 mode: Mode = default_mode,
50 };
51
52 /// Deprecated; call `std.fs.Dir.openFile` directly.
29 pub fn openRead(path: []const u8) OpenError!File {53 pub fn openRead(path: []const u8) OpenError!File {
30 return std.fs.Dir.cwd().openRead(path);54 return std.fs.Dir.cwd().openFile(path, .{});
31 }55 }
3256
33 /// Deprecated; call `std.fs.Dir.openReadC` directly.57 /// Deprecated; call `std.fs.Dir.openFileC` directly.
34 pub fn openReadC(path_c: [*:0]const u8) OpenError!File {58 pub fn openReadC(path_c: [*:0]const u8) OpenError!File {
35 return std.fs.Dir.cwd().openReadC(path_c);59 return std.fs.Dir.cwd().openFileC(path_c, .{});
36 }60 }
3761
38 /// Deprecated; call `std.fs.Dir.openReadW` directly.62 /// Deprecated; call `std.fs.Dir.openFileW` directly.
39 pub fn openReadW(path_w: [*]const u16) OpenError!File {63 pub fn openReadW(path_w: [*]const u16) OpenError!File {
40 return std.fs.Dir.cwd().openReadW(path_w);64 return std.fs.Dir.cwd().openFileW(path_w, .{});
41 }65 }
4266
43 /// Calls `openWriteMode` with `default_mode` for the mode.67 /// Deprecated; call `std.fs.Dir.createFile` directly.
44 /// TODO: deprecate this and move it to `std.fs.Dir`.
45 pub fn openWrite(path: []const u8) OpenError!File {68 pub fn openWrite(path: []const u8) OpenError!File {
46 return openWriteMode(path, default_mode);69 return std.fs.Dir.cwd().createFile(path, .{});
47 }70 }
4871
49 /// If the path does not exist it will be created.72 /// Deprecated; call `std.fs.Dir.createFile` directly.
50 /// If a file already exists in the destination it will be truncated.
51 /// Call close to clean up.
52 /// TODO: deprecate this and move it to `std.fs.Dir`.
53 pub fn openWriteMode(path: []const u8, file_mode: Mode) OpenError!File {73 pub fn openWriteMode(path: []const u8, file_mode: Mode) OpenError!File {
54 if (builtin.os == .windows) {74 return std.fs.Dir.cwd().createFile(path, .{ .mode = file_mode });
55 const path_w = try windows.sliceToPrefixedFileW(path);
56 return openWriteModeW(&path_w, file_mode);
57 }
58 const path_c = try os.toPosixPath(path);
59 return openWriteModeC(&path_c, file_mode);
60 }75 }
6176
62 /// Same as `openWriteMode` except `path` is null-terminated.77 /// Deprecated; call `std.fs.Dir.createFileC` directly.
63 /// TODO: deprecate this and move it to `std.fs.Dir`.78 pub fn openWriteModeC(path_c: [*:0]const u8, file_mode: Mode) OpenError!File {
64 pub fn openWriteModeC(path: [*:0]const u8, file_mode: Mode) OpenError!File {79 return std.fs.Dir.cwd().createFileC(path_c, .{ .mode = file_mode });
65 if (builtin.os == .windows) {
66 const path_w = try windows.cStrToPrefixedFileW(path);
67 return openWriteModeW(&path_w, file_mode);
68 }
69 const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0;
70 const flags = O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_TRUNC;
71 const fd = try os.openC(path, flags, file_mode);
72 return openHandle(fd);
73 }80 }
7481
75 /// Same as `openWriteMode` except `path` is null-terminated and UTF16LE encoded82 /// Deprecated; call `std.fs.Dir.createFileW` directly.
76 /// TODO: deprecate this and move it to `std.fs.Dir`.
77 pub fn openWriteModeW(path_w: [*:0]const u16, file_mode: Mode) OpenError!File {83 pub fn openWriteModeW(path_w: [*:0]const u16, file_mode: Mode) OpenError!File {
78 const handle = try windows.CreateFileW(84 return std.fs.Dir.cwd().createFileW(path_w, .{ .mode = file_mode });
79 path_w,
80 windows.GENERIC_WRITE,
81 windows.FILE_SHARE_WRITE | windows.FILE_SHARE_READ | windows.FILE_SHARE_DELETE,
82 null,
83 windows.CREATE_ALWAYS,
84 windows.FILE_ATTRIBUTE_NORMAL,
85 null,
86 );
87 return openHandle(handle);
88 }85 }
8986
90 /// If the path does not exist it will be created.87 /// Deprecated; call `std.fs.Dir.createFile` directly.
91 /// If a file already exists in the destination this returns OpenError.PathAlreadyExists
92 /// Call close to clean up.
93 /// TODO: deprecate this and move it to `std.fs.Dir`.
94 pub fn openWriteNoClobber(path: []const u8, file_mode: Mode) OpenError!File {88 pub fn openWriteNoClobber(path: []const u8, file_mode: Mode) OpenError!File {
95 if (builtin.os == .windows) {89 return std.fs.Dir.cwd().createFile(path, .{
96 const path_w = try windows.sliceToPrefixedFileW(path);90 .mode = file_mode,
97 return openWriteNoClobberW(&path_w, file_mode);91 .exclusive = true,
98 }92 });
99 const path_c = try os.toPosixPath(path);
100 return openWriteNoClobberC(&path_c, file_mode);
101 }93 }
10294
103 /// TODO: deprecate this and move it to `std.fs.Dir`.95 /// Deprecated; call `std.fs.Dir.createFileC` directly.
104 pub fn openWriteNoClobberC(path: [*:0]const u8, file_mode: Mode) OpenError!File {96 pub fn openWriteNoClobberC(path_c: [*:0]const u8, file_mode: Mode) OpenError!File {
105 if (builtin.os == .windows) {97 return std.fs.Dir.cwd().createFileC(path_c, .{
106 const path_w = try windows.cStrToPrefixedFileW(path);98 .mode = file_mode,
107 return openWriteNoClobberW(&path_w, file_mode);99 .exclusive = true,
108 }100 });
109 const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0;
110 const flags = O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_EXCL;
111 const fd = try os.openC(path, flags, file_mode);
112 return openHandle(fd);
113 }101 }
114102
115 /// TODO: deprecate this and move it to `std.fs.Dir`.103 /// Deprecated; call `std.fs.Dir.createFileW` directly.
116 pub fn openWriteNoClobberW(path_w: [*:0]const u16, file_mode: Mode) OpenError!File {104 pub fn openWriteNoClobberW(path_w: [*:0]const u16, file_mode: Mode) OpenError!File {
117 const handle = try windows.CreateFileW(105 return std.fs.Dir.cwd().createFileW(path_w, .{
118 path_w,106 .mode = file_mode,
119 windows.GENERIC_WRITE,107 .exclusive = true,
120 windows.FILE_SHARE_WRITE | windows.FILE_SHARE_READ | windows.FILE_SHARE_DELETE,108 });
121 null,
122 windows.CREATE_NEW,
123 windows.FILE_ATTRIBUTE_NORMAL,
124 null,
125 );
126 return openHandle(handle);
127 }109 }
128110
129 pub fn openHandle(handle: os.fd_t) File {111 pub fn openHandle(handle: os.fd_t) File {