0

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
Dan M
  • 1,175
  • 12
  • 23
  • Note that plan9 does not have user and group *IDs* but rather user and group *names* (strings). So the way to handle this as portably as possible, while supporting plan9, is to expand the IDs to names (strings) on Linux. I don't know about the rest of this though. – torek Dec 06 '20 at 08:30
  • `golang.org/x/sys/plan9` is not part of the go installation. The link you show is just the sys repo that contains that package. If you don’t have it it’s because you didn’t import it. – JimB Dec 06 '20 at 14:28
  • @torek i am open to handling the return value as `string`; the question is - how to implement instructions that will reference one function OR logic for Plan9 compilation and another for Linux? – Dan M Dec 06 '20 at 20:14
  • 2
    The general mechanism for that is the `+build` directive. You define some sort of "universal accessor", then write Go files for each OS to define a function that returns the right values for that OS. Then you `+build` each of those Go files only for that one OS. They all define the same function with the same arguments, so your portable code can now call that one function. – torek Dec 06 '20 at 20:19
  • @torek Thank you! I have moved the OS-specific codebase into separate files (as illustrated by the updated posting). The compilation now passes. However, another issue manifested - how to perform OS-specific "casting" of the `os.FileInfo.Sys` – Dan M Dec 07 '20 at 07:29
  • Unfortunately the stuff in `info.Sys()` is quite messy. If you look in the Go source, in the `src/syscall` directory, you'll see that there are a bunch of `ztypes_*_*.go` files, each of which defines a `Stat_t`: these are the OS-specific `Stat_t` types that an info `Sys` accesses (if it doesn't just return nil, that is). You'll see that each of these files also has a `+build` directive. – torek Dec 07 '20 at 07:54

1 Answers1

1

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
Dan M
  • 1,175
  • 12
  • 23