Commit 4a8c992ef1

Shawn Landden <shawn@git.icu>
2018-08-30 02:36:18
os: use less syscalls
these don't exist on new platforms (such as arm64) also switch from the deprecated dirent to dirent64
1 parent d956d30
Changed files (3)
std/os/linux/index.zig
@@ -665,6 +665,13 @@ pub const F_GETOWN_EX = 16;
 
 pub const F_GETOWNER_UIDS = 17;
 
+pub const AT_FDCWD = -100;
+pub const AT_SYMLINK_NOFOLLOW = 0x100;
+pub const AT_REMOVEDIR = 0x200;
+pub const AT_SYMLINK_FOLLOW = 0x400;
+pub const AT_NO_AUTOMOUNT = 0x800;
+pub const AT_EMPTY_PATH = 0x1000;
+
 pub fn S_ISREG(m: u32) bool {
     return m & S_IFMT == S_IFREG;
 }
@@ -738,7 +745,11 @@ pub fn getErrno(r: usize) usize {
 }
 
 pub fn dup2(old: i32, new: i32) usize {
-    return syscall2(SYS_dup2, @intCast(usize, old), @intCast(usize, new));
+    return dup3(old, new, 0);
+}
+
+pub fn dup3(old: i32, new: i32, flags: u32) usize {
+    return syscall3(SYS_dup3, @intCast(usize, old), @intCast(usize, new), flags);
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
@@ -757,7 +768,7 @@ pub fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [*]const ?[*
 }
 
 pub fn fork() usize {
-    return syscall0(SYS_fork);
+    return clone2(SIGCHLD, 0);
 }
 
 pub fn futex_wait(uaddr: usize, futex_op: u32, val: i32, timeout: ?*timespec) usize {
@@ -772,8 +783,8 @@ pub fn getcwd(buf: [*]u8, size: usize) usize {
     return syscall2(SYS_getcwd, @ptrToInt(buf), size);
 }
 
-pub fn getdents(fd: i32, dirp: [*]u8, count: usize) usize {
-    return syscall3(SYS_getdents, @intCast(usize, fd), @ptrToInt(dirp), count);
+pub fn getdents64(fd: i32, dirp: [*]u8, count: usize) usize {
+    return syscall3(SYS_getdents64, @intCast(usize, fd), @ptrToInt(dirp), count);
 }
 
 pub fn inotify_init1(flags: u32) usize {
@@ -795,16 +806,26 @@ pub fn isatty(fd: i32) bool {
 
 // TODO https://github.com/ziglang/zig/issues/265
 pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {
-    return syscall3(SYS_readlink, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
+    return readlinkat(AT_FDCWD, path, buf_ptr, buf_len);
+}
+
+// TODO https://github.com/ziglang/zig/issues/265
+pub fn readlinkat(dirfd: i32, noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {
+    return syscall4(SYS_readlinkat, @intCast(usize, dirfd), @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
 pub fn mkdir(path: [*]const u8, mode: u32) usize {
-    return syscall2(SYS_mkdir, @ptrToInt(path), mode);
+    return mkdirat(AT_FDCWD, path, mode);
+}
+
+// TODO https://github.com/ziglang/zig/issues/265
+pub fn mkdirat(dirfd: i32, path: [*]const u8, mode: u32) usize {
+    return syscall3(SYS_mkdirat, @intCast(usize, dirfd), @ptrToInt(path), mode);
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
-pub fn mount(special: [*]const u8, dir: [*]const u8, fstype: [*]const u8, flags: usize, data: usize) usize {
+pub fn mount(special: [*]const u8, dir: [*]const u8, fstype: [*]const u8, flags: u32, data: usize) usize {
     return syscall5(SYS_mount, @ptrToInt(special), @ptrToInt(dir), @ptrToInt(fstype), flags, data);
 }
 
@@ -840,28 +861,38 @@ pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) us
 
 // TODO https://github.com/ziglang/zig/issues/265
 pub fn rmdir(path: [*]const u8) usize {
-    return syscall1(SYS_rmdir, @ptrToInt(path));
+    return unlinkat(AT_FDCWD, path, AT_REMOVEDIR);
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
 pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {
-    return syscall2(SYS_symlink, @ptrToInt(existing), @ptrToInt(new));
+    return symlinkat(existing, AT_FDCWD, new);
 }
 
+// TODO https://github.com/ziglang/zig/issues/265
+pub fn symlinkat(existing: [*]const u8, newfd: i32, newpath: [*]const u8) usize {
+    return syscall3(SYS_symlinkat, @ptrToInt(existing), @intCast(usize, newfd), @ptrToInt(newpath));
+}
+
+// TODO https://github.com/ziglang/zig/issues/265
 pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize {
     return syscall4(SYS_pread, @intCast(usize, fd), @ptrToInt(buf), count, offset);
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
 pub fn access(path: [*]const u8, mode: u32) usize {
-    return syscall2(SYS_access, @ptrToInt(path), mode);
+    return faccessat(AT_FDCWD, path, mode);
+}
+
+pub fn faccessat(dirfd: i32, path: [*]const u8, mode: u32) usize {
+    return syscall3(SYS_faccessat, @intCast(usize, dirfd), @ptrToInt(path), mode);
 }
 
 pub fn pipe(fd: *[2]i32) usize {
     return pipe2(fd, 0);
 }
 
-pub fn pipe2(fd: *[2]i32, flags: usize) usize {
+pub fn pipe2(fd: *[2]i32, flags: u32) usize {
     return syscall2(SYS_pipe2, @ptrToInt(fd), flags);
 }
 
@@ -875,12 +906,17 @@ pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
 
 // TODO https://github.com/ziglang/zig/issues/265
 pub fn rename(old: [*]const u8, new: [*]const u8) usize {
-    return syscall2(SYS_rename, @ptrToInt(old), @ptrToInt(new));
+    return renameat2(AT_FDCWD, old, AT_FDCWD, new, 0);
+}
+
+// TODO https://github.com/ziglang/zig/issues/265
+pub fn renameat2(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const u8, flags: u32) usize {
+    return syscall5(SYS_renameat2, @intCast(usize, oldfd), @ptrToInt(oldpath), @intCast(usize, newfd), @ptrToInt(newpath), flags);
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
 pub fn open(path: [*]const u8, flags: u32, perm: usize) usize {
-    return syscall3(SYS_open, @ptrToInt(path), flags, perm);
+    return openat(AT_FDCWD, path, flags, perm);
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
@@ -889,7 +925,7 @@ pub fn create(path: [*]const u8, perm: usize) usize {
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
-pub fn openat(dirfd: i32, path: [*]const u8, flags: usize, mode: usize) usize {
+pub fn openat(dirfd: i32, path: [*]const u8, flags: u32, mode: usize) usize {
     return syscall4(SYS_openat, @intCast(usize, dirfd), @ptrToInt(path), flags, mode);
 }
 
@@ -899,7 +935,7 @@ pub fn clone5(flags: usize, child_stack_ptr: usize, parent_tid: *i32, child_tid:
 }
 
 /// See also `clone` (from the arch-specific include)
-pub fn clone2(flags: usize, child_stack_ptr: usize) usize {
+pub fn clone2(flags: u32, child_stack_ptr: usize) usize {
     return syscall2(SYS_clone, flags, child_stack_ptr);
 }
 
@@ -917,7 +953,7 @@ pub fn exit(status: i32) noreturn {
 }
 
 pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize {
-    return syscall3(SYS_getrandom, @ptrToInt(buf), count, @intCast(usize, flags));
+    return syscall3(SYS_getrandom, @ptrToInt(buf), count, flags);
 }
 
 pub fn kill(pid: i32, sig: i32) usize {
@@ -926,7 +962,12 @@ pub fn kill(pid: i32, sig: i32) usize {
 
 // TODO https://github.com/ziglang/zig/issues/265
 pub fn unlink(path: [*]const u8) usize {
-    return syscall1(SYS_unlink, @ptrToInt(path));
+    return unlinkat(AT_FDCWD, path, 0);
+}
+
+// TODO https://github.com/ziglang/zig/issues/265
+pub fn unlinkat(dirfd: i32, path: [*]const u8, flags: u32) usize {
+    return syscall3(SYS_unlinkat, @intCast(usize, dirfd), @ptrToInt(path), flags);
 }
 
 pub fn waitpid(pid: i32, status: *i32, options: i32) usize {
@@ -1230,17 +1271,22 @@ pub fn accept4(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t, flags:
 }
 
 pub fn fstat(fd: i32, stat_buf: *Stat) usize {
-    return syscall2(SYS_fstat, @intCast(usize, fd), @ptrToInt(stat_buf));
+    return fstatat(fd, c"", stat_buf, AT_EMPTY_PATH);
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
 pub fn stat(pathname: [*]const u8, statbuf: *Stat) usize {
-    return syscall2(SYS_stat, @ptrToInt(pathname), @ptrToInt(statbuf));
+    return fstatat(AT_FDCWD, pathname, statbuf, AT_NO_AUTOMOUNT);
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
 pub fn lstat(pathname: [*]const u8, statbuf: *Stat) usize {
-    return syscall2(SYS_lstat, @ptrToInt(pathname), @ptrToInt(statbuf));
+    return fstatat(AF_FDCWD, pathname, statbuf, AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT);
+}
+
+// TODO https://github.com/ziglang/zig/issues/265
+pub fn fstatat(dirfd: i32, path: [*]const u8, stat_buf: *Stat, flags: u32) usize {
+    return syscall4(SYS_fstatat, @intCast(usize, dirfd), @ptrToInt(path), @ptrToInt(stat_buf), flags);
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
@@ -1331,7 +1377,18 @@ pub fn epoll_ctl(epoll_fd: i32, op: u32, fd: i32, ev: *epoll_event) usize {
 }
 
 pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32) usize {
-    return syscall4(SYS_epoll_wait, @intCast(usize, epoll_fd), @ptrToInt(events), @intCast(usize, maxevents), @intCast(usize, timeout));
+    return epoll_pwait(epoll_fd, events, maxevents, timeout, null);
+}
+
+pub fn epoll_pwait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32, sigmask: ?*sigset_t) usize {
+    return syscall6(SYS_epoll_pwait,
+        @intCast(usize, epoll_fd),
+        @ptrToInt(events),
+        @intCast(usize, maxevents),
+        @intCast(usize, timeout),
+        @ptrToInt(sigmask),
+        @sizeOf(sigset_t)
+    );
 }
 
 pub fn eventfd(count: u32, flags: u32) usize {
@@ -1339,7 +1396,7 @@ pub fn eventfd(count: u32, flags: u32) usize {
 }
 
 pub fn timerfd_create(clockid: i32, flags: u32) usize {
-    return syscall2(SYS_timerfd_create, @intCast(usize, clockid), @intCast(usize, flags));
+    return syscall2(SYS_timerfd_create, @intCast(usize, clockid), flags);
 }
 
 pub const itimerspec = extern struct {
@@ -1352,7 +1409,7 @@ pub fn timerfd_gettime(fd: i32, curr_value: *itimerspec) usize {
 }
 
 pub fn timerfd_settime(fd: i32, flags: u32, new_value: *const itimerspec, old_value: ?*itimerspec) usize {
-    return syscall4(SYS_timerfd_settime, @intCast(usize, fd), @intCast(usize, flags), @ptrToInt(new_value), @ptrToInt(old_value));
+    return syscall4(SYS_timerfd_settime, @intCast(usize, fd), flags, @ptrToInt(new_value), @ptrToInt(old_value));
 }
 
 pub const _LINUX_CAPABILITY_VERSION_1 = 0x19980330;
@@ -1462,7 +1519,7 @@ pub const cap_user_data_t = extern struct {
 };
 
 pub fn unshare(flags: usize) usize {
-    return syscall1(SYS_unshare, @intCast(usize, flags));
+    return syscall1(SYS_unshare, flags);
 }
 
 pub fn capget(hdrp: *cap_user_header_t, datap: *cap_user_data_t) usize {
@@ -1481,6 +1538,14 @@ pub const inotify_event = extern struct {
     //name: [?]u8,
 };
 
+pub const dirent64 = extern struct {
+    d_ino: u64,
+    d_off: u64,
+    d_reclen: u16,
+    d_type: u8,
+    d_name: u8, // field address is the address of first byte of name https://github.com/ziglang/zig/issues/173
+};
+
 test "import" {
     if (builtin.os == builtin.Os.linux) {
         _ = @import("test.zig");
std/os/linux/x86_64.zig
@@ -266,6 +266,8 @@ pub const SYS_mknodat = 259;
 pub const SYS_fchownat = 260;
 pub const SYS_futimesat = 261;
 pub const SYS_newfstatat = 262;
+// https://github.com/ziglang/zig/issues/1439
+pub const SYS_fstatat = 262;
 pub const SYS_unlinkat = 263;
 pub const SYS_renameat = 264;
 pub const SYS_linkat = 265;
@@ -480,11 +482,4 @@ pub const timezone = extern struct {
     tz_dsttime: i32,
 };
 
-pub const dirent = extern struct {
-    d_ino: usize,
-    d_off: usize,
-    d_reclen: u16,
-    d_name: u8, // field address is the address of first byte of name
-};
-
 pub const Elf_Symndx = u32;
std/os/index.zig
@@ -1641,7 +1641,7 @@ pub const Dir = struct {
                 }
 
                 while (true) {
-                    const result = posix.getdents(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len);
+                    const result = posix.getdents64(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len);
                     const err = posix.getErrno(result);
                     if (err > 0) {
                         switch (err) {
@@ -1659,7 +1659,7 @@ pub const Dir = struct {
                     break;
                 }
             }
-            const linux_entry = @ptrCast(*align(1) posix.dirent, &self.handle.buf[self.handle.index]);
+            const linux_entry = @ptrCast(*align(1) posix.dirent64, &self.handle.buf[self.handle.index]);
             const next_index = self.handle.index + linux_entry.d_reclen;
             self.handle.index = next_index;
 
@@ -1670,8 +1670,7 @@ pub const Dir = struct {
                 continue :start_over;
             }
 
-            const type_char = self.handle.buf[next_index - 1];
-            const entry_kind = switch (type_char) {
+            const entry_kind = switch (linux_entry.d_type) {
                 posix.DT_BLK => Entry.Kind.BlockDevice,
                 posix.DT_CHR => Entry.Kind.CharacterDevice,
                 posix.DT_DIR => Entry.Kind.Directory,