Ensures 32-bit platforms build (#996)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
1
Makefile
1
Makefile
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build darwin || freebsd
|
||||
//go:build (amd64 || arm64) && (darwin || freebsd)
|
||||
|
||||
package platform
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build (amd64 || arm64) && linux
|
||||
|
||||
package platform
|
||||
|
||||
import (
|
||||
@@ -5,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.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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build (amd64 || arm64) && windows
|
||||
|
||||
package platform
|
||||
|
||||
import (
|
||||
@@ -5,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.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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"runtime"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/tetratelabs/wazero/internal/platform"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
@@ -327,21 +328,33 @@ 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},
|
||||
}
|
||||
@@ -349,26 +362,34 @@ func TestDirFS_Utimes(t *testing.T) {
|
||||
// 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)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user