xref: /openbsd/gnu/usr.bin/perl/t/op/syscall_emulator.t (revision d415bd75)
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