Commit 0e9280ef1a
Changed files (9)
lib/std/fs/Dir.zig
@@ -2630,74 +2630,6 @@ pub const CopyFileOptions = struct {
override_mode: ?File.Mode = null,
};
-pub const PrevStatus = enum {
- stale,
- fresh,
-};
-
-/// Check the file size, mtime, and mode of `source_path` and `dest_path`. If they are equal, does nothing.
-/// Otherwise, atomically copies `source_path` to `dest_path`. The destination file gains the mtime,
-/// atime, and mode of the source file so that the next call to `updateFile` will not need a copy.
-/// Returns the previous status of the file before updating.
-/// If any of the directories do not exist for dest_path, they are created.
-/// On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
-/// On WASI, both paths should be encoded as valid UTF-8.
-/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding.
-pub fn updateFile(
- source_dir: Dir,
- source_path: []const u8,
- dest_dir: Dir,
- dest_path: []const u8,
- options: CopyFileOptions,
-) !PrevStatus {
- var src_file = try source_dir.openFile(source_path, .{});
- defer src_file.close();
-
- const src_stat = try src_file.stat();
- const actual_mode = options.override_mode orelse src_stat.mode;
- check_dest_stat: {
- const dest_stat = blk: {
- var dest_file = dest_dir.openFile(dest_path, .{}) catch |err| switch (err) {
- error.FileNotFound => break :check_dest_stat,
- else => |e| return e,
- };
- defer dest_file.close();
-
- break :blk try dest_file.stat();
- };
-
- if (src_stat.size == dest_stat.size and
- src_stat.mtime == dest_stat.mtime and
- actual_mode == dest_stat.mode)
- {
- return PrevStatus.fresh;
- }
- }
-
- if (fs.path.dirname(dest_path)) |dirname| {
- try dest_dir.makePath(dirname);
- }
-
- var buffer: [1000]u8 = undefined; // Used only when direct fd-to-fd is not available.
- var atomic_file = try dest_dir.atomicFile(dest_path, .{
- .mode = actual_mode,
- .write_buffer = &buffer,
- });
- defer atomic_file.deinit();
-
- var src_reader: File.Reader = .initSize(src_file, &.{}, src_stat.size);
- const dest_writer = &atomic_file.file_writer.interface;
-
- _ = dest_writer.sendFileAll(&src_reader, .unlimited) catch |err| switch (err) {
- error.ReadFailed => return src_reader.err.?,
- error.WriteFailed => return atomic_file.file_writer.err.?,
- };
- try atomic_file.flush();
- try atomic_file.file_writer.file.updateTimes(src_stat.atime, src_stat.mtime);
- try atomic_file.renameIntoPlace();
- return .stale;
-}
-
pub const CopyFileError = File.OpenError || File.StatError ||
AtomicFile.InitError || AtomicFile.FinishError ||
File.ReadError || File.WriteError;
lib/std/fs/File.zig
@@ -1144,13 +1144,7 @@ pub const Reader = struct {
fn stream(io_reader: *std.Io.Reader, w: *std.Io.Writer, limit: std.Io.Limit) std.Io.Reader.StreamError!usize {
const r: *Reader = @alignCast(@fieldParentPtr("interface", io_reader));
switch (r.mode) {
- .positional, .streaming => return w.sendFile(r, limit) catch |write_err| switch (write_err) {
- error.Unimplemented => {
- r.mode = r.mode.toReading();
- return 0;
- },
- else => |e| return e,
- },
+ .positional, .streaming => @panic("TODO"),
.positional_reading => {
const dest = limit.slice(try w.writableSliceGreedy(1));
var data: [1][]u8 = .{dest};
lib/std/Io/net/HostName.zig
@@ -629,3 +629,28 @@ pub const ResolvConf = struct {
@panic("TODO");
}
};
+
+test ResolvConf {
+ const input =
+ \\# Generated by resolvconf
+ \\nameserver 1.0.0.1
+ \\nameserver 1.1.1.1
+ \\nameserver fe80::e0e:76ff:fed4:cf22%eno1
+ \\options edns0
+ \\
+ ;
+ var reader: Io.Reader = .fixed(input);
+
+ var rc: ResolvConf = .{
+ .nameservers_buffer = undefined,
+ .nameservers_len = 0,
+ .search_buffer = undefined,
+ .search_len = 0,
+ .ndots = 1,
+ .timeout = 5,
+ .attempts = 2,
+ };
+
+ try rc.parse(&reader);
+ try std.testing.expect(false);
+}
lib/std/Io/Dir.zig
@@ -0,0 +1,113 @@
+const Dir = @This();
+
+const std = @import("../std.zig");
+const Io = std.Io;
+const File = Io.File;
+
+handle: Handle,
+
+pub fn cwd() Dir {
+ return .{ .handle = std.fs.cwd().fd };
+}
+
+pub const Handle = std.posix.fd_t;
+
+pub fn openFile(dir: Dir, io: Io, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File {
+ return io.vtable.fileOpen(io.userdata, dir, sub_path, flags);
+}
+
+pub fn createFile(dir: Dir, io: Io, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File {
+ return io.vtable.createFile(io.userdata, dir, sub_path, flags);
+}
+
+pub const WriteFileOptions = struct {
+ /// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
+ /// On WASI, `sub_path` should be encoded as valid UTF-8.
+ /// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding.
+ sub_path: []const u8,
+ data: []const u8,
+ flags: File.CreateFlags = .{},
+};
+
+pub const WriteFileError = File.WriteError || File.OpenError || Io.Cancelable;
+
+/// Writes content to the file system, using the file creation flags provided.
+pub fn writeFile(dir: Dir, io: Io, options: WriteFileOptions) WriteFileError!void {
+ var file = try dir.createFile(io, options.sub_path, options.flags);
+ defer file.close(io);
+ try file.writeAll(io, options.data);
+}
+
+pub const PrevStatus = enum {
+ stale,
+ fresh,
+};
+
+pub const UpdateFileError = File.OpenError;
+
+/// Check the file size, mtime, and mode of `source_path` and `dest_path`. If
+/// they are equal, does nothing. Otherwise, atomically copies `source_path` to
+/// `dest_path`. The destination file gains the mtime, atime, and mode of the
+/// source file so that the next call to `updateFile` will not need a copy.
+///
+/// Returns the previous status of the file before updating.
+///
+/// * On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
+/// * On WASI, both paths should be encoded as valid UTF-8.
+/// * On other platforms, both paths are an opaque sequence of bytes with no particular encoding.
+pub fn updateFile(
+ source_dir: Dir,
+ io: Io,
+ source_path: []const u8,
+ dest_dir: Dir,
+ /// If directories in this path do not exist, they are created.
+ dest_path: []const u8,
+ options: std.fs.Dir.CopyFileOptions,
+) !PrevStatus {
+ var src_file = try source_dir.openFile(io, source_path, .{});
+ defer src_file.close();
+
+ const src_stat = try src_file.stat(io);
+ const actual_mode = options.override_mode orelse src_stat.mode;
+ check_dest_stat: {
+ const dest_stat = blk: {
+ var dest_file = dest_dir.openFile(io, dest_path, .{}) catch |err| switch (err) {
+ error.FileNotFound => break :check_dest_stat,
+ else => |e| return e,
+ };
+ defer dest_file.close(io);
+
+ break :blk try dest_file.stat(io);
+ };
+
+ if (src_stat.size == dest_stat.size and
+ src_stat.mtime == dest_stat.mtime and
+ actual_mode == dest_stat.mode)
+ {
+ return .fresh;
+ }
+ }
+
+ if (std.fs.path.dirname(dest_path)) |dirname| {
+ try dest_dir.makePath(io, dirname);
+ }
+
+ var buffer: [1000]u8 = undefined; // Used only when direct fd-to-fd is not available.
+ var atomic_file = try dest_dir.atomicFile(io, dest_path, .{
+ .mode = actual_mode,
+ .write_buffer = &buffer,
+ });
+ defer atomic_file.deinit();
+
+ var src_reader: File.Reader = .initSize(io, src_file, &.{}, src_stat.size);
+ const dest_writer = &atomic_file.file_writer.interface;
+
+ _ = dest_writer.sendFileAll(&src_reader, .unlimited) catch |err| switch (err) {
+ error.ReadFailed => return src_reader.err.?,
+ error.WriteFailed => return atomic_file.file_writer.err.?,
+ };
+ try atomic_file.flush();
+ try atomic_file.file_writer.file.updateTimes(src_stat.atime, src_stat.mtime);
+ try atomic_file.renameIntoPlace();
+ return .stale;
+}
lib/std/Io/File.zig
@@ -1,7 +1,9 @@
+const File = @This();
+
const builtin = @import("builtin");
+
const std = @import("../std.zig");
const Io = std.Io;
-const File = @This();
const assert = std.debug.assert;
handle: Handle,
lib/std/Io/net.zig
@@ -593,3 +593,7 @@ pub const InterfaceIndexError = error{
pub fn interfaceIndex(io: Io, name: []const u8) InterfaceIndexError!u32 {
return io.vtable.netInterfaceIndex(io.userdata, name);
}
+
+test {
+ _ = HostName;
+}
lib/std/fs.zig
@@ -107,13 +107,15 @@ pub fn updateFileAbsolute(
source_path: []const u8,
dest_path: []const u8,
args: Dir.CopyFileOptions,
-) !Dir.PrevStatus {
+) !std.Io.Dir.PrevStatus {
assert(path.isAbsolute(source_path));
assert(path.isAbsolute(dest_path));
const my_cwd = cwd();
return Dir.updateFile(my_cwd, source_path, my_cwd, dest_path, args);
}
+test updateFileAbsolute {}
+
/// Same as `Dir.copyFile`, except asserts that both `source_path` and `dest_path`
/// are absolute. See `Dir.copyFile` for a function that operates on both
/// absolute and relative paths.
@@ -131,6 +133,8 @@ pub fn copyFileAbsolute(
return Dir.copyFile(my_cwd, source_path, my_cwd, dest_path, args);
}
+test copyFileAbsolute {}
+
/// Create a new directory, based on an absolute path.
/// Asserts that the path is absolute. See `Dir.makeDir` for a function that operates
/// on both absolute and relative paths.
@@ -142,12 +146,16 @@ pub fn makeDirAbsolute(absolute_path: []const u8) !void {
return posix.mkdir(absolute_path, Dir.default_mode);
}
+test makeDirAbsolute {}
+
/// Same as `makeDirAbsolute` except the parameter is null-terminated.
pub fn makeDirAbsoluteZ(absolute_path_z: [*:0]const u8) !void {
assert(path.isAbsoluteZ(absolute_path_z));
return posix.mkdirZ(absolute_path_z, Dir.default_mode);
}
+test makeDirAbsoluteZ {}
+
/// Same as `makeDirAbsolute` except the parameter is a null-terminated WTF-16 LE-encoded string.
pub fn makeDirAbsoluteW(absolute_path_w: [*:0]const u16) !void {
assert(path.isAbsoluteWindowsW(absolute_path_w));
@@ -702,16 +710,10 @@ pub fn realpathAlloc(allocator: Allocator, pathname: []const u8) ![]u8 {
}
test {
- if (native_os != .wasi) {
- _ = &makeDirAbsolute;
- _ = &makeDirAbsoluteZ;
- _ = ©FileAbsolute;
- _ = &updateFileAbsolute;
- }
- _ = &AtomicFile;
- _ = &Dir;
- _ = &File;
- _ = &path;
+ _ = AtomicFile;
+ _ = Dir;
+ _ = File;
+ _ = path;
_ = @import("fs/test.zig");
_ = @import("fs/get_app_data_dir.zig");
}
lib/std/Io.zig
@@ -548,6 +548,7 @@ pub fn PollFiles(comptime StreamEnum: type) type {
}
test {
+ _ = net;
_ = Reader;
_ = Writer;
_ = tty;
@@ -688,42 +689,7 @@ pub const UnexpectedError = error{
Unexpected,
};
-pub const Dir = struct {
- handle: Handle,
-
- pub fn cwd() Dir {
- return .{ .handle = std.fs.cwd().fd };
- }
-
- pub const Handle = std.posix.fd_t;
-
- pub fn openFile(dir: Dir, io: Io, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File {
- return io.vtable.fileOpen(io.userdata, dir, sub_path, flags);
- }
-
- pub fn createFile(dir: Dir, io: Io, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File {
- return io.vtable.createFile(io.userdata, dir, sub_path, flags);
- }
-
- pub const WriteFileOptions = struct {
- /// On Windows, `sub_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
- /// On WASI, `sub_path` should be encoded as valid UTF-8.
- /// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding.
- sub_path: []const u8,
- data: []const u8,
- flags: File.CreateFlags = .{},
- };
-
- pub const WriteFileError = File.WriteError || File.OpenError || Cancelable;
-
- /// Writes content to the file system, using the file creation flags provided.
- pub fn writeFile(dir: Dir, io: Io, options: WriteFileOptions) WriteFileError!void {
- var file = try dir.createFile(io, options.sub_path, options.flags);
- defer file.close(io);
- try file.writeAll(io, options.data);
- }
-};
-
+pub const Dir = @import("Io/Dir.zig");
pub const File = @import("Io/File.zig");
pub const Timestamp = enum(i96) {
lib/std/posix.zig
@@ -939,7 +939,7 @@ pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize {
}
}
-pub const PReadError = std.Io.ReadPositionalError;
+pub const PReadError = std.Io.File.ReadPositionalError;
/// Number of bytes read is returned. Upon reading end-of-file, zero is returned.
///