/*-1* Copyright (C) 2025 ConnectWise, LLC. All rights reserved.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6* 1. Redistributions of source code must retain the above copyright7* notice, this list of conditions and the following disclaimer.8* 2. Redistributions in binary form must reproduce the above copyright9* notice, this list of conditions and the following disclaimer in the10* documentation and/or other materials provided with the distribution.11*12* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND13* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE14* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE15* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE16* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL17* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS18* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)19* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT20* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY21* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF22* SUCH DAMAGE.23*/2425#include <sys/exterrvar.h>26#include <sys/mman.h>2728#include <atf-c.h>29#include <errno.h>30#include <exterr.h>31#include <stdio.h>3233ATF_TC(gettext_extended);34ATF_TC_HEAD(gettext_extended, tc)35{36atf_tc_set_md_var(tc, "descr", "Retrieve an extended error message");37}38ATF_TC_BODY(gettext_extended, tc)39{40char exterr[UEXTERROR_MAXLEN];41int r;4243/*44* Use an invalid call to mmap() because it supports extended error45* messages, requires no special resources, and does not need root.46*/47ATF_CHECK_ERRNO(ENOTSUP,48mmap(NULL, 0, PROT_MAX(PROT_READ) | PROT_WRITE, 0, -1, 0));49r = uexterr_gettext(exterr, sizeof(exterr));50ATF_CHECK_EQ(0, r);51printf("Extended error: %s\n", exterr);52/* Note: error string may need to be updated due to kernel changes */53ATF_CHECK(strstr(exterr, "prot is not subset of max_prot") != 0);54}5556ATF_TC(gettext_noextended);57ATF_TC_HEAD(gettext_noextended, tc)58{59atf_tc_set_md_var(tc, "descr",60"Fail to retrieve an extended error message because none exists");61}62ATF_TC_BODY(gettext_noextended, tc)63{64char exterr[UEXTERROR_MAXLEN];65int r;6667ATF_CHECK_ERRNO(EINVAL, exterrctl(EXTERRCTL_UD, 0, NULL));68r = uexterr_gettext(exterr, sizeof(exterr));69ATF_CHECK_EQ(0, r);70ATF_CHECK_STREQ(exterr, "");71}7273ATF_TC(gettext_noextended_after_extended);74ATF_TC_HEAD(gettext_noextended_after_extended, tc)75{76atf_tc_set_md_var(tc, "descr",77"uexterr_gettext should not return a stale extended error message");78}79ATF_TC_BODY(gettext_noextended_after_extended, tc)80{81char exterr[UEXTERROR_MAXLEN];82int r;8384/*85* First do something that will create an extended error message, but86* ignore it.87*/88ATF_CHECK_ERRNO(ENOTSUP,89mmap(NULL, 0, PROT_MAX(PROT_READ) | PROT_WRITE, 0, -1, 0));9091/* Then do something that won't create an extended error message */92ATF_CHECK_ERRNO(EINVAL, exterrctl(EXTERRCTL_UD, 0, NULL));9394/* Hopefully we won't see the stale extended error message */95r = uexterr_gettext(exterr, sizeof(exterr));96ATF_CHECK_EQ(0, r);97ATF_CHECK_STREQ(exterr, "");98}99100ATF_TP_ADD_TCS(tp)101{102ATF_TP_ADD_TC(tp, gettext_extended);103ATF_TP_ADD_TC(tp, gettext_noextended);104ATF_TP_ADD_TC(tp, gettext_noextended_after_extended);105106return (atf_no_error());107}108109110