2

I'm trying to convert, or at least understand this ioctl call:

#define NVME_URING_CMD_IO   _IOWR('N', 0x80, struct nvme_uring_cmd)

Is there an equivalent of _IOWR in golang? maybe with the unix package?

Mascarpone
  • 2,516
  • 4
  • 25
  • 46
  • Seems connected to this https://stackoverflow.com/questions/54388088/how-to-ioctl-properly-from-golang – Mascarpone Oct 11 '22 at 17:03
  • 1
    Have you actually tried to do `grep -r -E '#define\s+_IOWR' /usr/include/` on your system and then read the `ioctl.h` file it finds? I mean, the question as stated makes little sense as you've shown a definition of a C macro which ostensibly refers to another C macro (which may refer to other—all the way down to the elephants and the turtle). So you first have to come up with the "unwrapped" bit of C code for your question to have sense. Note that the definition you have shown does not look like an `ioctl` call. – kostix Oct 11 '22 at 17:57
  • 1
    Also youmight start with a common approach: create a no-brained C program which contains `#include ` and then contains the definition you've cited, and then declares a variable of type `NVME_URING_CMD_IO`. Then ask the preprocessor to expand all the macros—for `gcc` that will be `gcc -E yourprogramfile.c`. You will see what kind of thing all this gets unwrapped in the end. – kostix Oct 11 '22 at 17:59
  • 1
    The `_IOWR` and similar macros compile to a magic constant. You can't always get this constant directly from Go as the constant embeds the result of `sizeof` some C data type and not all C data types can be expressed in Go (unions are problematic in particular). – torek Oct 12 '22 at 04:23
  • 1
    You can, however, run a C compiler over some C code that spits out the constant into a file that you can then incorporate into Go source code. But that still leaves you with the problem of setting up the C data structure. You can sometimes do the whole thing on a case-by-case basis, and that's generally what you find in cross-language ioctl packages. – torek Oct 12 '22 at 04:24
  • thanks guys, I couldn't compile the project due to some local conflicts, but by following the code and thanks to your suggestions I managed to make it work. It turns out that although it was in the `ioctl.h` file no `ioctl` calls are needed. – Mascarpone Oct 12 '22 at 12:31

1 Answers1

0

Ok, I managed to convert it, thanks to help in comments:


const (
    IocNrBits           = 8
    IocTypeBits         = 8
    IocSizeBits         = 14
    IocNrShift          = 0
    IocRead     uintptr = 2
    IocWrite    uintptr = 2
)

const (
    IocTypeShift = IocNrShift + IocNrBits
    IocSizeShift = IocTypeShift + IocTypeBits
    IocDirshift  = IocSizeShift + IocSizeBits
)

func IOC(dir, t, nr, size uintptr) uintptr {
    return (dir << IocDirshift) |
        (t << IocTypeShift) |
        (nr << IocNrShift) |
        (size << IocSizeShift)
}

func IOWR(t, nr, size uintptr) uintptr {
    return IOC(IocRead|IocWrite, t, nr, size)
}

func NVME_URING_CMD_IO() uintptr {
    return IOWR('N', 0x80, 32)
}

Mascarpone
  • 2,516
  • 4
  • 25
  • 46