Skip to content
Please note that GitHub no longer supports Internet Explorer.

We recommend upgrading to the latest Microsoft Edge, Google Chrome, or Firefox.

Learn more
Raw bindings to Linux platform APIs for .NET Core
C#
Branch: master
Clone or download
Latest commit ee598f4 Jan 26, 2020
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src Bump version prefix to 0.4.0 Jan 26, 2020
test/Tmds.LibC.Tests Update io_uring (#44) Jan 21, 2020
tools/GenerateDoc Rename Tmds.LibC.Definitions to Tmds.Linux.LibC (#18) Jan 27, 2019
.gitattributes Add git config files Jan 15, 2019
.gitignore
.travis.yml Add Tmds.LibC.Tests (#10) Jan 24, 2019
LICENSE Initial commit Jan 15, 2019
README.md Add mman (#41) Nov 5, 2019
README.md.in Fix example: ensure path passed to mkdir is null-terminated (#32) Mar 28, 2019

README.md

Travis NuGet

Tmds.LibC

Raw bindings to Linux platform APIs for .NET Core.

Raw bindings

The APIs provided by this package stay as close as possible to the native declarations. Because the native APIs are different per platform (e.g. linux-arm64 vs linux-x64), the package contains separate assemblies for each platform.

.NET Core will use the appropriate assembly based on the rid.

Supported platforms

  • linux x64 glibc
  • linux arm64 glibc
  • linux arm32 glibc

Using this package

Add the package using the dotnet cli:

$ dotnet add package Tmds.LibC

Alternatively, you can use a daily build from the https://www.myget.org/F/tmds/api/v3/index.json NuGet feed.

Program.cs

using System;
using System.Text;
using Tmds.Linux;
using static Tmds.Linux.LibC;

namespace console
{
    class Program
    {
        unsafe static void Main(string[] args)
        {
            var bytes = Encoding.UTF8.GetBytes("Hello world!");
            fixed (byte* buffer = bytes)
            {
                write(STDOUT_FILENO, buffer, bytes.Length);
            }
        }
    }
}

Functions

The following functions are defined in the static class Tmds.Linux.LibC:

_exit, accept, accept4, access, acct, alarm, bind, brk, cfgetispeed, cfgetospeed, cfsetispeed, cfsetospeed, chdir, chmod, chown, chroot, clone, close, confstr, connect, creat, ctermid, daemon, dladdr, dlclose, dlerror, dlinfo, dlopen, dlsym, dlvsym, dup, dup2, dup3, eaccess, epoll_create, epoll_create1, epoll_ctl, epoll_pwait, epoll_wait, euidaccess, execve, faccessat, fallocate, fchdir, fchmod, fchmodat, fchown, fchownat, fcntl, fdatasync, fexecve, fork, fpathconf, fstat, fstatat, fstatvfs, fsync, ftruncate, futimens, getcwd, getdomainname, getdtablesize, getegid, geteuid, getgid, getgroups, gethostid, gethostname, getlogin, getlogin_r, getpagesize, getpeername, getpgid, getpgrp, getpid, getppid, getresgid, getresuid, getsid, getsockname, getsockopt, getuid, htons, io_destroy, io_getevents, io_setup, io_submit, ioctl, isatty, kill, killpg, lchown, link, linkat, listen, lockf, lseek, lstat, mkdir, mkdirat, mkfifo, mkfifoat, mknod, mknodat, mlock, mlock2, mlockall, mmap, mount, mprotect, msync, munlock, munlockall, munmap, name_to_handle_at, nice, ntohs, open, open_by_handle_at, openat, pathconf, pause, pipe, pipe2, posix_fadvise, posix_fallocate, pread, psiginfo, psignal, pthread_kill, pthread_sigmask, pwrite, raise, read, readahead, readlink, readlinkat, recv, recvfrom, recvmsg, rmdir, sbrk, sched_get_priority_max, sched_get_priority_min, sched_getaffinity, sched_getcpu, sched_getscheduler, sched_rr_get_interval, sched_setaffinity, sched_yield, send, sendmsg, sendto, setdomainname, setegid, seteuid, setgid, setgroups, sethostname, setns, setpgid, setpgrp, setregid, setresgid, setresuid, setreuid, setsid, setsockopt, setuid, shutdown, sigaction, sigaddset, sigaltstack, sigandset, sigdelset, sigemptyset, sigfillset, sighold, sigignore, siginterrupt, sigisemptyset, sigismember, sigorset, sigpause, sigpending, sigprocmask, sigqueue, sigrelse, sigsuspend, sigtimedwait, sigwait, sigwaitinfo, sleep, socket, socketpair, splice, stat, statvfs, strerror_r, symlink, symlinkat, sync, sync_file_range, syncfs, syscall, sysconf, tcdrain, tcflow, tcflush, tcgetattr, tcgetpgrp, tcgetsid, tcsendbreak, tcsetattr, tcsetpgrp, tee, truncate, ttyname, ttyname_r, ualarm, umask, umount, umount2, unlink, unlinkat, unshare, usleep, utimensat, vfork, vhangup, vmsplice, write,

Structs

The following structs are defined in the Tmds.Linux namespace:

aio_context_t, aio_ring, blkcnt_t, blksize_t, clock_t, cmsghdr, cpu_set_t, dev_t, Dl_info, epoll_data_t, epoll_event, f_owner_ex, file_handle, flock, fsblkcnt_t, fsfilcnt_t, gid_t, group_filter, group_req, group_source_req, in_addr, in_pktinfo, in6_addr, in6_pktinfo, ino_t, io_event, iocb, iovec, ip_mreq, ip_mreq_source, ip_mreqn, ip_opts, ip6_mtuinfo, ipv6_mreq, linger, long_t, mmsghdr, mode_t, msghdr, nlink_t, off_t, pid_t, pthread_t, sa_family_t, scm_timestamping, sigaction, sigevent_t, siginfo_t, sigset_t, sigval, size_t, sock_extended_err, sockaddr, sockaddr_in, sockaddr_in6, sockaddr_storage, sockaddr_un, socklen_t, ssize_t, stack_t, stat, statvfs, syscall_arg, termios, time_t, timespec, ucred, uid_t, ulong_t, winsize,

Examples

This section shows some examples. The examples use a PlatformException class which is implemented as follows:

class PlatformException : Exception
{
    public PlatformException(int errno) :
        base(GetErrorMessage(errno))
    {
        HResult = errno;
    }

    public PlatformException() :
        this(LibC.errno)
    {}

    private unsafe static string GetErrorMessage(int errno)
    {
        int bufferLength = 1024;
        byte* buffer = stackalloc byte[bufferLength];

        int rv = strerror_r(errno, buffer, bufferLength);

        return rv == 0 ? Marshal.PtrToStringAnsi((IntPtr)buffer) : $"errno {errno}";
    }

    public static void Throw() => throw new PlatformException();
}

Example 1: Socket extension method to set raw socket options

static class SocketExtensions
{
    public static unsafe void SetRawSocketOption(this Socket socket, int level, int optname, int optval)
    {
        SafeHandle handle = socket.SafeHandle;
        bool refAdded = false;
        try
        {
            handle.DangerousAddRef(ref refAdded);
            int rv = setsockopt(handle.DangerousGetHandle().ToInt32(), level, optname, &optval, sizeof(int));
            if (rv != 0)
            {
                PlatformException.Throw();
            }
        }
        finally
        {
            if (refAdded)
                handle.DangerousRelease();
        }
    }
}

This extension method can be used with the constants provided by Tmds.LibC, for example:

socket.SetRawSocketOption(SOL_SOCKET, SO_REUSEADDR, 1);

Example 2: Process extension method to request termination

Unix processes can be requested to terminate using the SIGTERM signal. The following code adds an extension method to the Process class to send that signal.

static class ProcessExtensions
{
    public static void Terminate(this Process process)
    {
        if (process.HasExited)
        {
            return;
        }
        int rv = kill(process.Handle.ToInt32(), SIGTERM);
        if (rv == -1 &&
            errno != ESRCH /* process does not exist, assume it exited */)
        {
            PlatformException.Throw();
        }
    }
}

Example 3: Creating a temporary directory that is only accessible by the user

static class FileUtils
{
    public unsafe static string CreatePrivateTempDirectory()
    {
        string path = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());

        int byteLength = Encoding.UTF8.GetByteCount(path) + 1;
        Span<byte> bytes = byteLength <= 128 ? stackalloc byte[byteLength] : new byte[byteLength];
        Encoding.UTF8.GetBytes(path, bytes);

        fixed (byte* pathname = bytes)
        {
            int rv = mkdir(pathname, S_IRWXU);
            if (rv == -1)
            {
                PlatformException.Throw();
            }
        }

        return path;
    }
}
You can’t perform that action at this time.