Lindenii Project Forge
Login

go-lindenii-common

Common library for the Lindenii Project
Commit info
ID
e140786e35c5d64d5fa0d4bd64df1a44940b6be3
Author
Runxi Yu <me@runxiyu.org>
Author date
Sat, 04 Jan 2025 19:54:43 +0800
Committer
Runxi Yu <me@runxiyu.org>
Committer date
Sat, 04 Jan 2025 19:54:43 +0800
Actions
misc: Add Openat2
// Package misc provides miscellaneous functions.
package misc

import (
	"errors"
	"strings"
)

// Copy_map the map src to dst without clearing existing items in dst.
func Copy_map[K comparable, V any](dst map[K]V, src map[K]V) {
	for k, v := range src {
		dst[k] = v
	}
}

// String_to_byte_ptr returns a pointer to the first byte of a string. It
// ensures that the returned pointer is null-terminated.
func String_to_byte_ptr(s string) (*byte, error) {
	// If the string already contains a null then whoever attempts to
	// interpret this as a null-terminated string won't be able to see the
	// whole string. This is probably not expected by the caller.
	if strings.IndexByte(s, 0) != -1 {
		return nil, Err_null_byte
	}
	buf := make([]byte, len(s)+1) // Zeros them out...
	copy(buf, s)                  // ... so the last byte would be null.
	return &buf[0], nil
}

var Err_null_byte = errors.New("string contains null byte")
package misc

import (
	"syscall"
	"unsafe"
)

const SYS_OPENAT2 = 437

type Open_how_t struct {
	Flags   uint64
	Mode    uint64
	Resolve uint64
}

const (
	RESOLVE_BENEATH       = 0x8
	RESOLVE_IN_ROOT       = 0x10
	RESOLVE_NO_MAGICLINKS = 0x2
	RESOLVE_NO_SYMLINKS   = 0x4
	RESOLVE_NO_XDEV       = 0x1
)

// See openat2(2) on Linux
func Openat2(dirfd int, path string, open_how *Open_how_t, size int) (fd int, err error) {
	path_ptr, err := String_to_byte_ptr(path)
	if err != nil {
		return
	}
	_fd, _, errno := syscall.Syscall6(SYS_OPENAT2, uintptr(dirfd), uintptr(unsafe.Pointer(path_ptr)), uintptr(unsafe.Pointer(open_how)), uintptr(size), 0, 0)
	fd = int(_fd)
	if errno != 0 {
		err = errno
	}
	return
}