github.com/tetratelabs/wazero@v1.2.1/internal/sysfs/dirfs_unix_test.go (about)

     1  //go:build !windows
     2  
     3  package sysfs
     4  
     5  import (
     6  	"fmt"
     7  	"os"
     8  	"path"
     9  	"syscall"
    10  	"testing"
    11  
    12  	"github.com/tetratelabs/wazero/internal/testing/require"
    13  )
    14  
    15  func TestDirFS_Chown(t *testing.T) {
    16  	tmpDir := t.TempDir()
    17  	testFS := NewDirFS(tmpDir)
    18  
    19  	require.EqualErrno(t, 0, testFS.Mkdir("dir", 0o0777))
    20  	dirF, errno := testFS.OpenFile("dir", syscall.O_RDONLY, 0)
    21  	require.EqualErrno(t, 0, errno)
    22  
    23  	dirSt, errno := dirF.Stat()
    24  	require.EqualErrno(t, 0, errno)
    25  
    26  	// Similar to TestChown in os_unix_test.go, we can't expect to change
    27  	// owner unless root, and with another user. Instead, test gid.
    28  	gid := os.Getgid()
    29  	groups, err := os.Getgroups()
    30  	require.NoError(t, err)
    31  
    32  	t.Run("-1 parameters means leave alone", func(t *testing.T) {
    33  		require.EqualErrno(t, 0, testFS.Chown("dir", -1, -1))
    34  		checkUidGid(t, path.Join(tmpDir, "dir"), dirSt.Uid, dirSt.Gid)
    35  	})
    36  
    37  	t.Run("change gid, but not uid", func(t *testing.T) {
    38  		require.EqualErrno(t, 0, testFS.Chown("dir", -1, gid))
    39  		checkUidGid(t, path.Join(tmpDir, "dir"), dirSt.Uid, uint32(gid))
    40  	})
    41  
    42  	// Now, try any other groups of the current user.
    43  	for _, g := range groups {
    44  		g := g
    45  		t.Run(fmt.Sprintf("change to gid %d", g), func(t *testing.T) {
    46  			// Test using our Chown
    47  			require.EqualErrno(t, 0, testFS.Chown("dir", -1, g))
    48  			checkUidGid(t, path.Join(tmpDir, "dir"), dirSt.Uid, uint32(g))
    49  
    50  			// Revert back
    51  			require.EqualErrno(t, 0, dirF.Chown(-1, gid))
    52  			checkUidGid(t, path.Join(tmpDir, "dir"), dirSt.Uid, uint32(gid))
    53  		})
    54  	}
    55  
    56  	t.Run("not found", func(t *testing.T) {
    57  		require.EqualErrno(t, syscall.ENOENT, testFS.Chown("a", -1, gid))
    58  	})
    59  }
    60  
    61  func TestDirFS_Lchown(t *testing.T) {
    62  	tmpDir := t.TempDir()
    63  	testFS := NewDirFS(tmpDir)
    64  
    65  	require.EqualErrno(t, 0, testFS.Mkdir("dir", 0o0777))
    66  	dirF, errno := testFS.OpenFile("dir", syscall.O_RDONLY, 0)
    67  	require.EqualErrno(t, 0, errno)
    68  
    69  	dirSt, errno := dirF.Stat()
    70  	require.EqualErrno(t, 0, errno)
    71  
    72  	require.EqualErrno(t, 0, testFS.Symlink("dir", "link"))
    73  	linkF, errno := testFS.OpenFile("link", syscall.O_RDONLY, 0)
    74  	require.EqualErrno(t, 0, errno)
    75  
    76  	linkSt, errno := linkF.Stat()
    77  	require.EqualErrno(t, 0, errno)
    78  
    79  	// Similar to TestLchown in os_unix_test.go, we can't expect to change
    80  	// owner unless root, and with another user. Instead, test gid.
    81  	gid := os.Getgid()
    82  	groups, err := os.Getgroups()
    83  	require.NoError(t, err)
    84  
    85  	t.Run("-1 parameters means leave alone", func(t *testing.T) {
    86  		require.EqualErrno(t, 0, testFS.Lchown("link", -1, -1))
    87  		checkUidGid(t, path.Join(tmpDir, "link"), linkSt.Uid, linkSt.Gid)
    88  	})
    89  
    90  	t.Run("change gid, but not uid", func(t *testing.T) {
    91  		require.EqualErrno(t, 0, testFS.Chown("dir", -1, gid))
    92  		checkUidGid(t, path.Join(tmpDir, "link"), linkSt.Uid, uint32(gid))
    93  		// Make sure the target didn't change.
    94  		checkUidGid(t, path.Join(tmpDir, "dir"), dirSt.Uid, dirSt.Gid)
    95  	})
    96  
    97  	// Now, try any other groups of the current user.
    98  	for _, g := range groups {
    99  		g := g
   100  		t.Run(fmt.Sprintf("change to gid %d", g), func(t *testing.T) {
   101  			// Test using our Lchown
   102  			require.EqualErrno(t, 0, testFS.Lchown("link", -1, g))
   103  			checkUidGid(t, path.Join(tmpDir, "link"), linkSt.Uid, uint32(g))
   104  			// Make sure the target didn't change.
   105  			checkUidGid(t, path.Join(tmpDir, "dir"), dirSt.Uid, dirSt.Gid)
   106  
   107  			// Revert back
   108  			require.EqualErrno(t, 0, testFS.Lchown("link", -1, gid))
   109  			checkUidGid(t, path.Join(tmpDir, "link"), linkSt.Uid, uint32(gid))
   110  		})
   111  	}
   112  
   113  	t.Run("not found", func(t *testing.T) {
   114  		require.EqualErrno(t, syscall.ENOENT, testFS.Lchown("a", -1, gid))
   115  	})
   116  }
   117  
   118  // checkUidGid uses lstat to ensure the comparison is against the file, not the
   119  // target of a symbolic link.
   120  func checkUidGid(t *testing.T, path string, uid, gid uint32) {
   121  	ls, err := os.Lstat(path)
   122  	require.NoError(t, err)
   123  	sys := ls.Sys().(*syscall.Stat_t)
   124  	require.Equal(t, uid, sys.Uid)
   125  	require.Equal(t, gid, sys.Gid)
   126  }