Skip to content

Commit

Permalink
Ensures 32-bit platforms build (#996)
Browse files Browse the repository at this point in the history
Signed-off-by: Adrian Cole <[email protected]>
  • Loading branch information
codefromthecrypt authored Jan 2, 2023
1 parent 94491fe commit 4197caa
Show file tree
Hide file tree
Showing 13 changed files with 86 additions and 55 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ format:
.PHONY: check
check:
@GOARCH=amd64 GOOS=dragonfly go build ./... # Check if the internal/platform can be built on compiler-unsupported platforms
@GOARCH=386 GOOS=linux go build ./... # Check if the internal/platform can be built on compiler-unsupported platforms
@$(MAKE) lint golangci_lint_goarch=arm64
@$(MAKE) lint golangci_lint_goarch=amd64
@$(MAKE) format
Expand Down
10 changes: 5 additions & 5 deletions imports/wasi_snapshot_preview1/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,15 +273,15 @@ var blockFilestat = []byte{
func writeFilestat(buf []byte, stat fs.FileInfo) {
filetype := getWasiFiletype(stat.Mode())
filesize := uint64(stat.Size())
atimeSec, atimeNsec, mtimeSec, mtimeNsec, ctimeSec, ctimeNsec := platform.StatTimes(stat)
atimeNsec, mtimeNsec, ctimeNsec := platform.StatTimes(stat)

// memory is re-used, so ensure the result is defaulted.
copy(buf, blockFilestat[:32])
buf[16] = filetype
le.PutUint64(buf[32:], filesize) // filesize
le.PutUint64(buf[40:], uint64(atimeSec*1e9+atimeNsec)) // atim
le.PutUint64(buf[48:], uint64(mtimeSec*1e9+mtimeNsec)) // mtim
le.PutUint64(buf[56:], uint64(ctimeSec*1e9+ctimeNsec)) // ctim
le.PutUint64(buf[32:], filesize) // filesize
le.PutUint64(buf[40:], uint64(atimeNsec)) // atim
le.PutUint64(buf[48:], uint64(mtimeNsec)) // mtim
le.PutUint64(buf[56:], uint64(ctimeNsec)) // ctim
}

// fdFilestatSetSize is the WASI function named FdFilestatSetSizeName which
Expand Down
10 changes: 5 additions & 5 deletions internal/gojs/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,10 @@ func syscallFstat(fsc *internalsys.FSContext, fd uint32) (*jsSt, error) {
ret.isDir = stat.IsDir()
ret.mode = getJsMode(stat.Mode())
ret.size = stat.Size()
atimeSec, atimeNsec, mtimeSec, mtimeNsec, ctimeSec, ctimeNsec := platform.StatTimes(stat)
ret.atimeMs = atimeSec*1e3 + atimeNsec/1e6
ret.mtimeMs = mtimeSec*1e3 + mtimeNsec/1e6
ret.ctimeMs = ctimeSec*1e3 + ctimeNsec/1e6
atimeNsec, mtimeNsec, ctimeNsec := platform.StatTimes(stat)
ret.atimeMs = atimeNsec / 1e6
ret.mtimeMs = mtimeNsec / 1e6
ret.ctimeMs = ctimeNsec / 1e6
return ret, nil
}
}
Expand Down Expand Up @@ -525,7 +525,7 @@ func (*jsfsUtimes) invoke(ctx context.Context, mod api.Module, args ...interface
// syscallUtimes is like syscall.Utimes
func syscallUtimes(mod api.Module, name string, atimeSec, mtimeSec int64) (interface{}, error) {
fsc := mod.(*wasm.CallContext).Sys.FS()
err := fsc.Utimes(name, atimeSec, 0, mtimeSec, 0)
err := fsc.Utimes(name, atimeSec*1e9, mtimeSec*1e9)
return err != nil, err
}

Expand Down
12 changes: 6 additions & 6 deletions internal/platform/stat.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import "os"

// StatTimes returns platform-specific values if os.FileInfo Sys is available.
// Otherwise, it returns the mod time for all values.
func StatTimes(t os.FileInfo) (atimeSec, atimeNsec, mtimeSec, mtimeNsec, ctimeSec, ctimeNsec int64) {
func StatTimes(t os.FileInfo) (atimeNsec, mtimeNsec, ctimeNsec int64) {
if t.Sys() == nil { // possibly fake filesystem
return mtimes(t)
}
return statTimes(t)
}

func mtimes(t os.FileInfo) (int64, int64, int64, int64, int64, int64) {
mtime := t.ModTime().UnixNano()
mtimeSec := mtime / 1e9
mtimeNsec := mtime % 1e9
return mtimeSec, mtimeNsec, mtimeSec, mtimeNsec, mtimeSec, mtimeNsec
func mtimes(t os.FileInfo) (atimeNsec, mtimeNsec, ctimeNsec int64) {
mtimeNsec = t.ModTime().UnixNano()
atimeNsec = mtimeNsec
ctimeNsec = mtimeNsec
return
}
6 changes: 3 additions & 3 deletions internal/platform/stat_bsd.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build darwin || freebsd
//go:build (amd64 || arm64) && (darwin || freebsd)

package platform

Expand All @@ -7,10 +7,10 @@ import (
"syscall"
)

func statTimes(t os.FileInfo) (atimeSec, atimeNSec, mtimeSec, mtimeNSec, ctimeSec, ctimeNSec int64) {
func statTimes(t os.FileInfo) (atimeNsec, mtimeNsec, ctimeNsec int64) {
d := t.Sys().(*syscall.Stat_t)
atime := d.Atimespec
mtime := d.Mtimespec
ctime := d.Ctimespec
return atime.Sec, atime.Nsec, mtime.Sec, mtime.Nsec, ctime.Sec, ctime.Nsec
return atime.Sec*1e9 + atime.Nsec, mtime.Sec*1e9 + mtime.Nsec, ctime.Sec*1e9 + ctime.Nsec
}
6 changes: 4 additions & 2 deletions internal/platform/stat_linux.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
//go:build (amd64 || arm64) && linux

package platform

import (
"os"
"syscall"
)

func statTimes(t os.FileInfo) (atimeSec, atimeNSec, mtimeSec, mtimeNSec, ctimeSec, ctimeNSec int64) {
func statTimes(t os.FileInfo) (atimeNsec, mtimeNsec, ctimeNsec int64) {
d := t.Sys().(*syscall.Stat_t)
atime := d.Atim
mtime := d.Mtim
ctime := d.Ctim
return atime.Sec, atime.Nsec, mtime.Sec, mtime.Nsec, ctime.Sec, ctime.Nsec
return atime.Sec*1e9 + atime.Nsec, mtime.Sec*1e9 + mtime.Nsec, ctime.Sec*1e9 + ctime.Nsec
}
22 changes: 14 additions & 8 deletions internal/platform/stat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,38 +18,44 @@ func Test_StatTimes(t *testing.T) {
require.NoError(t, err)

type test struct {
name string
atimeSec, atimeNsec, mtimeSec, mtimeNsec int64
name string
atimeNsec, mtimeNsec int64
}
// Note: This sets microsecond granularity because Windows doesn't support
// nanosecond.
tests := []test{
{name: "positive", atimeSec: 123, atimeNsec: 4 * 1e3, mtimeSec: 567, mtimeNsec: 8 * 1e3},
{
name: "positive",
atimeNsec: time.Unix(123, 4*1e3).UnixNano(),
mtimeNsec: time.Unix(567, 8*1e3).UnixNano(),
},
{name: "zero"},
}

// linux and freebsd report inaccurate results when the input ts is negative.
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
tests = append(tests,
test{name: "negative", atimeSec: -123, atimeNsec: -4 * 1e3, mtimeSec: -567, mtimeNsec: -8 * 1e3},
test{
name: "negative",
atimeNsec: time.Unix(-123, -4*1e3).UnixNano(),
mtimeNsec: time.Unix(-567, -8*1e3).UnixNano(),
},
)
}

for _, tt := range tests {
tc := tt
t.Run(tc.name, func(t *testing.T) {
err := os.Chtimes(file, time.Unix(tc.atimeSec, tc.atimeNsec), time.Unix(tc.mtimeSec, tc.mtimeNsec))
err := os.Chtimes(file, time.UnixMicro(tc.atimeNsec/1e3), time.UnixMicro(tc.mtimeNsec/1e3))
require.NoError(t, err)

stat, err := os.Stat(file)
require.NoError(t, err)

atimeSec, atimeNsec, mtimeSec, mtimeNsec, _, _ := StatTimes(stat)
atimeNsec, mtimeNsec, _ := StatTimes(stat)
if CompilerSupported() {
require.Equal(t, atimeSec, tc.atimeSec)
require.Equal(t, atimeNsec, tc.atimeNsec)
} // else only mtimes will return.
require.Equal(t, mtimeSec, tc.mtimeSec)
require.Equal(t, mtimeNsec, tc.mtimeNsec)
})
}
Expand Down
4 changes: 2 additions & 2 deletions internal/platform/stat_unsupported.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//go:build !(darwin || linux || freebsd || windows)
//go:build !(amd64 || arm64) || !(darwin || linux || freebsd || windows)

package platform

import "os"

func statTimes(t os.FileInfo) (atimeSec, atimeNSec, mtimeSec, mtimeNSec, ctimeSec, ctimeNSec int64) {
func statTimes(t os.FileInfo) (atimeNsec, mtimeNsec, ctimeNsec int64) {
return mtimes(t)
}
12 changes: 7 additions & 5 deletions internal/platform/stat_windows.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
//go:build (amd64 || arm64) && windows

package platform

import (
"os"
"syscall"
)

func statTimes(t os.FileInfo) (atimeSec, atimeNsec, mtimeSec, mtimeNsec, ctimeSec, ctimeNsec int64) {
func statTimes(t os.FileInfo) (atimeNsec, mtimeNsec, ctimeNsec int64) {
d := t.Sys().(*syscall.Win32FileAttributeData)
atime := d.LastAccessTime.Nanoseconds()
mtime := d.LastWriteTime.Nanoseconds()
ctime := d.CreationTime.Nanoseconds()
return atime / 1e9, atime % 1e9, mtime / 1e9, mtime % 1e9, ctime / 1e9, ctime % 1e9
atimeNsec = d.LastAccessTime.Nanoseconds()
mtimeNsec = d.LastWriteTime.Nanoseconds()
ctimeNsec = d.CreationTime.Nanoseconds()
return
}
4 changes: 2 additions & 2 deletions internal/sys/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,10 +368,10 @@ func (c *FSContext) Unlink(name string) (err error) {
}

// Utimes is like syscall.Utimes.
func (c *FSContext) Utimes(name string, atimeSec, atimeNsec, mtimeSec, mtimeNsec int64) (err error) {
func (c *FSContext) Utimes(name string, atimeNsec, mtimeNsec int64) (err error) {
if wfs, ok := c.fs.(syscallfs.FS); ok {
name = c.cleanPath(name)
return wfs.Utimes(name, atimeSec, atimeNsec, mtimeSec, mtimeNsec)
return wfs.Utimes(name, atimeNsec, mtimeNsec)
}
err = syscall.ENOSYS
return
Expand Down
7 changes: 3 additions & 4 deletions internal/syscallfs/dirfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,12 @@ func (dir dirFS) Unlink(name string) error {
}

// Utimes implements FS.Utimes
func (dir dirFS) Utimes(name string, atimeSec, atimeNsec, mtimeSec, mtimeNsec int64) error {
func (dir dirFS) Utimes(name string, atimeNsec, mtimeNsec int64) error {
if !fs.ValidPath(name) {
return syscall.EINVAL
}

return syscall.UtimesNano(path.Join(string(dir), name), []syscall.Timespec{
{Sec: atimeSec, Nsec: atimeNsec},
{Sec: mtimeSec, Nsec: mtimeNsec},
syscall.NsecToTimespec(atimeNsec),
syscall.NsecToTimespec(mtimeNsec),
})
}
45 changes: 33 additions & 12 deletions internal/syscallfs/dirfs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"runtime"
"syscall"
"testing"
"time"

"github.com/tetratelabs/wazero/internal/platform"
"github.com/tetratelabs/wazero/internal/testing/require"
Expand Down Expand Up @@ -327,48 +328,68 @@ func TestDirFS_Utimes(t *testing.T) {
require.NoError(t, err)

t.Run("doesn't exist", func(t *testing.T) {
err := testFS.Utimes("nope", 123, 4, 567, 8)
err := testFS.Utimes("nope",
time.Unix(123, 4*1e3).UnixNano(),
time.Unix(567, 8*1e3).UnixNano())
require.Equal(t, syscall.ENOENT, err)
})

type test struct {
name string
path string
atimeSec, atimeNsec, mtimeSec, mtimeNsec int64
name string
path string
atimeNsec, mtimeNsec int64
}

// Note: This sets microsecond granularity because Windows doesn't support
// nanosecond.
tests := []test{
{name: "file positive", path: file, atimeSec: 123, atimeNsec: 4 * 1e3, mtimeSec: 567, mtimeNsec: 8 * 1e3},
{name: "dir positive", path: dir, atimeSec: 123, atimeNsec: 4 * 1e3, mtimeSec: 567, mtimeNsec: 8 * 1e3},
{
name: "file positive",
path: file,
atimeNsec: time.Unix(123, 4*1e3).UnixNano(),
mtimeNsec: time.Unix(567, 8*1e3).UnixNano(),
},
{
name: "dir positive",
path: dir,
atimeNsec: time.Unix(123, 4*1e3).UnixNano(),
mtimeNsec: time.Unix(567, 8*1e3).UnixNano(),
},
{name: "file zero", path: file},
{name: "dir zero", path: dir},
}

// linux and freebsd report inaccurate results when the input ts is negative.
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
tests = append(tests,
test{name: "file negative", path: file, atimeSec: -123, atimeNsec: -4 * 1e3, mtimeSec: -567, mtimeNsec: -8 * 1e3},
test{name: "dir negative", path: dir, atimeSec: -123, atimeNsec: -4 * 1e3, mtimeSec: -567, mtimeNsec: -8 * 1e3},
test{
name: "file negative",
path: file,
atimeNsec: time.Unix(-123, -4*1e3).UnixNano(),
mtimeNsec: time.Unix(-567, -8*1e3).UnixNano(),
},
test{
name: "dir negative",
path: dir,
atimeNsec: time.Unix(-123, -4*1e3).UnixNano(),
mtimeNsec: time.Unix(-567, -8*1e3).UnixNano(),
},
)
}

for _, tt := range tests {
tc := tt
t.Run(tc.name, func(t *testing.T) {
err := testFS.Utimes(tc.path, tc.atimeSec, tc.atimeNsec, tc.mtimeSec, tc.mtimeNsec)
err := testFS.Utimes(tc.path, tc.atimeNsec, tc.mtimeNsec)
require.NoError(t, err)

stat, err := os.Stat(path.Join(tmpDir, tc.path))
require.NoError(t, err)

atimeSec, atimeNsec, mtimeSec, mtimeNsec, _, _ := platform.StatTimes(stat)
atimeNsec, mtimeNsec, _ := platform.StatTimes(stat)
if platform.CompilerSupported() {
require.Equal(t, atimeSec, tc.atimeSec)
require.Equal(t, atimeNsec, tc.atimeNsec)
} // else only mtimes will return.
require.Equal(t, mtimeSec, tc.mtimeSec)
require.Equal(t, mtimeNsec, tc.mtimeNsec)
})
}
Expand Down
2 changes: 1 addition & 1 deletion internal/syscallfs/syscallfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,5 +83,5 @@ type FS interface {
// - To set wall clock time, retrieve it first from sys.Walltime.
// - syscall.UtimesNano cannot change the ctime. Also, neither WASI nor
// runtime.GOOS=js support changing it. Hence, ctime it is absent here.
Utimes(path string, atimeSec, atimeNsec, mtimeSec, mtimeNsec int64) error
Utimes(path string, atimeNsec, mtimeNsec int64) error
}

0 comments on commit 4197caa

Please sign in to comment.