xref: /freebsd/tests/sys/posixshm/posixshm_test.c (revision 4f77551258012a4eb53a992c75fa96dc3c3313e4)
14fdc3d75SEnji Cooper /*-
24fdc3d75SEnji Cooper  * Copyright (c) 2006 Robert N. M. Watson
34fdc3d75SEnji Cooper  * All rights reserved.
44fdc3d75SEnji Cooper  *
54fdc3d75SEnji Cooper  * Redistribution and use in source and binary forms, with or without
64fdc3d75SEnji Cooper  * modification, are permitted provided that the following conditions
74fdc3d75SEnji Cooper  * are met:
84fdc3d75SEnji Cooper  * 1. Redistributions of source code must retain the above copyright
94fdc3d75SEnji Cooper  *    notice, this list of conditions and the following disclaimer.
104fdc3d75SEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
114fdc3d75SEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
124fdc3d75SEnji Cooper  *    documentation and/or other materials provided with the distribution.
134fdc3d75SEnji Cooper  *
144fdc3d75SEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
154fdc3d75SEnji Cooper  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
164fdc3d75SEnji Cooper  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
174fdc3d75SEnji Cooper  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
184fdc3d75SEnji Cooper  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
194fdc3d75SEnji Cooper  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
204fdc3d75SEnji Cooper  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
214fdc3d75SEnji Cooper  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
224fdc3d75SEnji Cooper  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
234fdc3d75SEnji Cooper  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
244fdc3d75SEnji Cooper  * SUCH DAMAGE.
254fdc3d75SEnji Cooper  */
264fdc3d75SEnji Cooper 
274fdc3d75SEnji Cooper #include <sys/cdefs.h>
284fdc3d75SEnji Cooper __FBSDID("$FreeBSD$");
294fdc3d75SEnji Cooper 
304fdc3d75SEnji Cooper #include <sys/param.h>
314fdc3d75SEnji Cooper #include <sys/mman.h>
324fdc3d75SEnji Cooper #include <sys/resource.h>
334fdc3d75SEnji Cooper #include <sys/stat.h>
344fdc3d75SEnji Cooper #include <sys/syscall.h>
354fdc3d75SEnji Cooper #include <sys/wait.h>
364fdc3d75SEnji Cooper 
379afb12baSDavid Bright #include <ctype.h>
384fdc3d75SEnji Cooper #include <errno.h>
394fdc3d75SEnji Cooper #include <fcntl.h>
404fdc3d75SEnji Cooper #include <signal.h>
414fdc3d75SEnji Cooper #include <stdio.h>
424fdc3d75SEnji Cooper #include <stdlib.h>
434fdc3d75SEnji Cooper #include <string.h>
444fdc3d75SEnji Cooper #include <unistd.h>
454fdc3d75SEnji Cooper 
464fdc3d75SEnji Cooper #include <atf-c.h>
474fdc3d75SEnji Cooper 
484fdc3d75SEnji Cooper #define	TEST_PATH_LEN	256
494fdc3d75SEnji Cooper static char test_path[TEST_PATH_LEN];
509afb12baSDavid Bright static char test_path2[TEST_PATH_LEN];
519afb12baSDavid Bright static unsigned int test_path_idx = 0;
529afb12baSDavid Bright 
539afb12baSDavid Bright static void
549afb12baSDavid Bright gen_a_test_path(char *path)
559afb12baSDavid Bright {
569afb12baSDavid Bright 	snprintf(path, TEST_PATH_LEN, "%s/tmp.XXXXXX%d",
579afb12baSDavid Bright 	    getenv("TMPDIR") == NULL ? "/tmp" : getenv("TMPDIR"),
589afb12baSDavid Bright 	    test_path_idx);
599afb12baSDavid Bright 
609afb12baSDavid Bright 	test_path_idx++;
619afb12baSDavid Bright 
629afb12baSDavid Bright 	ATF_REQUIRE_MSG(mkstemp(path) != -1,
639afb12baSDavid Bright 	    "mkstemp failed; errno=%d", errno);
649afb12baSDavid Bright 	ATF_REQUIRE_MSG(unlink(path) == 0,
659afb12baSDavid Bright 	    "unlink failed; errno=%d", errno);
669afb12baSDavid Bright }
674fdc3d75SEnji Cooper 
684fdc3d75SEnji Cooper static void
694fdc3d75SEnji Cooper gen_test_path(void)
704fdc3d75SEnji Cooper {
719afb12baSDavid Bright 	gen_a_test_path(test_path);
729afb12baSDavid Bright }
734fdc3d75SEnji Cooper 
749afb12baSDavid Bright static void
759afb12baSDavid Bright gen_test_path2(void)
769afb12baSDavid Bright {
779afb12baSDavid Bright 	gen_a_test_path(test_path2);
784fdc3d75SEnji Cooper }
794fdc3d75SEnji Cooper 
804fdc3d75SEnji Cooper /*
814fdc3d75SEnji Cooper  * Attempt a shm_open() that should fail with an expected error of 'error'.
824fdc3d75SEnji Cooper  */
834fdc3d75SEnji Cooper static void
844fdc3d75SEnji Cooper shm_open_should_fail(const char *path, int flags, mode_t mode, int error)
854fdc3d75SEnji Cooper {
864fdc3d75SEnji Cooper 	int fd;
874fdc3d75SEnji Cooper 
884fdc3d75SEnji Cooper 	fd = shm_open(path, flags, mode);
894fdc3d75SEnji Cooper 	ATF_CHECK_MSG(fd == -1, "shm_open didn't fail");
904fdc3d75SEnji Cooper 	ATF_CHECK_MSG(error == errno,
914fdc3d75SEnji Cooper 	    "shm_open didn't fail with expected errno; errno=%d; expected "
924fdc3d75SEnji Cooper 	    "errno=%d", errno, error);
934fdc3d75SEnji Cooper }
944fdc3d75SEnji Cooper 
954fdc3d75SEnji Cooper /*
964fdc3d75SEnji Cooper  * Attempt a shm_unlink() that should fail with an expected error of 'error'.
974fdc3d75SEnji Cooper  */
984fdc3d75SEnji Cooper static void
994fdc3d75SEnji Cooper shm_unlink_should_fail(const char *path, int error)
1004fdc3d75SEnji Cooper {
1014fdc3d75SEnji Cooper 
1024fdc3d75SEnji Cooper 	ATF_CHECK_MSG(shm_unlink(path) == -1, "shm_unlink didn't fail");
1034fdc3d75SEnji Cooper 	ATF_CHECK_MSG(error == errno,
1044fdc3d75SEnji Cooper 	    "shm_unlink didn't fail with expected errno; errno=%d; expected "
1054fdc3d75SEnji Cooper 	    "errno=%d", errno, error);
1064fdc3d75SEnji Cooper }
1074fdc3d75SEnji Cooper 
1084fdc3d75SEnji Cooper /*
1099afb12baSDavid Bright  * Open the test object and write a value to the first byte.  Returns valid fd
1104fdc3d75SEnji Cooper  * on success and -1 on failure.
1114fdc3d75SEnji Cooper  */
1124fdc3d75SEnji Cooper static int
1139afb12baSDavid Bright scribble_object(const char *path, char value)
1144fdc3d75SEnji Cooper {
1154fdc3d75SEnji Cooper 	char *page;
11694ebd6f5SEnji Cooper 	int fd, pagesize;
1174fdc3d75SEnji Cooper 
11894ebd6f5SEnji Cooper 	ATF_REQUIRE(0 < (pagesize = getpagesize()));
11994ebd6f5SEnji Cooper 
1209afb12baSDavid Bright 	fd = shm_open(path, O_CREAT|O_EXCL|O_RDWR, 0777);
1214fdc3d75SEnji Cooper 	if (fd < 0 && errno == EEXIST) {
1224fdc3d75SEnji Cooper 		if (shm_unlink(test_path) < 0)
1234fdc3d75SEnji Cooper 			atf_tc_fail("shm_unlink");
1244fdc3d75SEnji Cooper 		fd = shm_open(test_path, O_CREAT | O_EXCL | O_RDWR, 0777);
1254fdc3d75SEnji Cooper 	}
1264fdc3d75SEnji Cooper 	if (fd < 0)
1274fdc3d75SEnji Cooper 		atf_tc_fail("shm_open failed; errno=%d", errno);
12894ebd6f5SEnji Cooper 	if (ftruncate(fd, pagesize) < 0)
1294fdc3d75SEnji Cooper 		atf_tc_fail("ftruncate failed; errno=%d", errno);
1304fdc3d75SEnji Cooper 
13194ebd6f5SEnji Cooper 	page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1324fdc3d75SEnji Cooper 	if (page == MAP_FAILED)
1334fdc3d75SEnji Cooper 		atf_tc_fail("mmap failed; errno=%d", errno);
1344fdc3d75SEnji Cooper 
1359afb12baSDavid Bright 	page[0] = value;
13694ebd6f5SEnji Cooper 	ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",
13794ebd6f5SEnji Cooper 	    errno);
1384fdc3d75SEnji Cooper 
1394fdc3d75SEnji Cooper 	return (fd);
1404fdc3d75SEnji Cooper }
1414fdc3d75SEnji Cooper 
1429afb12baSDavid Bright /*
1439afb12baSDavid Bright  * Fail the test case if the 'path' does not refer to an shm whose first byte
1449afb12baSDavid Bright  * is equal to expected_value
1459afb12baSDavid Bright  */
1469afb12baSDavid Bright static void
1479afb12baSDavid Bright verify_object(const char *path, char expected_value)
1489afb12baSDavid Bright {
1499afb12baSDavid Bright 	int fd;
1509afb12baSDavid Bright 	int pagesize;
1519afb12baSDavid Bright 	char *page;
1529afb12baSDavid Bright 
1539afb12baSDavid Bright 	ATF_REQUIRE(0 < (pagesize = getpagesize()));
1549afb12baSDavid Bright 
1559afb12baSDavid Bright 	fd = shm_open(path, O_RDONLY, 0777);
1569afb12baSDavid Bright 	if (fd < 0)
1579afb12baSDavid Bright 		atf_tc_fail("shm_open failed in verify_object; errno=%d, path=%s",
1589afb12baSDavid Bright 		    errno, path);
1599afb12baSDavid Bright 
1609afb12baSDavid Bright 	page = mmap(0, pagesize, PROT_READ, MAP_SHARED, fd, 0);
1619afb12baSDavid Bright 	if (page == MAP_FAILED)
1629afb12baSDavid Bright 		atf_tc_fail("mmap(1)");
1639afb12baSDavid Bright 	if (page[0] != expected_value)
1649afb12baSDavid Bright 		atf_tc_fail("Renamed object has incorrect value; has"
1659afb12baSDavid Bright 		    "%d (0x%x, '%c'), expected %d (0x%x, '%c')\n",
1669afb12baSDavid Bright 		    page[0], page[0], isprint(page[0]) ? page[0] : ' ',
1679afb12baSDavid Bright 		    expected_value, expected_value,
1689afb12baSDavid Bright 		    isprint(expected_value) ? expected_value : ' ');
1699afb12baSDavid Bright 	ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",
1709afb12baSDavid Bright 	    errno);
1719afb12baSDavid Bright 	close(fd);
1729afb12baSDavid Bright }
1739afb12baSDavid Bright 
1744fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(remap_object);
1754fdc3d75SEnji Cooper ATF_TC_BODY(remap_object, tc)
1764fdc3d75SEnji Cooper {
1774fdc3d75SEnji Cooper 	char *page;
17894ebd6f5SEnji Cooper 	int fd, pagesize;
17994ebd6f5SEnji Cooper 
18094ebd6f5SEnji Cooper 	ATF_REQUIRE(0 < (pagesize = getpagesize()));
1814fdc3d75SEnji Cooper 
1829afb12baSDavid Bright 	gen_test_path();
1839afb12baSDavid Bright 	fd = scribble_object(test_path, '1');
1844fdc3d75SEnji Cooper 
18594ebd6f5SEnji Cooper 	page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1864fdc3d75SEnji Cooper 	if (page == MAP_FAILED)
1874fdc3d75SEnji Cooper 		atf_tc_fail("mmap(2) failed; errno=%d", errno);
1884fdc3d75SEnji Cooper 
1894fdc3d75SEnji Cooper 	if (page[0] != '1')
1904fdc3d75SEnji Cooper 		atf_tc_fail("missing data ('%c' != '1')", page[0]);
1914fdc3d75SEnji Cooper 
1924fdc3d75SEnji Cooper 	close(fd);
19394ebd6f5SEnji Cooper 	ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",
19494ebd6f5SEnji Cooper 	    errno);
1954fdc3d75SEnji Cooper 
1964fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,
1974fdc3d75SEnji Cooper 	    "shm_unlink failed; errno=%d", errno);
1984fdc3d75SEnji Cooper }
1994fdc3d75SEnji Cooper 
2009afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_from_anon);
2019afb12baSDavid Bright ATF_TC_BODY(rename_from_anon, tc)
2029afb12baSDavid Bright {
2039afb12baSDavid Bright 	int rc;
2049afb12baSDavid Bright 
2059afb12baSDavid Bright 	gen_test_path();
2069afb12baSDavid Bright 	rc = shm_rename(SHM_ANON, test_path, 0);
2079afb12baSDavid Bright 	if (rc != -1)
2089afb12baSDavid Bright 		atf_tc_fail("shm_rename from SHM_ANON succeeded unexpectedly");
2099afb12baSDavid Bright }
2109afb12baSDavid Bright 
2119afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_bad_path_pointer);
2129afb12baSDavid Bright ATF_TC_BODY(rename_bad_path_pointer, tc)
2139afb12baSDavid Bright {
2149afb12baSDavid Bright 	const char *bad_path;
2159afb12baSDavid Bright 	int rc;
2169afb12baSDavid Bright 
2179afb12baSDavid Bright 	bad_path = (const char *)0x1;
2189afb12baSDavid Bright 
2199afb12baSDavid Bright 	gen_test_path();
2209afb12baSDavid Bright 	rc = shm_rename(test_path, bad_path, 0);
2219afb12baSDavid Bright 	if (rc != -1)
2229afb12baSDavid Bright 		atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly");
2239afb12baSDavid Bright 
2249afb12baSDavid Bright 	rc = shm_rename(bad_path, test_path, 0);
2259afb12baSDavid Bright 	if (rc != -1)
2269afb12baSDavid Bright 		atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly");
2279afb12baSDavid Bright }
2289afb12baSDavid Bright 
2299afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_from_nonexisting);
2309afb12baSDavid Bright ATF_TC_BODY(rename_from_nonexisting, tc)
2319afb12baSDavid Bright {
2329afb12baSDavid Bright 	int rc;
2339afb12baSDavid Bright 
2349afb12baSDavid Bright 	gen_test_path();
2359afb12baSDavid Bright 	rc = shm_rename(test_path, test_path2, 0);
2369afb12baSDavid Bright 	if (rc != -1)
2379afb12baSDavid Bright 		atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly");
2389afb12baSDavid Bright 
2399afb12baSDavid Bright 	if (errno != ENOENT)
2409afb12baSDavid Bright 		atf_tc_fail("Expected ENOENT to rename of nonexistent shm");
2419afb12baSDavid Bright }
2429afb12baSDavid Bright 
2439afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_anon);
2449afb12baSDavid Bright ATF_TC_BODY(rename_to_anon, tc)
2459afb12baSDavid Bright {
2469afb12baSDavid Bright 	int rc;
2479afb12baSDavid Bright 
2489afb12baSDavid Bright 	gen_test_path();
2499afb12baSDavid Bright 	rc = shm_rename(test_path, SHM_ANON, 0);
2509afb12baSDavid Bright 	if (rc != -1)
2519afb12baSDavid Bright 		atf_tc_fail("shm_rename to SHM_ANON succeeded unexpectedly");
2529afb12baSDavid Bright }
2539afb12baSDavid Bright 
2549afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_replace);
2559afb12baSDavid Bright ATF_TC_BODY(rename_to_replace, tc)
2569afb12baSDavid Bright {
2579afb12baSDavid Bright 	char expected_value;
2589afb12baSDavid Bright 	int fd;
2599afb12baSDavid Bright 	int fd2;
2609afb12baSDavid Bright 
2619afb12baSDavid Bright 	// Some contents we can verify later
2629afb12baSDavid Bright 	expected_value = 'g';
2639afb12baSDavid Bright 
2649afb12baSDavid Bright 	gen_test_path();
2659afb12baSDavid Bright 	fd = scribble_object(test_path, expected_value);
2669afb12baSDavid Bright 	close(fd);
2679afb12baSDavid Bright 
2689afb12baSDavid Bright 	// Give the other some different value so we can detect success
2699afb12baSDavid Bright 	gen_test_path2();
2709afb12baSDavid Bright 	fd2 = scribble_object(test_path2, 'h');
2719afb12baSDavid Bright 	close(fd2);
2729afb12baSDavid Bright 
2739afb12baSDavid Bright 	ATF_REQUIRE_MSG(shm_rename(test_path, test_path2, 0) == 0,
2749afb12baSDavid Bright 	    "shm_rename failed; errno=%d", errno);
2759afb12baSDavid Bright 
2769afb12baSDavid Bright 	// Read back renamed; verify contents
2779afb12baSDavid Bright 	verify_object(test_path2, expected_value);
2789afb12baSDavid Bright }
2799afb12baSDavid Bright 
2809afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_noreplace);
2819afb12baSDavid Bright ATF_TC_BODY(rename_to_noreplace, tc)
2829afb12baSDavid Bright {
2839afb12baSDavid Bright 	char expected_value_from;
2849afb12baSDavid Bright 	char expected_value_to;
2859afb12baSDavid Bright 	int fd_from;
2869afb12baSDavid Bright 	int fd_to;
2879afb12baSDavid Bright 	int rc;
2889afb12baSDavid Bright 
2899afb12baSDavid Bright 	// Some contents we can verify later
2909afb12baSDavid Bright 	expected_value_from = 'g';
2919afb12baSDavid Bright 	gen_test_path();
2929afb12baSDavid Bright 	fd_from = scribble_object(test_path, expected_value_from);
2939afb12baSDavid Bright 	close(fd_from);
2949afb12baSDavid Bright 
2959afb12baSDavid Bright 	// Give the other some different value so we can detect success
2969afb12baSDavid Bright 	expected_value_to = 'h';
2979afb12baSDavid Bright 	gen_test_path2();
2989afb12baSDavid Bright 	fd_to = scribble_object(test_path2, expected_value_to);
2999afb12baSDavid Bright 	close(fd_to);
3009afb12baSDavid Bright 
3019afb12baSDavid Bright 	rc = shm_rename(test_path, test_path2, SHM_RENAME_NOREPLACE);
3029afb12baSDavid Bright 	ATF_REQUIRE_MSG((rc == -1) && (errno == EEXIST),
3039afb12baSDavid Bright 	    "shm_rename didn't fail as expected; errno: %d; return: %d", errno,
3049afb12baSDavid Bright 	    rc);
3059afb12baSDavid Bright 
3069afb12baSDavid Bright 	// Read back renamed; verify contents
3079afb12baSDavid Bright 	verify_object(test_path2, expected_value_to);
3089afb12baSDavid Bright }
3099afb12baSDavid Bright 
3109afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_exchange);
3119afb12baSDavid Bright ATF_TC_BODY(rename_to_exchange, tc)
3129afb12baSDavid Bright {
3139afb12baSDavid Bright 	char expected_value_from;
3149afb12baSDavid Bright 	char expected_value_to;
3159afb12baSDavid Bright 	int fd_from;
3169afb12baSDavid Bright 	int fd_to;
3179afb12baSDavid Bright 
3189afb12baSDavid Bright 	// Some contents we can verify later
3199afb12baSDavid Bright 	expected_value_from = 'g';
3209afb12baSDavid Bright 	gen_test_path();
3219afb12baSDavid Bright 	fd_from = scribble_object(test_path, expected_value_from);
3229afb12baSDavid Bright 	close(fd_from);
3239afb12baSDavid Bright 
3249afb12baSDavid Bright 	// Give the other some different value so we can detect success
3259afb12baSDavid Bright 	expected_value_to = 'h';
3269afb12baSDavid Bright 	gen_test_path2();
3279afb12baSDavid Bright 	fd_to = scribble_object(test_path2, expected_value_to);
3289afb12baSDavid Bright 	close(fd_to);
3299afb12baSDavid Bright 
3309afb12baSDavid Bright 	ATF_REQUIRE_MSG(shm_rename(test_path, test_path2,
3319afb12baSDavid Bright 	    SHM_RENAME_EXCHANGE) == 0,
3329afb12baSDavid Bright 	    "shm_rename failed; errno=%d", errno);
3339afb12baSDavid Bright 
3349afb12baSDavid Bright 	// Read back renamed; verify contents
3359afb12baSDavid Bright 	verify_object(test_path, expected_value_to);
3369afb12baSDavid Bright 	verify_object(test_path2, expected_value_from);
3379afb12baSDavid Bright }
3389afb12baSDavid Bright 
3399afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_exchange_nonexisting);
3409afb12baSDavid Bright ATF_TC_BODY(rename_to_exchange_nonexisting, tc)
3419afb12baSDavid Bright {
3429afb12baSDavid Bright 	char expected_value_from;
3439afb12baSDavid Bright 	int fd_from;
3449afb12baSDavid Bright 
3459afb12baSDavid Bright 	// Some contents we can verify later
3469afb12baSDavid Bright 	expected_value_from = 'g';
3479afb12baSDavid Bright 	gen_test_path();
3489afb12baSDavid Bright 	fd_from = scribble_object(test_path, expected_value_from);
3499afb12baSDavid Bright 	close(fd_from);
3509afb12baSDavid Bright 
3519afb12baSDavid Bright 	gen_test_path2();
3529afb12baSDavid Bright 
3539afb12baSDavid Bright 	ATF_REQUIRE_MSG(shm_rename(test_path, test_path2,
3549afb12baSDavid Bright 	    SHM_RENAME_EXCHANGE) == 0,
3559afb12baSDavid Bright 	    "shm_rename failed; errno=%d", errno);
3569afb12baSDavid Bright 
3579afb12baSDavid Bright 	// Read back renamed; verify contents
3589afb12baSDavid Bright 	verify_object(test_path2, expected_value_from);
3599afb12baSDavid Bright }
3609afb12baSDavid Bright 
3619afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_self);
3629afb12baSDavid Bright ATF_TC_BODY(rename_to_self, tc)
3639afb12baSDavid Bright {
3649afb12baSDavid Bright 	int fd;
3659afb12baSDavid Bright 	char expected_value;
3669afb12baSDavid Bright 
3679afb12baSDavid Bright 	expected_value = 't';
3689afb12baSDavid Bright 
3699afb12baSDavid Bright 	gen_test_path();
3709afb12baSDavid Bright 	fd = scribble_object(test_path, expected_value);
3719afb12baSDavid Bright 	close(fd);
3729afb12baSDavid Bright 
3739afb12baSDavid Bright 	ATF_REQUIRE_MSG(shm_rename(test_path, test_path, 0) == 0,
3749afb12baSDavid Bright 	    "shm_rename failed; errno=%d", errno);
3759afb12baSDavid Bright 
3769afb12baSDavid Bright 	verify_object(test_path, expected_value);
3779afb12baSDavid Bright }
3789afb12baSDavid Bright 
3799afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_bad_flag);
3809afb12baSDavid Bright ATF_TC_BODY(rename_bad_flag, tc)
3819afb12baSDavid Bright {
3829afb12baSDavid Bright 	int fd;
3839afb12baSDavid Bright 	int rc;
3849afb12baSDavid Bright 
3859afb12baSDavid Bright 	/* Make sure we don't fail out due to ENOENT */
3869afb12baSDavid Bright 	gen_test_path();
3879afb12baSDavid Bright 	gen_test_path2();
3889afb12baSDavid Bright 	fd = scribble_object(test_path, 'd');
3899afb12baSDavid Bright 	close(fd);
3909afb12baSDavid Bright 	fd = scribble_object(test_path2, 'd');
3919afb12baSDavid Bright 	close(fd);
3929afb12baSDavid Bright 
3939afb12baSDavid Bright 	/*
3949afb12baSDavid Bright 	 * Note: if we end up with enough flags that we use all the bits,
3959afb12baSDavid Bright 	 * then remove this test completely.
3969afb12baSDavid Bright 	 */
3979afb12baSDavid Bright 	rc = shm_rename(test_path, test_path2, INT_MIN);
3989afb12baSDavid Bright 	ATF_REQUIRE_MSG((rc == -1) && (errno == EINVAL),
3999afb12baSDavid Bright 	    "shm_rename should have failed with EINVAL; got: return=%d, "
4009afb12baSDavid Bright 	    "errno=%d", rc, errno);
4019afb12baSDavid Bright }
4029afb12baSDavid Bright 
4034fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(reopen_object);
4044fdc3d75SEnji Cooper ATF_TC_BODY(reopen_object, tc)
4054fdc3d75SEnji Cooper {
4064fdc3d75SEnji Cooper 	char *page;
40794ebd6f5SEnji Cooper 	int fd, pagesize;
40894ebd6f5SEnji Cooper 
40994ebd6f5SEnji Cooper 	ATF_REQUIRE(0 < (pagesize = getpagesize()));
4104fdc3d75SEnji Cooper 
4119afb12baSDavid Bright 	gen_test_path();
4129afb12baSDavid Bright 	fd = scribble_object(test_path, '1');
4134fdc3d75SEnji Cooper 	close(fd);
4144fdc3d75SEnji Cooper 
4154fdc3d75SEnji Cooper 	fd = shm_open(test_path, O_RDONLY, 0777);
4164fdc3d75SEnji Cooper 	if (fd < 0)
4174fdc3d75SEnji Cooper 		atf_tc_fail("shm_open(2) failed; errno=%d", errno);
4184fdc3d75SEnji Cooper 
41994ebd6f5SEnji Cooper 	page = mmap(0, pagesize, PROT_READ, MAP_SHARED, fd, 0);
4204fdc3d75SEnji Cooper 	if (page == MAP_FAILED)
4214fdc3d75SEnji Cooper 		atf_tc_fail("mmap(2) failed; errno=%d", errno);
4224fdc3d75SEnji Cooper 
4234fdc3d75SEnji Cooper 	if (page[0] != '1')
4244fdc3d75SEnji Cooper 		atf_tc_fail("missing data ('%c' != '1')", page[0]);
4254fdc3d75SEnji Cooper 
42694ebd6f5SEnji Cooper 	ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",
42794ebd6f5SEnji Cooper 	    errno);
4284fdc3d75SEnji Cooper 	close(fd);
4294fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,
4304fdc3d75SEnji Cooper 	    "shm_unlink failed; errno=%d", errno);
4314fdc3d75SEnji Cooper }
4324fdc3d75SEnji Cooper 
4334fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(readonly_mmap_write);
4344fdc3d75SEnji Cooper ATF_TC_BODY(readonly_mmap_write, tc)
4354fdc3d75SEnji Cooper {
4364fdc3d75SEnji Cooper 	char *page;
43794ebd6f5SEnji Cooper 	int fd, pagesize;
43894ebd6f5SEnji Cooper 
43994ebd6f5SEnji Cooper 	ATF_REQUIRE(0 < (pagesize = getpagesize()));
4404fdc3d75SEnji Cooper 
4414fdc3d75SEnji Cooper 	gen_test_path();
4424fdc3d75SEnji Cooper 
4434fdc3d75SEnji Cooper 	fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777);
4444fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
4454fdc3d75SEnji Cooper 
4464fdc3d75SEnji Cooper 	/* PROT_WRITE should fail with EACCES. */
44794ebd6f5SEnji Cooper 	page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
4484fdc3d75SEnji Cooper 	if (page != MAP_FAILED)
4494fdc3d75SEnji Cooper 		atf_tc_fail("mmap(PROT_WRITE) succeeded unexpectedly");
4504fdc3d75SEnji Cooper 
4514fdc3d75SEnji Cooper 	if (errno != EACCES)
4524fdc3d75SEnji Cooper 		atf_tc_fail("mmap(PROT_WRITE) didn't fail with EACCES; "
4534fdc3d75SEnji Cooper 		    "errno=%d", errno);
4544fdc3d75SEnji Cooper 
4554fdc3d75SEnji Cooper 	close(fd);
4564fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,
4574fdc3d75SEnji Cooper 	    "shm_unlink failed; errno=%d", errno);
4584fdc3d75SEnji Cooper }
4594fdc3d75SEnji Cooper 
4604fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_after_link);
4614fdc3d75SEnji Cooper ATF_TC_BODY(open_after_link, tc)
4624fdc3d75SEnji Cooper {
4634fdc3d75SEnji Cooper 	int fd;
4644fdc3d75SEnji Cooper 
4654fdc3d75SEnji Cooper 	gen_test_path();
4664fdc3d75SEnji Cooper 
4674fdc3d75SEnji Cooper 	fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777);
4684fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno);
4694fdc3d75SEnji Cooper 	close(fd);
4704fdc3d75SEnji Cooper 
4714fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, "shm_unlink failed: %d",
4724fdc3d75SEnji Cooper 	    errno);
4734fdc3d75SEnji Cooper 
4744fdc3d75SEnji Cooper 	shm_open_should_fail(test_path, O_RDONLY, 0777, ENOENT);
4754fdc3d75SEnji Cooper }
4764fdc3d75SEnji Cooper 
4774fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_invalid_path);
4784fdc3d75SEnji Cooper ATF_TC_BODY(open_invalid_path, tc)
4794fdc3d75SEnji Cooper {
4804fdc3d75SEnji Cooper 
4814fdc3d75SEnji Cooper 	shm_open_should_fail("blah", O_RDONLY, 0777, EINVAL);
4824fdc3d75SEnji Cooper }
4834fdc3d75SEnji Cooper 
4844fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_write_only);
4854fdc3d75SEnji Cooper ATF_TC_BODY(open_write_only, tc)
4864fdc3d75SEnji Cooper {
4874fdc3d75SEnji Cooper 
4884fdc3d75SEnji Cooper 	gen_test_path();
4894fdc3d75SEnji Cooper 
4904fdc3d75SEnji Cooper 	shm_open_should_fail(test_path, O_WRONLY, 0777, EINVAL);
4914fdc3d75SEnji Cooper }
4924fdc3d75SEnji Cooper 
4934fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_extra_flags);
4944fdc3d75SEnji Cooper ATF_TC_BODY(open_extra_flags, tc)
4954fdc3d75SEnji Cooper {
4964fdc3d75SEnji Cooper 
4974fdc3d75SEnji Cooper 	gen_test_path();
4984fdc3d75SEnji Cooper 
4994fdc3d75SEnji Cooper 	shm_open_should_fail(test_path, O_RDONLY | O_DIRECT, 0777, EINVAL);
5004fdc3d75SEnji Cooper }
5014fdc3d75SEnji Cooper 
5024fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_anon);
5034fdc3d75SEnji Cooper ATF_TC_BODY(open_anon, tc)
5044fdc3d75SEnji Cooper {
5054fdc3d75SEnji Cooper 	int fd;
5064fdc3d75SEnji Cooper 
5074fdc3d75SEnji Cooper 	fd = shm_open(SHM_ANON, O_RDWR, 0777);
5084fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
5094fdc3d75SEnji Cooper 	close(fd);
5104fdc3d75SEnji Cooper }
5114fdc3d75SEnji Cooper 
5124fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_anon_readonly);
5134fdc3d75SEnji Cooper ATF_TC_BODY(open_anon_readonly, tc)
5144fdc3d75SEnji Cooper {
5154fdc3d75SEnji Cooper 
5164fdc3d75SEnji Cooper 	shm_open_should_fail(SHM_ANON, O_RDONLY, 0777, EINVAL);
5174fdc3d75SEnji Cooper }
5184fdc3d75SEnji Cooper 
5194fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_bad_path_pointer);
5204fdc3d75SEnji Cooper ATF_TC_BODY(open_bad_path_pointer, tc)
5214fdc3d75SEnji Cooper {
5224fdc3d75SEnji Cooper 
5234fdc3d75SEnji Cooper 	shm_open_should_fail((char *)1024, O_RDONLY, 0777, EFAULT);
5244fdc3d75SEnji Cooper }
5254fdc3d75SEnji Cooper 
5264fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_path_too_long);
5274fdc3d75SEnji Cooper ATF_TC_BODY(open_path_too_long, tc)
5284fdc3d75SEnji Cooper {
5294fdc3d75SEnji Cooper 	char *page;
5304fdc3d75SEnji Cooper 
5314fdc3d75SEnji Cooper 	page = malloc(MAXPATHLEN + 1);
5324fdc3d75SEnji Cooper 	memset(page, 'a', MAXPATHLEN);
5334fdc3d75SEnji Cooper 	page[MAXPATHLEN] = '\0';
5344fdc3d75SEnji Cooper 	shm_open_should_fail(page, O_RDONLY, 0777, ENAMETOOLONG);
5354fdc3d75SEnji Cooper 	free(page);
5364fdc3d75SEnji Cooper }
5374fdc3d75SEnji Cooper 
5384fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_nonexisting_object);
5394fdc3d75SEnji Cooper ATF_TC_BODY(open_nonexisting_object, tc)
5404fdc3d75SEnji Cooper {
5414fdc3d75SEnji Cooper 
5424fdc3d75SEnji Cooper 	shm_open_should_fail("/notreallythere", O_RDONLY, 0777, ENOENT);
5434fdc3d75SEnji Cooper }
5444fdc3d75SEnji Cooper 
5454fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_create_existing_object);
5464fdc3d75SEnji Cooper ATF_TC_BODY(open_create_existing_object, tc)
5474fdc3d75SEnji Cooper {
5484fdc3d75SEnji Cooper 	int fd;
5494fdc3d75SEnji Cooper 
5504fdc3d75SEnji Cooper 	gen_test_path();
5514fdc3d75SEnji Cooper 
5524fdc3d75SEnji Cooper 	fd = shm_open(test_path, O_RDONLY|O_CREAT, 0777);
5534fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
5544fdc3d75SEnji Cooper 	close(fd);
5554fdc3d75SEnji Cooper 
5564fdc3d75SEnji Cooper 	shm_open_should_fail(test_path, O_RDONLY|O_CREAT|O_EXCL,
5574fdc3d75SEnji Cooper 	    0777, EEXIST);
5584fdc3d75SEnji Cooper 
5594fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,
5604fdc3d75SEnji Cooper 	    "shm_unlink failed; errno=%d", errno);
5614fdc3d75SEnji Cooper }
5624fdc3d75SEnji Cooper 
5634fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(trunc_resets_object);
5644fdc3d75SEnji Cooper ATF_TC_BODY(trunc_resets_object, tc)
5654fdc3d75SEnji Cooper {
5664fdc3d75SEnji Cooper 	struct stat sb;
5674fdc3d75SEnji Cooper 	int fd;
5684fdc3d75SEnji Cooper 
5694fdc3d75SEnji Cooper 	gen_test_path();
5704fdc3d75SEnji Cooper 
5714fdc3d75SEnji Cooper 	/* Create object and set size to 1024. */
5724fdc3d75SEnji Cooper 	fd = shm_open(test_path, O_RDWR | O_CREAT, 0777);
5734fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno);
5744fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(ftruncate(fd, 1024) != -1,
5754fdc3d75SEnji Cooper 	    "ftruncate failed; errno=%d", errno);
5764fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(fstat(fd, &sb) != -1,
5774fdc3d75SEnji Cooper 	    "fstat(1) failed; errno=%d", errno);
5784fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(sb.st_size == 1024, "size %d != 1024", (int)sb.st_size);
5794fdc3d75SEnji Cooper 	close(fd);
5804fdc3d75SEnji Cooper 
5814fdc3d75SEnji Cooper 	/* Open with O_TRUNC which should reset size to 0. */
5824fdc3d75SEnji Cooper 	fd = shm_open(test_path, O_RDWR | O_TRUNC, 0777);
5834fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(fd >= 0, "shm_open(2) failed; errno=%d", errno);
5844fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(fstat(fd, &sb) != -1,
5854fdc3d75SEnji Cooper 	    "fstat(2) failed; errno=%d", errno);
5864fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(sb.st_size == 0,
5874fdc3d75SEnji Cooper 	    "size was not 0 after truncation: %d", (int)sb.st_size);
5884fdc3d75SEnji Cooper 	close(fd);
5894fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,
5904fdc3d75SEnji Cooper 	    "shm_unlink failed; errno=%d", errno);
5914fdc3d75SEnji Cooper }
5924fdc3d75SEnji Cooper 
5934fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(unlink_bad_path_pointer);
5944fdc3d75SEnji Cooper ATF_TC_BODY(unlink_bad_path_pointer, tc)
5954fdc3d75SEnji Cooper {
5964fdc3d75SEnji Cooper 
5974fdc3d75SEnji Cooper 	shm_unlink_should_fail((char *)1024, EFAULT);
5984fdc3d75SEnji Cooper }
5994fdc3d75SEnji Cooper 
6004fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(unlink_path_too_long);
6014fdc3d75SEnji Cooper ATF_TC_BODY(unlink_path_too_long, tc)
6024fdc3d75SEnji Cooper {
6034fdc3d75SEnji Cooper 	char *page;
6044fdc3d75SEnji Cooper 
6054fdc3d75SEnji Cooper 	page = malloc(MAXPATHLEN + 1);
6064fdc3d75SEnji Cooper 	memset(page, 'a', MAXPATHLEN);
6074fdc3d75SEnji Cooper 	page[MAXPATHLEN] = '\0';
6084fdc3d75SEnji Cooper 	shm_unlink_should_fail(page, ENAMETOOLONG);
6094fdc3d75SEnji Cooper 	free(page);
6104fdc3d75SEnji Cooper }
6114fdc3d75SEnji Cooper 
6124fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(object_resize);
6134fdc3d75SEnji Cooper ATF_TC_BODY(object_resize, tc)
6144fdc3d75SEnji Cooper {
6154fdc3d75SEnji Cooper 	pid_t pid;
6164fdc3d75SEnji Cooper 	struct stat sb;
61794ebd6f5SEnji Cooper 	char *page;
61894ebd6f5SEnji Cooper 	int fd, pagesize, status;
61994ebd6f5SEnji Cooper 
62094ebd6f5SEnji Cooper 	ATF_REQUIRE(0 < (pagesize = getpagesize()));
6214fdc3d75SEnji Cooper 
6224fdc3d75SEnji Cooper 	/* Start off with a size of a single page. */
6234fdc3d75SEnji Cooper 	fd = shm_open(SHM_ANON, O_CREAT|O_RDWR, 0777);
6244fdc3d75SEnji Cooper 	if (fd < 0)
6254fdc3d75SEnji Cooper 		atf_tc_fail("shm_open failed; errno=%d", errno);
6264fdc3d75SEnji Cooper 
62794ebd6f5SEnji Cooper 	if (ftruncate(fd, pagesize) < 0)
6284fdc3d75SEnji Cooper 		atf_tc_fail("ftruncate(1) failed; errno=%d", errno);
6294fdc3d75SEnji Cooper 
6304fdc3d75SEnji Cooper 	if (fstat(fd, &sb) < 0)
6314fdc3d75SEnji Cooper 		atf_tc_fail("fstat(1) failed; errno=%d", errno);
6324fdc3d75SEnji Cooper 
63394ebd6f5SEnji Cooper 	if (sb.st_size != pagesize)
6344fdc3d75SEnji Cooper 		atf_tc_fail("first resize failed (%d != %d)",
63594ebd6f5SEnji Cooper 		    (int)sb.st_size, pagesize);
6364fdc3d75SEnji Cooper 
6374fdc3d75SEnji Cooper 	/* Write a '1' to the first byte. */
63894ebd6f5SEnji Cooper 	page = mmap(0, pagesize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
6394fdc3d75SEnji Cooper 	if (page == MAP_FAILED)
6404fdc3d75SEnji Cooper 		atf_tc_fail("mmap(1)");
6414fdc3d75SEnji Cooper 
6424fdc3d75SEnji Cooper 	page[0] = '1';
6434fdc3d75SEnji Cooper 
64494ebd6f5SEnji Cooper 	ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",
64594ebd6f5SEnji Cooper 	    errno);
6464fdc3d75SEnji Cooper 
6474fdc3d75SEnji Cooper 	/* Grow the object to 2 pages. */
64894ebd6f5SEnji Cooper 	if (ftruncate(fd, pagesize * 2) < 0)
6494fdc3d75SEnji Cooper 		atf_tc_fail("ftruncate(2) failed; errno=%d", errno);
6504fdc3d75SEnji Cooper 
6514fdc3d75SEnji Cooper 	if (fstat(fd, &sb) < 0)
6524fdc3d75SEnji Cooper 		atf_tc_fail("fstat(2) failed; errno=%d", errno);
6534fdc3d75SEnji Cooper 
65494ebd6f5SEnji Cooper 	if (sb.st_size != pagesize * 2)
6554fdc3d75SEnji Cooper 		atf_tc_fail("second resize failed (%d != %d)",
65694ebd6f5SEnji Cooper 		    (int)sb.st_size, pagesize * 2);
6574fdc3d75SEnji Cooper 
6584fdc3d75SEnji Cooper 	/* Check for '1' at the first byte. */
65994ebd6f5SEnji Cooper 	page = mmap(0, pagesize * 2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
6604fdc3d75SEnji Cooper 	if (page == MAP_FAILED)
6614fdc3d75SEnji Cooper 		atf_tc_fail("mmap(2) failed; errno=%d", errno);
6624fdc3d75SEnji Cooper 
6634fdc3d75SEnji Cooper 	if (page[0] != '1')
6644fdc3d75SEnji Cooper 		atf_tc_fail("'%c' != '1'", page[0]);
6654fdc3d75SEnji Cooper 
6664fdc3d75SEnji Cooper 	/* Write a '2' at the start of the second page. */
66794ebd6f5SEnji Cooper 	page[pagesize] = '2';
6684fdc3d75SEnji Cooper 
6694fdc3d75SEnji Cooper 	/* Shrink the object back to 1 page. */
67094ebd6f5SEnji Cooper 	if (ftruncate(fd, pagesize) < 0)
6714fdc3d75SEnji Cooper 		atf_tc_fail("ftruncate(3) failed; errno=%d", errno);
6724fdc3d75SEnji Cooper 
6734fdc3d75SEnji Cooper 	if (fstat(fd, &sb) < 0)
6744fdc3d75SEnji Cooper 		atf_tc_fail("fstat(3) failed; errno=%d", errno);
6754fdc3d75SEnji Cooper 
67694ebd6f5SEnji Cooper 	if (sb.st_size != pagesize)
6774fdc3d75SEnji Cooper 		atf_tc_fail("third resize failed (%d != %d)",
67894ebd6f5SEnji Cooper 		    (int)sb.st_size, pagesize);
6794fdc3d75SEnji Cooper 
6804fdc3d75SEnji Cooper 	/*
6814fdc3d75SEnji Cooper 	 * Fork a child process to make sure the second page is no
6824fdc3d75SEnji Cooper 	 * longer valid.
6834fdc3d75SEnji Cooper 	 */
6844fdc3d75SEnji Cooper 	pid = fork();
6854fdc3d75SEnji Cooper 	if (pid == -1)
6864fdc3d75SEnji Cooper 		atf_tc_fail("fork failed; errno=%d", errno);
6874fdc3d75SEnji Cooper 
6884fdc3d75SEnji Cooper 	if (pid == 0) {
6894fdc3d75SEnji Cooper 		struct rlimit lim;
6904fdc3d75SEnji Cooper 		char c;
6914fdc3d75SEnji Cooper 
6924fdc3d75SEnji Cooper 		/* Don't generate a core dump. */
69394ebd6f5SEnji Cooper 		ATF_REQUIRE(getrlimit(RLIMIT_CORE, &lim) == 0);
6944fdc3d75SEnji Cooper 		lim.rlim_cur = 0;
69594ebd6f5SEnji Cooper 		ATF_REQUIRE(setrlimit(RLIMIT_CORE, &lim) == 0);
6964fdc3d75SEnji Cooper 
6974fdc3d75SEnji Cooper 		/*
6984fdc3d75SEnji Cooper 		 * The previous ftruncate(2) shrunk the backing object
6994fdc3d75SEnji Cooper 		 * so that this address is no longer valid, so reading
700*4f775512SJilles Tjoelker 		 * from it should trigger a SIGBUS.
7014fdc3d75SEnji Cooper 		 */
70294ebd6f5SEnji Cooper 		c = page[pagesize];
7034fdc3d75SEnji Cooper 		fprintf(stderr, "child: page 1: '%c'\n", c);
7044fdc3d75SEnji Cooper 		exit(0);
7054fdc3d75SEnji Cooper 	}
7064fdc3d75SEnji Cooper 
7074fdc3d75SEnji Cooper 	if (wait(&status) < 0)
7084fdc3d75SEnji Cooper 		atf_tc_fail("wait failed; errno=%d", errno);
7094fdc3d75SEnji Cooper 
710*4f775512SJilles Tjoelker 	if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGBUS)
7114fdc3d75SEnji Cooper 		atf_tc_fail("child terminated with status %x", status);
7124fdc3d75SEnji Cooper 
7134fdc3d75SEnji Cooper 	/* Grow the object back to 2 pages. */
71494ebd6f5SEnji Cooper 	if (ftruncate(fd, pagesize * 2) < 0)
7154fdc3d75SEnji Cooper 		atf_tc_fail("ftruncate(2) failed; errno=%d", errno);
7164fdc3d75SEnji Cooper 
7174fdc3d75SEnji Cooper 	if (fstat(fd, &sb) < 0)
7184fdc3d75SEnji Cooper 		atf_tc_fail("fstat(2) failed; errno=%d", errno);
7194fdc3d75SEnji Cooper 
72094ebd6f5SEnji Cooper 	if (sb.st_size != pagesize * 2)
7214fdc3d75SEnji Cooper 		atf_tc_fail("fourth resize failed (%d != %d)",
72294ebd6f5SEnji Cooper 		    (int)sb.st_size, pagesize);
7234fdc3d75SEnji Cooper 
7244fdc3d75SEnji Cooper 	/*
7254fdc3d75SEnji Cooper 	 * Note that the mapping at 'page' for the second page is
7264fdc3d75SEnji Cooper 	 * still valid, and now that the shm object has been grown
7274fdc3d75SEnji Cooper 	 * back up to 2 pages, there is now memory backing this page
7284fdc3d75SEnji Cooper 	 * so the read will work.  However, the data should be zero
7294fdc3d75SEnji Cooper 	 * rather than '2' as the old data was thrown away when the
7304fdc3d75SEnji Cooper 	 * object was shrunk and the new pages when an object are
7314fdc3d75SEnji Cooper 	 * grown are zero-filled.
7324fdc3d75SEnji Cooper 	 */
73394ebd6f5SEnji Cooper 	if (page[pagesize] != 0)
7344fdc3d75SEnji Cooper 		atf_tc_fail("invalid data at %d: %x != 0",
73594ebd6f5SEnji Cooper 		    pagesize, (int)page[pagesize]);
7364fdc3d75SEnji Cooper 
7374fdc3d75SEnji Cooper 	close(fd);
7384fdc3d75SEnji Cooper }
7394fdc3d75SEnji Cooper 
7404fdc3d75SEnji Cooper /* Signal handler which does nothing. */
7414fdc3d75SEnji Cooper static void
7424fdc3d75SEnji Cooper ignoreit(int sig __unused)
7434fdc3d75SEnji Cooper {
7444fdc3d75SEnji Cooper 	;
7454fdc3d75SEnji Cooper }
7464fdc3d75SEnji Cooper 
7474fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(shm_functionality_across_fork);
7484fdc3d75SEnji Cooper ATF_TC_BODY(shm_functionality_across_fork, tc)
7494fdc3d75SEnji Cooper {
7504fdc3d75SEnji Cooper 	char *cp, c;
7514fdc3d75SEnji Cooper 	int error, desc, rv;
7524fdc3d75SEnji Cooper 	long scval;
7534fdc3d75SEnji Cooper 	sigset_t ss;
7544fdc3d75SEnji Cooper 	struct sigaction sa;
7554fdc3d75SEnji Cooper 	void *region;
7564fdc3d75SEnji Cooper 	size_t i, psize;
7574fdc3d75SEnji Cooper 
7584fdc3d75SEnji Cooper #ifndef _POSIX_SHARED_MEMORY_OBJECTS
7594fdc3d75SEnji Cooper 	printf("_POSIX_SHARED_MEMORY_OBJECTS is undefined\n");
7604fdc3d75SEnji Cooper #else
7614fdc3d75SEnji Cooper 	printf("_POSIX_SHARED_MEMORY_OBJECTS is defined as %ld\n",
7624fdc3d75SEnji Cooper 	       (long)_POSIX_SHARED_MEMORY_OBJECTS - 0);
7634fdc3d75SEnji Cooper 	if (_POSIX_SHARED_MEMORY_OBJECTS - 0 == -1)
7644fdc3d75SEnji Cooper 		printf("***Indicates this feature may be unsupported!\n");
7654fdc3d75SEnji Cooper #endif
7664fdc3d75SEnji Cooper 	errno = 0;
7674fdc3d75SEnji Cooper 	scval = sysconf(_SC_SHARED_MEMORY_OBJECTS);
7684fdc3d75SEnji Cooper 	if (scval == -1 && errno != 0) {
7694fdc3d75SEnji Cooper 		atf_tc_fail("sysconf(_SC_SHARED_MEMORY_OBJECTS) failed; "
7704fdc3d75SEnji Cooper 		    "errno=%d", errno);
7714fdc3d75SEnji Cooper 	} else {
7724fdc3d75SEnji Cooper 		printf("sysconf(_SC_SHARED_MEMORY_OBJECTS) returns %ld\n",
7734fdc3d75SEnji Cooper 		       scval);
7744fdc3d75SEnji Cooper 		if (scval == -1)
7754fdc3d75SEnji Cooper 			printf("***Indicates this feature is unsupported!\n");
7764fdc3d75SEnji Cooper 	}
7774fdc3d75SEnji Cooper 
7784fdc3d75SEnji Cooper 	errno = 0;
7794fdc3d75SEnji Cooper 	scval = sysconf(_SC_PAGESIZE);
7804fdc3d75SEnji Cooper 	if (scval == -1 && errno != 0) {
7814fdc3d75SEnji Cooper 		atf_tc_fail("sysconf(_SC_PAGESIZE) failed; errno=%d", errno);
78294ebd6f5SEnji Cooper 	} else if (scval <= 0) {
7834fdc3d75SEnji Cooper 		fprintf(stderr, "bogus return from sysconf(_SC_PAGESIZE): %ld",
7844fdc3d75SEnji Cooper 		    scval);
7854fdc3d75SEnji Cooper 		psize = 4096;
7864fdc3d75SEnji Cooper 	} else {
7874fdc3d75SEnji Cooper 		printf("sysconf(_SC_PAGESIZE) returns %ld\n", scval);
7884fdc3d75SEnji Cooper 		psize = scval;
7894fdc3d75SEnji Cooper 	}
7904fdc3d75SEnji Cooper 
7914fdc3d75SEnji Cooper 	gen_test_path();
7924fdc3d75SEnji Cooper 	desc = shm_open(test_path, O_EXCL | O_CREAT | O_RDWR, 0600);
7934fdc3d75SEnji Cooper 
7944fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(desc >= 0, "shm_open failed; errno=%d", errno);
7954fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(shm_unlink(test_path) == 0,
7964fdc3d75SEnji Cooper 	    "shm_unlink failed; errno=%d", errno);
7974fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(ftruncate(desc, (off_t)psize) != -1,
7984fdc3d75SEnji Cooper 	    "ftruncate failed; errno=%d", errno);
7994fdc3d75SEnji Cooper 
80094ebd6f5SEnji Cooper 	region = mmap(NULL, psize, PROT_READ | PROT_WRITE, MAP_SHARED, desc, 0);
8014fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(region != MAP_FAILED, "mmap failed; errno=%d", errno);
8024fdc3d75SEnji Cooper 	memset(region, '\377', psize);
8034fdc3d75SEnji Cooper 
8044fdc3d75SEnji Cooper 	sa.sa_flags = 0;
8054fdc3d75SEnji Cooper 	sa.sa_handler = ignoreit;
8064fdc3d75SEnji Cooper 	sigemptyset(&sa.sa_mask);
8074fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(sigaction(SIGUSR1, &sa, (struct sigaction *)0) == 0,
8084fdc3d75SEnji Cooper 	    "sigaction failed; errno=%d", errno);
8094fdc3d75SEnji Cooper 
8104fdc3d75SEnji Cooper 	sigemptyset(&ss);
8114fdc3d75SEnji Cooper 	sigaddset(&ss, SIGUSR1);
8124fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(sigprocmask(SIG_BLOCK, &ss, (sigset_t *)0) == 0,
8134fdc3d75SEnji Cooper 	    "sigprocmask failed; errno=%d", errno);
8144fdc3d75SEnji Cooper 
8154fdc3d75SEnji Cooper 	rv = fork();
8164fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(rv != -1, "fork failed; errno=%d", errno);
8174fdc3d75SEnji Cooper 	if (rv == 0) {
8184fdc3d75SEnji Cooper 		sigemptyset(&ss);
8194fdc3d75SEnji Cooper 		sigsuspend(&ss);
8204fdc3d75SEnji Cooper 
8214fdc3d75SEnji Cooper 		for (cp = region; cp < (char *)region + psize; cp++) {
8224fdc3d75SEnji Cooper 			if (*cp != '\151')
8234fdc3d75SEnji Cooper 				_exit(1);
8244fdc3d75SEnji Cooper 		}
8254fdc3d75SEnji Cooper 		if (lseek(desc, 0, SEEK_SET) == -1)
8264fdc3d75SEnji Cooper 			_exit(1);
8274fdc3d75SEnji Cooper 		for (i = 0; i < psize; i++) {
8284fdc3d75SEnji Cooper 			error = read(desc, &c, 1);
8294fdc3d75SEnji Cooper 			if (c != '\151')
8304fdc3d75SEnji Cooper 				_exit(1);
8314fdc3d75SEnji Cooper 		}
8324fdc3d75SEnji Cooper 		_exit(0);
8334fdc3d75SEnji Cooper 	} else {
8344fdc3d75SEnji Cooper 		int status;
8354fdc3d75SEnji Cooper 
8364fdc3d75SEnji Cooper 		memset(region, '\151', psize - 2);
8374fdc3d75SEnji Cooper 		error = pwrite(desc, region, 2, psize - 2);
8384fdc3d75SEnji Cooper 		if (error != 2) {
8394fdc3d75SEnji Cooper 			if (error >= 0)
8404fdc3d75SEnji Cooper 				atf_tc_fail("short write; %d bytes written",
8414fdc3d75SEnji Cooper 				    error);
8424fdc3d75SEnji Cooper 			else
8434fdc3d75SEnji Cooper 				atf_tc_fail("shmfd write");
8444fdc3d75SEnji Cooper 		}
8454fdc3d75SEnji Cooper 		kill(rv, SIGUSR1);
8464fdc3d75SEnji Cooper 		waitpid(rv, &status, 0);
8474fdc3d75SEnji Cooper 
8484fdc3d75SEnji Cooper 		if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
8494fdc3d75SEnji Cooper 			printf("Functionality test successful\n");
8504fdc3d75SEnji Cooper 		} else if (WIFEXITED(status)) {
8514fdc3d75SEnji Cooper 			atf_tc_fail("Child process exited with status %d",
8524fdc3d75SEnji Cooper 			    WEXITSTATUS(status));
8534fdc3d75SEnji Cooper 		} else {
8544fdc3d75SEnji Cooper 			atf_tc_fail("Child process terminated with %s",
8554fdc3d75SEnji Cooper 			    strsignal(WTERMSIG(status)));
8564fdc3d75SEnji Cooper 		}
8574fdc3d75SEnji Cooper 	}
85894ebd6f5SEnji Cooper 
85994ebd6f5SEnji Cooper 	ATF_REQUIRE_MSG(munmap(region, psize) == 0, "munmap failed; errno=%d",
86094ebd6f5SEnji Cooper 	    errno);
86194ebd6f5SEnji Cooper 	shm_unlink(test_path);
8624fdc3d75SEnji Cooper }
8634fdc3d75SEnji Cooper 
86495aa96f3SKyle Evans ATF_TC_WITHOUT_HEAD(cloexec);
86595aa96f3SKyle Evans ATF_TC_BODY(cloexec, tc)
86695aa96f3SKyle Evans {
86795aa96f3SKyle Evans 	int fd;
86895aa96f3SKyle Evans 
86995aa96f3SKyle Evans 	gen_test_path();
87095aa96f3SKyle Evans 
87195aa96f3SKyle Evans 	/* shm_open(2) is required to set FD_CLOEXEC */
87295aa96f3SKyle Evans 	fd = shm_open(SHM_ANON, O_RDWR, 0777);
87395aa96f3SKyle Evans 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
87495aa96f3SKyle Evans 	ATF_REQUIRE((fcntl(fd, F_GETFD) & FD_CLOEXEC) != 0);
87595aa96f3SKyle Evans 	close(fd);
87695aa96f3SKyle Evans 
87795aa96f3SKyle Evans 	/* Also make sure that named shm is correct */
87895aa96f3SKyle Evans 	fd = shm_open(test_path, O_CREAT | O_RDWR, 0600);
87995aa96f3SKyle Evans 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
88095aa96f3SKyle Evans 	ATF_REQUIRE((fcntl(fd, F_GETFD) & FD_CLOEXEC) != 0);
88195aa96f3SKyle Evans 	close(fd);
88295aa96f3SKyle Evans }
88395aa96f3SKyle Evans 
88495aa96f3SKyle Evans 
8854fdc3d75SEnji Cooper ATF_TP_ADD_TCS(tp)
8864fdc3d75SEnji Cooper {
8874fdc3d75SEnji Cooper 
8884fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, remap_object);
8899afb12baSDavid Bright 	ATF_TP_ADD_TC(tp, rename_from_anon);
8909afb12baSDavid Bright 	ATF_TP_ADD_TC(tp, rename_bad_path_pointer);
8919afb12baSDavid Bright 	ATF_TP_ADD_TC(tp, rename_from_nonexisting);
8929afb12baSDavid Bright 	ATF_TP_ADD_TC(tp, rename_to_anon);
8939afb12baSDavid Bright 	ATF_TP_ADD_TC(tp, rename_to_replace);
8949afb12baSDavid Bright 	ATF_TP_ADD_TC(tp, rename_to_noreplace);
8959afb12baSDavid Bright 	ATF_TP_ADD_TC(tp, rename_to_exchange);
8969afb12baSDavid Bright 	ATF_TP_ADD_TC(tp, rename_to_exchange_nonexisting);
8979afb12baSDavid Bright 	ATF_TP_ADD_TC(tp, rename_to_self);
8989afb12baSDavid Bright 	ATF_TP_ADD_TC(tp, rename_bad_flag);
8994fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, reopen_object);
9004fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, readonly_mmap_write);
9014fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, open_after_link);
9024fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, open_invalid_path);
9034fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, open_write_only);
9044fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, open_extra_flags);
9054fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, open_anon);
9064fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, open_anon_readonly);
9074fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, open_bad_path_pointer);
9084fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, open_path_too_long);
9094fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, open_nonexisting_object);
9104fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, open_create_existing_object);
9114fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, shm_functionality_across_fork);
9124fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, trunc_resets_object);
9134fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, unlink_bad_path_pointer);
9144fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, unlink_path_too_long);
9154fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, object_resize);
91695aa96f3SKyle Evans 	ATF_TP_ADD_TC(tp, cloexec);
9174fdc3d75SEnji Cooper 
9184fdc3d75SEnji Cooper 	return (atf_no_error());
9194fdc3d75SEnji Cooper }
920