0

I have the following Go code:

package main

import (
    "syscall"
)

func main() {
    _ = syscall.SYS_IOCTL // Assign to _ to avoid compiler error
}

This compiles fine for Linux, but fails to compile for Solaris:

$ GOOS=linux GOARCH=amd64 go build
$ GOOS=solaris GOARCH=amd64 go build
# ioctl-experimentation
./main.go:8:14: undefined: syscall.SYS_IOCTL

The ioctl function is a POSIX function, so I would expect to find it defined for all Unixes. Also, ioctl appears in section 2 of Solaris 11's man pages, and section 2 of Solaris 11's man pages is for system calls.

Why is syscall.SYS_IOCTL defined for Linux but undefined for Solaris?

Shane Bishop
  • 3,905
  • 4
  • 17
  • 47
  • 2
    The `syscall` package does not strive to cover POSIX (or any other "defined" subset of symbols); instead, it provides only a minimal coverage of whatever is needed to make the Go runtime and Go standard library functioning. If you need more, consider `golang.org/x/sys/unix`, and even then you might need to occasionally provide your own wrappers for missing syscalls/constants/etc. To recap, your expectations about `syscall` are quite possibly incorrect, alas. – kostix Aug 08 '22 at 16:37
  • `unix.SYS_IOCTL` is also undefined for Solaris, but is defined for Linux. I was hoping I could avoid writing any C by using [`syscall.Syscall`](https://pkg.go.dev/syscall#Syscall), but since `SYS_IOCTL` is not defined, and none of the `unix.Ioctl*` wrapper functions suit my use case, it appears I will have to write my own wrapper for `ioctl`. – Shane Bishop Aug 08 '22 at 16:46
  • 2
    Also, Solaris only considers the system libc to be the public API, so most of the time you should not be making syscalls directly. The `syscall` packages probably do not generate wrappers for other Solaris calls for this reason. – JimB Aug 08 '22 at 16:46

1 Answers1

0

syscall is not complete and has not been updated since 2015 all syscall definitions added after that only have landed in golang.org/x/sys/unix When we maintainers see golang libraries still using syscall we urge an update to golang.org/x/sys/unix which should only be a replacement of the import path and add it to the go modules file.

EDIT-- Since I last checked things have changed quite a bit. ioctl is a spacial case on platforms that don't export ioctl as public api.

If you look at https://cs.opensource.google/go/x/sys/+/master:unix/ioctl.go;bpv=0;bpt=1 there are now generic wrappers to set and specific ones to get. If you need to add support for a type adding them as a wrapper might be the best option.

In general it will be better to ask a more targeted question about the usecase so I can propose the right calls. Another option you can investigate is dynamic linking with lines like this //go:cgo_import_dynamic libc_readv readv "libc.so" for example in https://cs.opensource.google/go/x/sys/+/master:unix/zsyscall_illumos_amd64.go;bpv=0;bpt=0

Toasterson
  • 115
  • 1
  • 2
  • 11
  • With Go 1.18.3 on Linux, when I compile this code with `GOOS=solaris GOARCH=amd64 go build`, I get the error `undefined: unix.SYS_IOCTL`. Which version of Go did you test this code on? – Shane Bishop Aug 18 '22 at 22:41
  • Apparently the one before 2020 where they stopped adding syscalls on platforms that don't want them to do that. macOS and illumos/Solaris. Wireguard had also to workouround the situtation https://github.com/WireGuard/wireguard-go/pull/42 – Toasterson Aug 21 '22 at 17:51
  • Updated answer to point to places about ioctls in x/sys/unix and how they work. If you have a specific question please fill that for the usecase so I can give a concrete answer, since the answer will now depend on the types involved. – Toasterson Aug 21 '22 at 18:02
  • If you are interested in my use case, I have [this other question](https://stackoverflow.com/q/73267800/8593689) which has details on my use case. I tried following the suggestions in the comments to write my own `ioctl` wrappers in cgo, but I am struggling to cross-compile code that uses cgo for Solaris, which I ask about in [this question](https://stackoverflow.com/q/73261159/8593689). – Shane Bishop Aug 21 '22 at 18:27
  • cgo prevents cross-compiling as far as I remember – Toasterson Aug 22 '22 at 01:46
  • From the [cgo docs](https://pkg.go.dev/cmd/cgo): "[cgo] is disabled by default when cross-compiling. You can control this by setting the CGO_ENABLED environment variable when running the go tool: set it to 1 to enable the use of cgo, and to 0 to disable it." My interpretation of this is that you can cross-compile with cgo if you use `CGO_ENABLED=1`. – Shane Bishop Aug 22 '22 at 16:21
  • 1
    Yes but then you also will need al libraries and headers of the target system to link against. And a suitable GCC. It's basicaly a C cross compile environment at that point so. While yes you can hack around it, it's easier to just use a native environment. – Toasterson Aug 23 '22 at 20:17