gojs: adds support for uid and gid (#1245)

This adds `gojs.WithOSUser` which passes through current user IDs so
that GOOS=js compiled wasm can read them. This also adds support for
reading back the uid and gid on files. In summary, this passes
`os.TestChown` except on windows where it will not work due to lack of
support.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
Crypt Keeper
2023-03-16 11:07:27 +08:00
committed by GitHub
parent e17a85146a
commit 8464474e21
25 changed files with 556 additions and 270 deletions

View File

@@ -19,6 +19,14 @@ type Stat_t struct {
// Ino is the file serial number.
Ino uint64
// Uid is the user ID that owns the file, or zero if unsupported.
// For example, this is unsupported on some virtual filesystems or windows.
Uid uint32
// Gid is the group ID that owns the file, or zero if unsupported.
// For example, this is unsupported on some virtual filesystems or windows.
Gid uint32
// Mode is the same as Mode on fs.FileInfo containing bits to identify the
// type of the file (fs.ModeType) and its permissions (fs.ModePerm).
Mode fs.FileMode

View File

@@ -37,8 +37,10 @@ func inoFromFileInfo(_ readdirFile, t fs.FileInfo) (ino uint64, err error) {
func fillStatFromFileInfo(st *Stat_t, t fs.FileInfo) {
if d, ok := t.Sys().(*syscall.Stat_t); ok {
st.Ino = d.Ino
st.Dev = uint64(d.Dev)
st.Ino = d.Ino
st.Uid = d.Uid
st.Gid = d.Gid
st.Mode = t.Mode()
st.Nlink = uint64(d.Nlink)
st.Size = d.Size

View File

@@ -40,8 +40,10 @@ func inoFromFileInfo(_ readdirFile, t fs.FileInfo) (ino uint64, err error) {
func fillStatFromFileInfo(st *Stat_t, t fs.FileInfo) {
if d, ok := t.Sys().(*syscall.Stat_t); ok {
st.Ino = uint64(d.Ino)
st.Dev = uint64(d.Dev)
st.Ino = uint64(d.Ino)
st.Uid = d.Uid
st.Gid = d.Gid
st.Mode = t.Mode()
st.Nlink = uint64(d.Nlink)
st.Size = d.Size

View File

@@ -315,7 +315,8 @@ func TestStatFile_dev_inode(t *testing.T) {
}
func requireDirectoryDevIno(t *testing.T, st Stat_t) {
// windows before go 1.20 has trouble reading the inode information on directories.
// windows before go 1.20 has trouble reading the inode information on
// directories.
if runtime.GOOS != "windows" || IsGo120 {
require.NotEqual(t, uint64(0), st.Dev)
require.NotEqual(t, uint64(0), st.Ino)
@@ -324,3 +325,57 @@ func requireDirectoryDevIno(t *testing.T, st Stat_t) {
require.Zero(t, st.Ino)
}
}
// TestStat_uid_gid is similar to os.TestChown
func TestStat_uid_gid(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("windows")
}
// We don't attempt changing the uid of a file, as only root can do that.
// Also, this isn't a test of chown. The main goal here is to read-back
// the uid, gid, both of which are zero if run as root.
uid := uint32(os.Getuid())
gid := uint32(os.Getgid())
t.Run("Stat", func(t *testing.T) {
tmpDir := t.TempDir()
dir := path.Join(tmpDir, "dir")
require.NoError(t, os.Mkdir(dir, 0o0700))
require.NoError(t, chgid(dir, gid))
var st Stat_t
require.NoError(t, Stat(dir, &st))
require.Equal(t, uid, st.Uid)
require.Equal(t, gid, st.Gid)
})
t.Run("LStat", func(t *testing.T) {
tmpDir := t.TempDir()
link := path.Join(tmpDir, "link")
require.NoError(t, os.Symlink(tmpDir, link))
require.NoError(t, chgid(link, gid))
var st Stat_t
require.NoError(t, Lstat(link, &st))
require.Equal(t, uid, st.Uid)
require.Equal(t, gid, st.Gid)
})
t.Run("StatFile", func(t *testing.T) {
tmpDir := t.TempDir()
file := path.Join(tmpDir, "file")
require.NoError(t, os.WriteFile(file, nil, 0o0600))
require.NoError(t, chgid(file, gid))
var st Stat_t
require.NoError(t, Lstat(file, &st))
require.Equal(t, uid, st.Uid)
require.Equal(t, gid, st.Gid)
})
}
func chgid(path string, gid uint32) error {
// Note: In Chown, -1 is means leave the uid alone
return Chown(path, -1, int(gid))
}