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.master
parent
85e1e3b95f
commit
d039fed831
103
lib/std/fs.zig
103
lib/std/fs.zig
|
@ -698,29 +698,104 @@ pub const Dir = struct {
|
|||
self.* = undefined;
|
||||
}
|
||||
|
||||
/// Call `File.close` on the result when done.
|
||||
pub fn openRead(self: Dir, sub_path: []const u8) File.OpenError!File {
|
||||
/// Opens a file for reading or writing, without attempting to create a new file.
|
||||
/// Call `File.close` to release the resource.
|
||||
pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File {
|
||||
if (builtin.os == .windows) {
|
||||
const path_w = try os.windows.sliceToPrefixedFileW(sub_path);
|
||||
return self.openReadW(&path_w);
|
||||
return self.openFileW(&path_w, flags);
|
||||
}
|
||||
const path_c = try os.toPosixPath(sub_path);
|
||||
return self.openReadC(&path_c);
|
||||
return self.openFileC(&path_c, flags);
|
||||
}
|
||||
|
||||
/// Call `File.close` on the result when done.
|
||||
pub fn openReadC(self: Dir, sub_path: [*:0]const u8) File.OpenError!File {
|
||||
/// Same as `openFile` but the path parameter is null-terminated.
|
||||
pub fn openFileC(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) File.OpenError!File {
|
||||
if (builtin.os == .windows) {
|
||||
const path_w = try os.windows.cStrToPrefixedFileW(sub_path);
|
||||
return self.openReadW(&path_w);
|
||||
return self.openFileW(&path_w, flags);
|
||||
}
|
||||
const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0;
|
||||
const flags = O_LARGEFILE | os.O_RDONLY | os.O_CLOEXEC;
|
||||
const fd = try os.openatC(self.fd, sub_path, flags, 0);
|
||||
return File.openHandle(fd);
|
||||
const os_flags = O_LARGEFILE | os.O_CLOEXEC | if (flags.write and flags.read)
|
||||
@as(u32, os.O_RDWR)
|
||||
else if (flags.write)
|
||||
@as(u32, os.O_WRONLY)
|
||||
else
|
||||
@as(u32, os.O_RDONLY);
|
||||
const fd = try os.openatC(self.fd, sub_path, os_flags, 0);
|
||||
return File{ .handle = fd };
|
||||
}
|
||||
|
||||
pub fn openReadW(self: Dir, sub_path_w: [*:0]const u16) File.OpenError!File {
|
||||
/// Same as `openFile` but the path parameter is WTF-16 encoded.
|
||||
pub fn openFileW(self: Dir, sub_path_w: [*:0]const u16, flags: File.OpenFlags) File.OpenError!File {
|
||||
const w = os.windows;
|
||||
const access_mask = w.SYNCHRONIZE |
|
||||
(if (flags.read) @as(u32, w.GENERIC_READ) else 0) |
|
||||
(if (flags.write) @as(u32, w.GENERIC_WRITE) else 0);
|
||||
return self.openFileWindows(sub_path_w, access_mask, w.FILE_OPEN);
|
||||
}
|
||||
|
||||
/// Creates, opens, or overwrites a file with write access.
|
||||
/// Call `File.close` on the result when done.
|
||||
pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File {
|
||||
if (builtin.os == .windows) {
|
||||
const path_w = try os.windows.sliceToPrefixedFileW(sub_path);
|
||||
return self.createFileW(&path_w, flags);
|
||||
}
|
||||
const path_c = try os.toPosixPath(sub_path);
|
||||
return self.createFileC(&path_c, flags);
|
||||
}
|
||||
|
||||
/// Same as `createFile` but the path parameter is null-terminated.
|
||||
pub fn createFileC(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags) File.OpenError!File {
|
||||
if (builtin.os == .windows) {
|
||||
const path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);
|
||||
return self.createFileW(&path_w, flags);
|
||||
}
|
||||
const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0;
|
||||
const os_flags = O_LARGEFILE | os.O_CREAT | os.O_CLOEXEC |
|
||||
(if (flags.truncate) @as(u32, os.O_TRUNC) else 0) |
|
||||
(if (flags.read) @as(u32, os.O_RDWR) else os.O_WRONLY) |
|
||||
(if (flags.exclusive) @as(u32, os.O_EXCL) else 0);
|
||||
const fd = try os.openatC(self.fd, sub_path_c, os_flags, flags.mode);
|
||||
return File{ .handle = fd };
|
||||
}
|
||||
|
||||
/// Same as `createFile` but the path parameter is WTF-16 encoded.
|
||||
pub fn createFileW(self: Dir, sub_path_w: [*:0]const u16, flags: File.CreateFlags) File.OpenError!File {
|
||||
const w = os.windows;
|
||||
const access_mask = w.SYNCHRONIZE | w.GENERIC_WRITE |
|
||||
(if (flags.read) @as(u32, w.GENERIC_READ) else 0);
|
||||
const creation = if (flags.exclusive)
|
||||
@as(u32, w.FILE_CREATE)
|
||||
else if (flags.truncate)
|
||||
@as(u32, w.FILE_OVERWRITE_IF)
|
||||
else
|
||||
@as(u32, w.FILE_OPEN_IF);
|
||||
return self.openFileWindows(sub_path_w, access_mask, creation);
|
||||
}
|
||||
|
||||
/// Deprecated; call `openFile` directly.
|
||||
pub fn openRead(self: Dir, sub_path: []const u8) File.OpenError!File {
|
||||
return self.openFile(sub_path, .{});
|
||||
}
|
||||
|
||||
/// Deprecated; call `openFileC` directly.
|
||||
pub fn openReadC(self: Dir, sub_path: [*:0]const u8) File.OpenError!File {
|
||||
return self.openFileC(sub_path, .{});
|
||||
}
|
||||
|
||||
/// Deprecated; call `openFileW` directly.
|
||||
pub fn openReadW(self: Dir, sub_path: [*:0]const u16) File.OpenError!File {
|
||||
return self.openFileW(sub_path, .{});
|
||||
}
|
||||
|
||||
pub fn openFileWindows(
|
||||
self: Dir,
|
||||
sub_path_w: [*:0]const u16,
|
||||
access_mask: os.windows.ACCESS_MASK,
|
||||
creation: os.windows.ULONG,
|
||||
) File.OpenError!File {
|
||||
const w = os.windows;
|
||||
|
||||
var result = File{ .handle = undefined };
|
||||
|
@ -750,13 +825,13 @@ pub const Dir = struct {
|
|||
var io: w.IO_STATUS_BLOCK = undefined;
|
||||
const rc = w.ntdll.NtCreateFile(
|
||||
&result.handle,
|
||||
w.GENERIC_READ | w.SYNCHRONIZE,
|
||||
access_mask,
|
||||
&attr,
|
||||
&io,
|
||||
null,
|
||||
w.FILE_ATTRIBUTE_NORMAL,
|
||||
w.FILE_SHARE_READ,
|
||||
w.FILE_OPEN,
|
||||
w.FILE_SHARE_WRITE | w.FILE_SHARE_READ | w.FILE_SHARE_DELETE,
|
||||
creation,
|
||||
w.FILE_NON_DIRECTORY_FILE | w.FILE_SYNCHRONOUS_IO_NONALERT,
|
||||
null,
|
||||
0,
|
||||
|
|
|
@ -25,105 +25,87 @@ pub const File = struct {
|
|||
|
||||
pub const OpenError = windows.CreateFileError || os.OpenError;
|
||||
|
||||
/// Deprecated; call `std.fs.Dir.openRead` directly.
|
||||
/// TODO https://github.com/ziglang/zig/issues/3802
|
||||
pub const OpenFlags = struct {
|
||||
read: bool = true,
|
||||
write: bool = false,
|
||||
};
|
||||
|
||||
/// TODO https://github.com/ziglang/zig/issues/3802
|
||||
pub const CreateFlags = struct {
|
||||
/// Whether the file will be created with read access.
|
||||
read: bool = false,
|
||||
|
||||
/// If the file already exists, and is a regular file, and the access
|
||||
/// mode allows writing, it will be truncated to length 0.
|
||||
truncate: bool = true,
|
||||
|
||||
/// Ensures that this open call creates the file, otherwise causes
|
||||
/// `error.FileAlreadyExists` to be returned.
|
||||
exclusive: bool = false,
|
||||
|
||||
/// For POSIX systems this is the file system mode the file will
|
||||
/// be created with.
|
||||
mode: Mode = default_mode,
|
||||
};
|
||||
|
||||
/// Deprecated; call `std.fs.Dir.openFile` directly.
|
||||
pub fn openRead(path: []const u8) OpenError!File {
|
||||
return std.fs.Dir.cwd().openRead(path);
|
||||
return std.fs.Dir.cwd().openFile(path, .{});
|
||||
}
|
||||
|
||||
/// Deprecated; call `std.fs.Dir.openReadC` directly.
|
||||
/// Deprecated; call `std.fs.Dir.openFileC` directly.
|
||||
pub fn openReadC(path_c: [*:0]const u8) OpenError!File {
|
||||
return std.fs.Dir.cwd().openReadC(path_c);
|
||||
return std.fs.Dir.cwd().openFileC(path_c, .{});
|
||||
}
|
||||
|
||||
/// Deprecated; call `std.fs.Dir.openReadW` directly.
|
||||
/// Deprecated; call `std.fs.Dir.openFileW` directly.
|
||||
pub fn openReadW(path_w: [*]const u16) OpenError!File {
|
||||
return std.fs.Dir.cwd().openReadW(path_w);
|
||||
return std.fs.Dir.cwd().openFileW(path_w, .{});
|
||||
}
|
||||
|
||||
/// Calls `openWriteMode` with `default_mode` for the mode.
|
||||
/// TODO: deprecate this and move it to `std.fs.Dir`.
|
||||
/// Deprecated; call `std.fs.Dir.createFile` directly.
|
||||
pub fn openWrite(path: []const u8) OpenError!File {
|
||||
return openWriteMode(path, default_mode);
|
||||
return std.fs.Dir.cwd().createFile(path, .{});
|
||||
}
|
||||
|
||||
/// If the path does not exist it will be created.
|
||||
/// If a file already exists in the destination it will be truncated.
|
||||
/// Call close to clean up.
|
||||
/// TODO: deprecate this and move it to `std.fs.Dir`.
|
||||
/// Deprecated; call `std.fs.Dir.createFile` directly.
|
||||
pub fn openWriteMode(path: []const u8, file_mode: Mode) OpenError!File {
|
||||
if (builtin.os == .windows) {
|
||||
const path_w = try windows.sliceToPrefixedFileW(path);
|
||||
return openWriteModeW(&path_w, file_mode);
|
||||
}
|
||||
const path_c = try os.toPosixPath(path);
|
||||
return openWriteModeC(&path_c, file_mode);
|
||||
return std.fs.Dir.cwd().createFile(path, .{ .mode = file_mode });
|
||||
}
|
||||
|
||||
/// Same as `openWriteMode` except `path` is null-terminated.
|
||||
/// TODO: deprecate this and move it to `std.fs.Dir`.
|
||||
pub fn openWriteModeC(path: [*:0]const u8, file_mode: Mode) OpenError!File {
|
||||
if (builtin.os == .windows) {
|
||||
const path_w = try windows.cStrToPrefixedFileW(path);
|
||||
return openWriteModeW(&path_w, file_mode);
|
||||
}
|
||||
const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0;
|
||||
const flags = O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_TRUNC;
|
||||
const fd = try os.openC(path, flags, file_mode);
|
||||
return openHandle(fd);
|
||||
/// Deprecated; call `std.fs.Dir.createFileC` directly.
|
||||
pub fn openWriteModeC(path_c: [*:0]const u8, file_mode: Mode) OpenError!File {
|
||||
return std.fs.Dir.cwd().createFileC(path_c, .{ .mode = file_mode });
|
||||
}
|
||||
|
||||
/// Same as `openWriteMode` except `path` is null-terminated and UTF16LE encoded
|
||||
/// TODO: deprecate this and move it to `std.fs.Dir`.
|
||||
/// Deprecated; call `std.fs.Dir.createFileW` directly.
|
||||
pub fn openWriteModeW(path_w: [*:0]const u16, file_mode: Mode) OpenError!File {
|
||||
const handle = try windows.CreateFileW(
|
||||
path_w,
|
||||
windows.GENERIC_WRITE,
|
||||
windows.FILE_SHARE_WRITE | windows.FILE_SHARE_READ | windows.FILE_SHARE_DELETE,
|
||||
null,
|
||||
windows.CREATE_ALWAYS,
|
||||
windows.FILE_ATTRIBUTE_NORMAL,
|
||||
null,
|
||||
);
|
||||
return openHandle(handle);
|
||||
return std.fs.Dir.cwd().createFileW(path_w, .{ .mode = file_mode });
|
||||
}
|
||||
|
||||
/// If the path does not exist it will be created.
|
||||
/// If a file already exists in the destination this returns OpenError.PathAlreadyExists
|
||||
/// Call close to clean up.
|
||||
/// TODO: deprecate this and move it to `std.fs.Dir`.
|
||||
/// Deprecated; call `std.fs.Dir.createFile` directly.
|
||||
pub fn openWriteNoClobber(path: []const u8, file_mode: Mode) OpenError!File {
|
||||
if (builtin.os == .windows) {
|
||||
const path_w = try windows.sliceToPrefixedFileW(path);
|
||||
return openWriteNoClobberW(&path_w, file_mode);
|
||||
}
|
||||
const path_c = try os.toPosixPath(path);
|
||||
return openWriteNoClobberC(&path_c, file_mode);
|
||||
return std.fs.Dir.cwd().createFile(path, .{
|
||||
.mode = file_mode,
|
||||
.exclusive = true,
|
||||
});
|
||||
}
|
||||
|
||||
/// TODO: deprecate this and move it to `std.fs.Dir`.
|
||||
pub fn openWriteNoClobberC(path: [*:0]const u8, file_mode: Mode) OpenError!File {
|
||||
if (builtin.os == .windows) {
|
||||
const path_w = try windows.cStrToPrefixedFileW(path);
|
||||
return openWriteNoClobberW(&path_w, file_mode);
|
||||
}
|
||||
const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0;
|
||||
const flags = O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_EXCL;
|
||||
const fd = try os.openC(path, flags, file_mode);
|
||||
return openHandle(fd);
|
||||
/// Deprecated; call `std.fs.Dir.createFileC` directly.
|
||||
pub fn openWriteNoClobberC(path_c: [*:0]const u8, file_mode: Mode) OpenError!File {
|
||||
return std.fs.Dir.cwd().createFileC(path_c, .{
|
||||
.mode = file_mode,
|
||||
.exclusive = true,
|
||||
});
|
||||
}
|
||||
|
||||
/// TODO: deprecate this and move it to `std.fs.Dir`.
|
||||
/// Deprecated; call `std.fs.Dir.createFileW` directly.
|
||||
pub fn openWriteNoClobberW(path_w: [*:0]const u16, file_mode: Mode) OpenError!File {
|
||||
const handle = try windows.CreateFileW(
|
||||
path_w,
|
||||
windows.GENERIC_WRITE,
|
||||
windows.FILE_SHARE_WRITE | windows.FILE_SHARE_READ | windows.FILE_SHARE_DELETE,
|
||||
null,
|
||||
windows.CREATE_NEW,
|
||||
windows.FILE_ATTRIBUTE_NORMAL,
|
||||
null,
|
||||
);
|
||||
return openHandle(handle);
|
||||
return std.fs.Dir.cwd().createFileW(path_w, .{
|
||||
.mode = file_mode,
|
||||
.exclusive = true,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn openHandle(handle: os.fd_t) File {
|
||||
|
|
Loading…
Reference in New Issue