mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 19:43:32 +00:00
8f522cb702
This change progresses our AARCH64 support: - The AARCH64 build and tests are now passing - Add 128-bit floating-point support to printf() - Fix clone() so it initializes cosmo's x28 TLS register - Fix TLS memory layout issue with aarch64 _Alignas vars - Revamp microbenchmarking tools so they work on aarch64 - Make some subtle improvements to aarch64 crash reporting - Make kisdangerous() memory checks more accurate on aarch64 - Remove sys_open() since it's not available on Linux AARCH64 This change makes general improvements to Cosmo and Redbean: - Introduce GetHostIsa() function in Redbean - You can now feature check using pledge(0, 0) - You can now feature check using unveil("",0) - Refactor some more x86-specific asm comments - Refactor and write docs for some libm functions - Make the mmap() API behave more similar to Linux - Fix WIFSIGNALED() which wrongly returned true for zero - Rename some obscure cosmo keywords from noFOO to dontFOO
165 lines
5 KiB
Lua
165 lines
5 KiB
Lua
-- Copyright 2022 Justine Alexandra Roberts Tunney
|
|
--
|
|
-- Permission to use, copy, modify, and/or distribute this software for
|
|
-- any purpose with or without fee is hereby granted, provided that the
|
|
-- above copyright notice and this permission notice appear in all copies.
|
|
--
|
|
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
|
-- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
|
-- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
|
-- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
|
-- DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
|
-- PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
-- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
-- PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
gotsigusr1 = false
|
|
tmpdir = "%s/o/tmp/lunix_test.%d" % {os.getenv('TMPDIR'), unix.getpid()}
|
|
|
|
function string.starts(String,Start)
|
|
return string.sub(String,1,string.len(Start))==Start
|
|
end
|
|
|
|
function OnSigUsr1(sig)
|
|
gotsigusr1 = true
|
|
end
|
|
|
|
function UnixTest()
|
|
|
|
-- strsignal
|
|
assert(unix.strsignal(9) == "SIGKILL")
|
|
assert(unix.strsignal(unix.SIGKILL) == "SIGKILL")
|
|
|
|
-- gmtime
|
|
year,mon,mday,hour,min,sec,gmtoffsec,wday,yday,dst,zone = assert(unix.gmtime(1657297063))
|
|
assert(year == 2022)
|
|
assert(mon == 7)
|
|
assert(mday == 8)
|
|
assert(hour == 16)
|
|
assert(min == 17)
|
|
assert(sec == 43)
|
|
assert(gmtoffsec == 0)
|
|
assert(wday == 5)
|
|
assert(yday == 188)
|
|
assert(dst == 0)
|
|
assert(zone == "GMT")
|
|
|
|
-- dup
|
|
-- 1. duplicate stderr as lowest available fd
|
|
-- 1. close the newly assigned file descriptor
|
|
fd = assert(unix.dup(2))
|
|
assert(unix.close(fd))
|
|
|
|
-- dup2
|
|
-- 1. duplicate stderr as fd 10
|
|
-- 1. close the new file descriptor
|
|
assert(assert(unix.dup(2, 10)) == 10)
|
|
assert(unix.close(10))
|
|
|
|
-- fork
|
|
-- basic subprocess creation
|
|
if assert(unix.fork()) == 0 then
|
|
assert(unix.pledge(""))
|
|
unix.exit(42)
|
|
end
|
|
pid, ws = assert(unix.wait())
|
|
assert(unix.WIFEXITED(ws))
|
|
assert(unix.WEXITSTATUS(ws) == 42)
|
|
|
|
-- pledge
|
|
-- 1. fork off a process
|
|
-- 2. sandbox the process
|
|
-- 3. then violate its security
|
|
if unix.pledge(nil, nil) then
|
|
reader, writer = assert(unix.pipe())
|
|
if assert(unix.fork()) == 0 then
|
|
assert(unix.dup(writer, 2))
|
|
assert(unix.pledge("stdio"))
|
|
unix.socket()
|
|
unix.exit(0)
|
|
end
|
|
unix.close(writer)
|
|
unix.close(reader)
|
|
pid, ws = assert(unix.wait())
|
|
assert(unix.WIFSIGNALED(ws))
|
|
assert(unix.WTERMSIG(ws) == unix.SIGSYS or -- Linux
|
|
unix.WTERMSIG(ws) == unix.SIGABRT) -- OpenBSD
|
|
end
|
|
|
|
-- sigaction
|
|
-- 1. install a signal handler for USR1
|
|
-- 2. block USR1
|
|
-- 3. trigger USR1 signal [it gets enqueued]
|
|
-- 4. pause() w/ atomic unblocking of USR1 [now it gets delivered!]
|
|
-- 5. restore old signal mask
|
|
-- 6. restore old sig handler
|
|
oldhand, oldflags, oldmask = assert(unix.sigaction(unix.SIGUSR1, OnSigUsr1))
|
|
oldmask = assert(unix.sigprocmask(unix.SIG_BLOCK, unix.Sigset(unix.SIGUSR1)))
|
|
assert(unix.raise(unix.SIGUSR1))
|
|
assert(not gotsigusr1)
|
|
ok, err = unix.sigsuspend(oldmask)
|
|
assert(not ok)
|
|
assert(err:errno() == unix.EINTR)
|
|
assert(gotsigusr1)
|
|
assert(unix.sigprocmask(unix.SIG_SETMASK, oldmask))
|
|
assert(unix.sigaction(unix.SIGUSR1, oldhand, oldflags, oldmask))
|
|
|
|
-- open
|
|
-- 1. create file
|
|
-- 2. fill it up
|
|
-- 3. inspect it
|
|
-- 4. mess with it
|
|
fd = assert(unix.open("%s/foo" % {tmpdir}, unix.O_RDWR | unix.O_CREAT | unix.O_TRUNC, 0600))
|
|
assert(assert(unix.fstat(fd)):size() == 0)
|
|
assert(unix.ftruncate(fd, 8192))
|
|
assert(assert(unix.fstat(fd)):size() == 8192)
|
|
assert(unix.write(fd, "hello"))
|
|
assert(unix.lseek(fd, 4096))
|
|
assert(unix.write(fd, "poke"))
|
|
assert(unix.lseek(fd, 8192-4))
|
|
assert(unix.write(fd, "poke"))
|
|
st = assert(unix.fstat(fd))
|
|
assert(st:size() == 8192)
|
|
assert(st:blocks() == 8192/512)
|
|
assert((st:mode() & 0777) == 0600)
|
|
assert(st:uid() == unix.getuid())
|
|
assert(st:gid() == unix.getgid())
|
|
assert(unix.write(fd, "bear", 4))
|
|
assert(unix.read(fd, 10, 0) == "hellbear\x00\x00")
|
|
assert(unix.close(fd))
|
|
fd = assert(unix.open("%s/foo" % {tmpdir}))
|
|
assert(unix.lseek(fd, 4))
|
|
assert(unix.read(fd, 4) == "bear")
|
|
assert(unix.close(fd))
|
|
fd = assert(unix.open("%s/foo" % {tmpdir}, unix.O_RDWR))
|
|
assert(unix.write(fd, "bear"))
|
|
assert(unix.close(fd))
|
|
fd = assert(unix.open("%s/foo" % {tmpdir}))
|
|
assert(unix.read(fd, 8) == "bearbear")
|
|
assert(unix.close(fd))
|
|
|
|
-- getdents
|
|
t = {}
|
|
for name, kind, ino, off in assert(unix.opendir(tmpdir)) do
|
|
table.insert(t, name)
|
|
end
|
|
table.sort(t)
|
|
assert(EncodeLua(t) == '{".", "..", "foo"}');
|
|
|
|
end
|
|
|
|
function main()
|
|
assert(unix.makedirs(tmpdir))
|
|
unix.unveil(tmpdir, "rwc")
|
|
unix.unveil(nil, nil)
|
|
assert(unix.pledge("stdio rpath wpath cpath proc"))
|
|
ok, err = pcall(UnixTest)
|
|
if ok then
|
|
assert(unix.rmrf(tmpdir))
|
|
else
|
|
print(err)
|
|
error('UnixTest failed (%s)' % {tmpdir})
|
|
end
|
|
end
|
|
|
|
main()
|