mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
std.Io: implement dirMake
In the future, it might be nice to introduce a type for file system path names. This would be a way to avoid having InvalidFileName in the error set, since construction of such type could validate it above the interface.
This commit is contained in:
parent
e85df854aa
commit
eadfefa002
@ -155,8 +155,6 @@ pub const MakeError = error{
|
||||
NoSpaceLeft,
|
||||
NotDir,
|
||||
ReadOnlyFileSystem,
|
||||
/// WASI-only; file paths must be valid UTF-8.
|
||||
InvalidUtf8,
|
||||
/// Windows-only; file paths provided by the user must be valid WTF-8.
|
||||
/// https://simonsapin.github.io/wtf-8/
|
||||
InvalidWtf8,
|
||||
@ -164,6 +162,8 @@ pub const MakeError = error{
|
||||
NoDevice,
|
||||
/// On Windows, `\\server` or `\\server\share` was not found.
|
||||
NetworkNotFound,
|
||||
/// File system cannot encode the requested file name bytes.
|
||||
InvalidFileName,
|
||||
} || Io.Cancelable || Io.UnexpectedError;
|
||||
|
||||
/// Creates a single directory with a relative or absolute path.
|
||||
|
||||
@ -160,7 +160,11 @@ pub fn io(pool: *Pool) Io {
|
||||
.conditionWait = conditionWait,
|
||||
.conditionWake = conditionWake,
|
||||
|
||||
.dirMake = dirMake,
|
||||
.dirMake = switch (builtin.os.tag) {
|
||||
.windows => @panic("TODO"),
|
||||
.wasi => @panic("TODO"),
|
||||
else => dirMakePosix,
|
||||
},
|
||||
.dirStat = dirStat,
|
||||
.dirStatPath = dirStatPath,
|
||||
.fileStat = switch (builtin.os.tag) {
|
||||
@ -759,14 +763,35 @@ fn conditionWake(userdata: ?*anyopaque, cond: *Io.Condition, wake: Io.Condition.
|
||||
}
|
||||
}
|
||||
|
||||
fn dirMake(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void {
|
||||
fn dirMakePosix(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void {
|
||||
const pool: *Pool = @ptrCast(@alignCast(userdata));
|
||||
try pool.checkCancel();
|
||||
|
||||
_ = dir;
|
||||
_ = sub_path;
|
||||
_ = mode;
|
||||
@panic("TODO");
|
||||
var path_buffer: [posix.PATH_MAX]u8 = undefined;
|
||||
const sub_path_posix = try toPosixPath(sub_path, &path_buffer);
|
||||
while (true) {
|
||||
try pool.checkCancel();
|
||||
switch (posix.errno(posix.system.mkdirat(dir.handle, sub_path_posix, mode))) {
|
||||
.SUCCESS => return,
|
||||
.INTR => continue,
|
||||
.ACCES => return error.AccessDenied,
|
||||
.BADF => |err| return errnoBug(err),
|
||||
.PERM => return error.PermissionDenied,
|
||||
.DQUOT => return error.DiskQuota,
|
||||
.EXIST => return error.PathAlreadyExists,
|
||||
.FAULT => |err| return errnoBug(err),
|
||||
.LOOP => return error.SymLinkLoop,
|
||||
.MLINK => return error.LinkQuotaExceeded,
|
||||
.NAMETOOLONG => return error.NameTooLong,
|
||||
.NOENT => return error.FileNotFound,
|
||||
.NOMEM => return error.SystemResources,
|
||||
.NOSPC => return error.NoSpaceLeft,
|
||||
.NOTDIR => return error.NotDir,
|
||||
.ROFS => return error.ReadOnlyFileSystem,
|
||||
// dragonfly: when dir_fd is unlinked from filesystem
|
||||
.NOTCONN => return error.FileNotFound,
|
||||
.ILSEQ => return error.InvalidFileName,
|
||||
else => |err| return posix.unexpectedErrno(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn dirStat(userdata: ?*anyopaque, dir: Io.Dir) Io.Dir.StatError!Io.Dir.Stat {
|
||||
@ -2267,3 +2292,12 @@ fn timestampToPosix(nanoseconds: i96) std.posix.timespec {
|
||||
.nsec = @intCast(@mod(nanoseconds, std.time.ns_per_s)),
|
||||
};
|
||||
}
|
||||
|
||||
fn toPosixPath(file_path: []const u8, buffer: *[posix.PATH_MAX]u8) error{ NameTooLong, InvalidFileName }![:0]u8 {
|
||||
if (std.mem.containsAtLeastScalar2(u8, file_path, 0, 1)) return error.InvalidFileName;
|
||||
// >= rather than > to make room for the null byte
|
||||
if (file_path.len >= buffer.len) return error.NameTooLong;
|
||||
@memcpy(buffer[0..file_path.len], file_path);
|
||||
buffer[file_path.len] = 0;
|
||||
return buffer[0..file_path.len :0];
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user