Search code examples
goplan-9

undefined: syscall.Stat_t for plan9


I am working on a file manager for 9front/Plan9; dev work is done in Go v1.15 under 64-bit Ubuntu with cross-compilation to build Plan9 binaries.

Let's assume a function to retrieve user/group information:

import "syscall"
func GetXid(info os.FileInfo) (string, string) {
    UID := "N/A"
    GID := "N/A"
    if stat, ok := info.Sys().(*syscall.Stat_t); ok {
        UID = strconv.Itoa(int(stat.Uid))
        GID = strconv.Itoa(int(stat.Gid))
    }
    return UID, GID
}

it fails during Plan9 compilation with undefined: syscall.Stat_t.

syscall package page states that it has been deprecated since Go v1.4 and replaced with OS-specific repos under golang.org/x/sys/.

  • How to implement OS-specific casting of the os.FileInfo.Sys for Linux and Plan9

Solution

  • This answer greatly aided my research. In short, while the syscall codebase was broken and moved into OS-specific packages under golang.org/x/sys/, we still use syscall.xxx semantic to access structures from golang.org/x/sys/:

    • for Plan9 it is Dir
    var info os.FileInfo = ...
    info.Sys().(*syscall.Dir)
    
    var info os.FileInfo = ...
    info.Sys().(*syscall.Stat_t)
    

    To put the above findings into the solution, I followed @torek advice and created two files, each with the func GetXid(info os.FileInfo) (string, string) function and // +build <os> instruction at the top:

    • file_details_plan9.go
    // +build plan9
    
    package model
    import (
        "syscall"
        "os"
    )
    
    func GetXid(info os.FileInfo) (string, string) {
        UID := "N/A"
        GID := "N/A"
        if stat, ok := info.Sys().(*syscall.Dir); ok {
            UID = stat.Uid
            GID = stat.Gid
        }
        return UID, GID
    }
    
    • file_details_unix.go
    // +build linux
    
    package model
    import (
        "os"
        "strconv"
        "syscall"
    )
    
    func GetXid(info os.FileInfo) (string, string) {
        UID := "N/A"
        GID := "N/A"
        if stat, ok := info.Sys().(*syscall.Stat_t); ok {
            UID = strconv.Itoa(int(stat.Uid))
            GID = strconv.Itoa(int(stat.Gid))
        }
        return UID, GID
    }
    

    NOTE: it also appears that the package golang.org/x/sys/plan9 is missing in the standard Go installation, and needs to be installed explicitly:

    go get golang.org/x/sys/plan9
    go mod vendor
    go mod tidy