1#!/usr/bin/perl 2# $OpenBSD: syscall_emulator.t,v 1.1 2023/09/03 01:43:09 afresh1 Exp $ # 3 4# Copyright (c) 2023 Andrew Hewus Fresh <afresh1@openbsd.org> 5# 6# Permission to use, copy, modify, and distribute this software for any 7# purpose with or without fee is hereby granted, provided that the above 8# copyright notice and this permission notice appear in all copies. 9# 10# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 18BEGIN { 19 chdir 't' if -d 't'; 20 require "./test.pl"; 21 set_up_inc( qw(. ../lib lib ../dist/base/lib) ); 22} 23 24use v5.36; 25 26use File::Temp; 27use POSIX qw< S_IRUSR S_IWUSR S_IRGRP S_IROTH O_CREAT O_WRONLY O_RDONLY >; 28 29use constant { 30 PROT_READ => 0x01, 31 MAP_PRIVATE => 0x0002, 32 MAP_FAILED => -1, 33}; 34 35my $dir = File::Temp->newdir("syscall_emulator-XXXXXXXXX"); 36{ 37 local $ENV{PERL5LIB} = join ':', @INC; 38 open(my $fh, '-|', $^X, "../utils/h2ph", '-d', $dir, 39 "/usr/include/sys/syscall.h") or die "h2ph: $!"; 40 note <$fh>; 41 close($fh) or die $! ? "h2ph: $!" : "h2ph: $?"; 42 local @INC = ("$dir/usr/include", "$dir"); 43 require 'sys/syscall.ph'; 44} 45 46my $filename = "test.txt"; 47my $file = "$dir/$filename"; 48my $fd; 49my $out = "Hello World\n"; 50my $in = "\0" x 32; 51my ($in_p, $in_v); 52my $sb = "\0" x 4096; 53my $st_mode; 54 55my $perms = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH; 56 57plan tests => 17; 58 59ok(! 60 (($fd = syscall(SYS_open(), $file, O_CREAT|O_WRONLY, $perms)) < 0), 61 "Opened $filename for write/create" 62); 63ok(! 64 (syscall(SYS_write(), $fd, $out, length $out) <= 0), 65 "Wrote out to $filename" 66); 67ok(! 68 (syscall(SYS_close(), $fd) != 0), 69 "closed $filename" 70); 71 72 73ok(! 74 (syscall(SYS_stat(), $file, $sb) != 0), 75 "stat $filename" 76); 77 78# fortunately st_mode is the first unsigned long in stat struct 79$st_mode = unpack "L", $sb; 80 81ok( ($st_mode & 0777) == ($perms & 0777), 82 sprintf "new file %s has correct permissions (%o)", 83 $filename, $st_mode & 0777 84); 85 86ok(! 87 (($fd = syscall(SYS_open(), $file, O_RDONLY)) < 0), 88 "Opened $filename for read" 89); 90ok(! 91 (syscall(SYS_read(), $fd, $in, length $in) <= 0), 92 "read from $filename" 93); 94 95$in = unpack 'Z*', $in; 96 97ok( length($in) == length($out) && ($in eq $out), 98 "Read written content from $filename" 99); 100 101ok(! 102 (syscall(SYS_lseek(), $fd, 0, SEEK_SET) < 0), 103 "lseek on fd" 104); 105 106ok(! 107 (syscall(SYS_pread(), $fd, $in = "\0" x 32, 5, 3) < 0), 108 "pread on fd" 109); 110 111$in = unpack 'Z*', $in; 112 113ok( length($in) == 5 && ($in eq substr $out, 3, 5), 114 "Read written content from $filename ($in)" 115); 116 117ok(! 118 (syscall(SYS_lseek(), $fd, 0, SEEK_SET) < 0), 119 "lseek on fd" 120); 121 122ok(! 123 (syscall(SYS_lseek(), $fd, 0, SEEK_SET) < 0), 124 "lseek on fd" 125); 126 127ok(! 128 (($in_p = syscall(SYS_mmap(), undef, length($out), PROT_READ, MAP_PRIVATE, 129 $fd, 0)) == MAP_FAILED), 130 "mmap fd" 131); 132 133# From ingy's Pointer module 134$in_v = unpack "p*", pack "L!", $in_p; 135 136ok( length($in_v) == length($out) && ($in_v eq $out), 137 "Read written content from $filename" 138); 139 140ok(! 141 (syscall(SYS_munmap(), $in_p, length($out)) != 0), 142 "munmap fd" 143); 144 145ok(! 146 (syscall(SYS_close(), $fd) != 0), 147 "closed $filename" 148); 149