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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user