diff --git a/Dir.zig b/Dir.zig index 331cb8b1ece00dde355a7e5467f19858bf891543..ff6ccc81aeb0b07aa45f8c1c095926152358f90b 100644 --- a/Dir.zig +++ b/Dir.zig @@ -146,6 +146,7 @@ pub fn iterate(self: Dir) Iterator { .buf = undefined, .idx = 0, .len = 0, + .seek = 0, }; } @@ -154,8 +155,28 @@ pub const Iterator = struct { buf: [1024]u8, idx: usize, len: usize, + seek: c_long, pub fn next(iter: *Iterator) !?Entry { + if (os == .macos) { + if (iter.idx == iter.len) { + const len = try sys.getdirentries(@intFromEnum(iter.dir.fd), &iter.buf, &iter.seek); + if (len == 0) return null; + iter.idx = 0; + iter.len = len; + } + const ent: *align(1) sys.struct_dirent = @ptrCast(&iter.buf[iter.idx]); + iter.idx += ent.reclen; + ent.name[ent.namlen] = 0; + const name = ent.name[0..ent.namlen :0]; + if (std.mem.eql(u8, name, ".")) return next(iter); + if (std.mem.eql(u8, name, "..")) return next(iter); + if (ent.ino == 0) return next(iter); + return .{ + .name = name, + .type = ent.type, + }; + } if (iter.idx == iter.len) { const len = try sys.getdents(@intFromEnum(iter.dir.fd), &iter.buf); if (len == 0) return null; @@ -328,3 +349,49 @@ pub const AccessMode = packed struct(c_uint) { executable: bool = false, _: u29 = 0, }; + +pub fn realpath(self: Dir, sub_path: [:0]const u8, buf: *[sys.PATH_MAX]u8) ![:0]u8 { + if (std.mem.eql(u8, sub_path, ".")) { + if (@intFromEnum(self.fd) == sys.AT.FDCWD) { + return nfs.cwdpath(buf); + } + return nfs.realdpath(self.fd, buf); + } + var file = try self.openFile(sub_path, .{}); + defer file.close(); + return nfs.realdpath(file.fd, buf); +} + +pub fn realpathAlloc(self: Dir, allocator: std.mem.Allocator, sub_path: [:0]const u8) ![:0]u8 { + var buf: [sys.PATH_MAX]u8 = undefined; + const actual = try self.realpath(sub_path, &buf); + return allocator.dupeZ(u8, actual); +} + +pub fn deleteFile(self: Dir, sub_path: [:0]const u8) !void { + return sys.unlinkat(@intFromEnum(self.fd), sub_path.ptr, 0); +} + +pub fn deleteDir(self: Dir, sub_path: [:0]const u8) !void { + return sys.unlinkat(@intFromEnum(self.fd), sub_path.ptr, sys.AT.REMOVEDIR); +} + +pub fn deleteTree(self: Dir, sub_path: [:0]const u8) !void { + var dir = try self.openDir(sub_path, .{}); + { + errdefer dir.close(); + var iter = dir.iterate(); + while (try iter.next()) |entry| { + switch (entry.type) { + .DIR => { + try dir.deleteTree(entry.name); + }, + else => { + try dir.deleteFile(entry.name); + }, + } + } + dir.close(); + } + try self.deleteDir(sub_path); +} diff --git a/File.zig b/File.zig index 9f6814e9bfa5afc967c335b8648c9d086460dde5..a4b52a992d54bb600f607cc7fe611eb08771bc00 100644 --- a/File.zig +++ b/File.zig @@ -211,3 +211,11 @@ pub fn mmap(self: File) ![]const u8 { pub fn utime(self: File, times: [2]sys.struct_timespec) !void { return sys.futimens(@intFromEnum(self.fd), times); } + +pub fn isatty(self: File) bool { + return sys.libc.isatty(@intFromEnum(self.fd)) == 1; +} + +pub fn seekTo(self: File, pos: u64) !void { + return sys.lseek(@intFromEnum(self.fd), @bitCast(pos), sys.SEEK.SET); +} diff --git a/nfs.zig b/nfs.zig index f0d181390891ab9a49429b22a3fc40ed6378e8b8..3a31ddd140867f66874533a5ff1972f00635ed6f 100644 --- a/nfs.zig +++ b/nfs.zig @@ -1,6 +1,7 @@ const std = @import("std"); const builtin = @import("builtin"); const sys_linux = @import("sys-linux"); +const nio = @import("nio"); pub const Dir = @import("./Dir.zig"); pub const File = @import("./File.zig"); @@ -25,6 +26,12 @@ pub fn cwd() Dir { return .{ .fd = @enumFromInt(sys.AT.FDCWD) }; } +pub fn cwdpath(buf: []u8) ![:0]u8 { + const ptr = try sys.getcwd(buf); + const str = std.mem.sliceTo(ptr, 0); + return str; +} + pub fn stdin() File { return .{ .fd = @enumFromInt(0) }; } @@ -80,3 +87,18 @@ pub fn pipe2(flag: c_int) ![2]File { pub fn dup2(fd1: Handle, fd2: Handle) !void { return sys.dup2(@intFromEnum(fd1), @intFromEnum(fd2)); } + +pub fn realdpath(fd: Handle, buf: *[sys.PATH_MAX]u8) ![:0]u8 { + if (os == .linux) { + var dbuf: [64]u8 = undefined; + const str = nio.fmt.bufPrintZ(&dbuf, "/proc/self/fd/{d}", .{fd}) catch unreachable; + return sys.readlinkat(@intFromEnum(cwd().fd), str, buf); + } + if (os == .macos) { + @memset(buf, 0); + const rc = sys.libc.fcntl(@intFromEnum(fd), sys.F.GETPATH, buf.ptr); + if (rc == -1) return sys.errno.fromInt(sys.errno.fromLibC()); + const idx = std.mem.indexOfScalar(u8, buf, 0).?; + return buf[0..idx :0]; + } +}