xref: /freebsd/tests/sys/posixshm/posixshm_test.c (revision f10405323ab1ac3b4bad100c6e746395d02f392a)
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 {
562d5603feSDavid 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();
2352d5603feSDavid Bright 	gen_test_path2();
2369afb12baSDavid Bright 	rc = shm_rename(test_path, test_path2, 0);
2379afb12baSDavid Bright 	if (rc != -1)
2389afb12baSDavid Bright 		atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly");
2399afb12baSDavid Bright 
2409afb12baSDavid Bright 	if (errno != ENOENT)
2412d5603feSDavid Bright 		atf_tc_fail("Expected ENOENT to rename of nonexistent shm; got %d",
2422d5603feSDavid Bright 		    errno);
2439afb12baSDavid Bright }
2449afb12baSDavid Bright 
2459afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_anon);
2469afb12baSDavid Bright ATF_TC_BODY(rename_to_anon, tc)
2479afb12baSDavid Bright {
2489afb12baSDavid Bright 	int rc;
2499afb12baSDavid Bright 
2509afb12baSDavid Bright 	gen_test_path();
2519afb12baSDavid Bright 	rc = shm_rename(test_path, SHM_ANON, 0);
2529afb12baSDavid Bright 	if (rc != -1)
2539afb12baSDavid Bright 		atf_tc_fail("shm_rename to SHM_ANON succeeded unexpectedly");
2549afb12baSDavid Bright }
2559afb12baSDavid Bright 
2569afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_replace);
2579afb12baSDavid Bright ATF_TC_BODY(rename_to_replace, tc)
2589afb12baSDavid Bright {
2599afb12baSDavid Bright 	char expected_value;
2609afb12baSDavid Bright 	int fd;
2619afb12baSDavid Bright 	int fd2;
2629afb12baSDavid Bright 
2639afb12baSDavid Bright 	// Some contents we can verify later
2649afb12baSDavid Bright 	expected_value = 'g';
2659afb12baSDavid Bright 
2669afb12baSDavid Bright 	gen_test_path();
2679afb12baSDavid Bright 	fd = scribble_object(test_path, expected_value);
2689afb12baSDavid Bright 	close(fd);
2699afb12baSDavid Bright 
2709afb12baSDavid Bright 	// Give the other some different value so we can detect success
2719afb12baSDavid Bright 	gen_test_path2();
2729afb12baSDavid Bright 	fd2 = scribble_object(test_path2, 'h');
2739afb12baSDavid Bright 	close(fd2);
2749afb12baSDavid Bright 
2759afb12baSDavid Bright 	ATF_REQUIRE_MSG(shm_rename(test_path, test_path2, 0) == 0,
2769afb12baSDavid Bright 	    "shm_rename failed; errno=%d", errno);
2779afb12baSDavid Bright 
2789afb12baSDavid Bright 	// Read back renamed; verify contents
2799afb12baSDavid Bright 	verify_object(test_path2, expected_value);
2809afb12baSDavid Bright }
2819afb12baSDavid Bright 
2829afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_noreplace);
2839afb12baSDavid Bright ATF_TC_BODY(rename_to_noreplace, tc)
2849afb12baSDavid Bright {
2859afb12baSDavid Bright 	char expected_value_from;
2869afb12baSDavid Bright 	char expected_value_to;
2879afb12baSDavid Bright 	int fd_from;
2889afb12baSDavid Bright 	int fd_to;
2899afb12baSDavid Bright 	int rc;
2909afb12baSDavid Bright 
2919afb12baSDavid Bright 	// Some contents we can verify later
2929afb12baSDavid Bright 	expected_value_from = 'g';
2939afb12baSDavid Bright 	gen_test_path();
2949afb12baSDavid Bright 	fd_from = scribble_object(test_path, expected_value_from);
2959afb12baSDavid Bright 	close(fd_from);
2969afb12baSDavid Bright 
2979afb12baSDavid Bright 	// Give the other some different value so we can detect success
2989afb12baSDavid Bright 	expected_value_to = 'h';
2999afb12baSDavid Bright 	gen_test_path2();
3009afb12baSDavid Bright 	fd_to = scribble_object(test_path2, expected_value_to);
3019afb12baSDavid Bright 	close(fd_to);
3029afb12baSDavid Bright 
3039afb12baSDavid Bright 	rc = shm_rename(test_path, test_path2, SHM_RENAME_NOREPLACE);
3049afb12baSDavid Bright 	ATF_REQUIRE_MSG((rc == -1) && (errno == EEXIST),
3059afb12baSDavid Bright 	    "shm_rename didn't fail as expected; errno: %d; return: %d", errno,
3069afb12baSDavid Bright 	    rc);
3079afb12baSDavid Bright 
3089afb12baSDavid Bright 	// Read back renamed; verify contents
3099afb12baSDavid Bright 	verify_object(test_path2, expected_value_to);
3109afb12baSDavid Bright }
3119afb12baSDavid Bright 
3129afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_exchange);
3139afb12baSDavid Bright ATF_TC_BODY(rename_to_exchange, tc)
3149afb12baSDavid Bright {
3159afb12baSDavid Bright 	char expected_value_from;
3169afb12baSDavid Bright 	char expected_value_to;
3179afb12baSDavid Bright 	int fd_from;
3189afb12baSDavid Bright 	int fd_to;
3199afb12baSDavid Bright 
3209afb12baSDavid Bright 	// Some contents we can verify later
3219afb12baSDavid Bright 	expected_value_from = 'g';
3229afb12baSDavid Bright 	gen_test_path();
3239afb12baSDavid Bright 	fd_from = scribble_object(test_path, expected_value_from);
3249afb12baSDavid Bright 	close(fd_from);
3259afb12baSDavid Bright 
3269afb12baSDavid Bright 	// Give the other some different value so we can detect success
3279afb12baSDavid Bright 	expected_value_to = 'h';
3289afb12baSDavid Bright 	gen_test_path2();
3299afb12baSDavid Bright 	fd_to = scribble_object(test_path2, expected_value_to);
3309afb12baSDavid Bright 	close(fd_to);
3319afb12baSDavid Bright 
3329afb12baSDavid Bright 	ATF_REQUIRE_MSG(shm_rename(test_path, test_path2,
3339afb12baSDavid Bright 	    SHM_RENAME_EXCHANGE) == 0,
3349afb12baSDavid Bright 	    "shm_rename failed; errno=%d", errno);
3359afb12baSDavid Bright 
3369afb12baSDavid Bright 	// Read back renamed; verify contents
3379afb12baSDavid Bright 	verify_object(test_path, expected_value_to);
3389afb12baSDavid Bright 	verify_object(test_path2, expected_value_from);
3399afb12baSDavid Bright }
3409afb12baSDavid Bright 
3419afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_exchange_nonexisting);
3429afb12baSDavid Bright ATF_TC_BODY(rename_to_exchange_nonexisting, tc)
3439afb12baSDavid Bright {
3449afb12baSDavid Bright 	char expected_value_from;
3459afb12baSDavid Bright 	int fd_from;
3469afb12baSDavid Bright 
3479afb12baSDavid Bright 	// Some contents we can verify later
3489afb12baSDavid Bright 	expected_value_from = 'g';
3499afb12baSDavid Bright 	gen_test_path();
3509afb12baSDavid Bright 	fd_from = scribble_object(test_path, expected_value_from);
3519afb12baSDavid Bright 	close(fd_from);
3529afb12baSDavid Bright 
3539afb12baSDavid Bright 	gen_test_path2();
3549afb12baSDavid Bright 
3559afb12baSDavid Bright 	ATF_REQUIRE_MSG(shm_rename(test_path, test_path2,
3569afb12baSDavid Bright 	    SHM_RENAME_EXCHANGE) == 0,
3579afb12baSDavid Bright 	    "shm_rename failed; errno=%d", errno);
3589afb12baSDavid Bright 
3599afb12baSDavid Bright 	// Read back renamed; verify contents
3609afb12baSDavid Bright 	verify_object(test_path2, expected_value_from);
3619afb12baSDavid Bright }
3629afb12baSDavid Bright 
3639afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_self);
3649afb12baSDavid Bright ATF_TC_BODY(rename_to_self, tc)
3659afb12baSDavid Bright {
3669afb12baSDavid Bright 	int fd;
3679afb12baSDavid Bright 	char expected_value;
3689afb12baSDavid Bright 
3699afb12baSDavid Bright 	expected_value = 't';
3709afb12baSDavid Bright 
3719afb12baSDavid Bright 	gen_test_path();
3729afb12baSDavid Bright 	fd = scribble_object(test_path, expected_value);
3739afb12baSDavid Bright 	close(fd);
3749afb12baSDavid Bright 
3759afb12baSDavid Bright 	ATF_REQUIRE_MSG(shm_rename(test_path, test_path, 0) == 0,
3769afb12baSDavid Bright 	    "shm_rename failed; errno=%d", errno);
3779afb12baSDavid Bright 
3789afb12baSDavid Bright 	verify_object(test_path, expected_value);
3799afb12baSDavid Bright }
3809afb12baSDavid Bright 
3819afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_bad_flag);
3829afb12baSDavid Bright ATF_TC_BODY(rename_bad_flag, tc)
3839afb12baSDavid Bright {
3849afb12baSDavid Bright 	int fd;
3859afb12baSDavid Bright 	int rc;
3869afb12baSDavid Bright 
3879afb12baSDavid Bright 	/* Make sure we don't fail out due to ENOENT */
3889afb12baSDavid Bright 	gen_test_path();
3899afb12baSDavid Bright 	gen_test_path2();
3909afb12baSDavid Bright 	fd = scribble_object(test_path, 'd');
3919afb12baSDavid Bright 	close(fd);
3929afb12baSDavid Bright 	fd = scribble_object(test_path2, 'd');
3939afb12baSDavid Bright 	close(fd);
3949afb12baSDavid Bright 
3959afb12baSDavid Bright 	/*
3969afb12baSDavid Bright 	 * Note: if we end up with enough flags that we use all the bits,
3979afb12baSDavid Bright 	 * then remove this test completely.
3989afb12baSDavid Bright 	 */
3999afb12baSDavid Bright 	rc = shm_rename(test_path, test_path2, INT_MIN);
4009afb12baSDavid Bright 	ATF_REQUIRE_MSG((rc == -1) && (errno == EINVAL),
4019afb12baSDavid Bright 	    "shm_rename should have failed with EINVAL; got: return=%d, "
4029afb12baSDavid Bright 	    "errno=%d", rc, errno);
4039afb12baSDavid Bright }
4049afb12baSDavid Bright 
4054fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(reopen_object);
4064fdc3d75SEnji Cooper ATF_TC_BODY(reopen_object, tc)
4074fdc3d75SEnji Cooper {
4084fdc3d75SEnji Cooper 	char *page;
40994ebd6f5SEnji Cooper 	int fd, pagesize;
41094ebd6f5SEnji Cooper 
41194ebd6f5SEnji Cooper 	ATF_REQUIRE(0 < (pagesize = getpagesize()));
4124fdc3d75SEnji Cooper 
4139afb12baSDavid Bright 	gen_test_path();
4149afb12baSDavid Bright 	fd = scribble_object(test_path, '1');
4154fdc3d75SEnji Cooper 	close(fd);
4164fdc3d75SEnji Cooper 
4174fdc3d75SEnji Cooper 	fd = shm_open(test_path, O_RDONLY, 0777);
4184fdc3d75SEnji Cooper 	if (fd < 0)
4194fdc3d75SEnji Cooper 		atf_tc_fail("shm_open(2) failed; errno=%d", errno);
4204fdc3d75SEnji Cooper 
42194ebd6f5SEnji Cooper 	page = mmap(0, pagesize, PROT_READ, MAP_SHARED, fd, 0);
4224fdc3d75SEnji Cooper 	if (page == MAP_FAILED)
4234fdc3d75SEnji Cooper 		atf_tc_fail("mmap(2) failed; errno=%d", errno);
4244fdc3d75SEnji Cooper 
4254fdc3d75SEnji Cooper 	if (page[0] != '1')
4264fdc3d75SEnji Cooper 		atf_tc_fail("missing data ('%c' != '1')", page[0]);
4274fdc3d75SEnji Cooper 
42894ebd6f5SEnji Cooper 	ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",
42994ebd6f5SEnji Cooper 	    errno);
4304fdc3d75SEnji Cooper 	close(fd);
4314fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,
4324fdc3d75SEnji Cooper 	    "shm_unlink failed; errno=%d", errno);
4334fdc3d75SEnji Cooper }
4344fdc3d75SEnji Cooper 
4354fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(readonly_mmap_write);
4364fdc3d75SEnji Cooper ATF_TC_BODY(readonly_mmap_write, tc)
4374fdc3d75SEnji Cooper {
4384fdc3d75SEnji Cooper 	char *page;
43994ebd6f5SEnji Cooper 	int fd, pagesize;
44094ebd6f5SEnji Cooper 
44194ebd6f5SEnji Cooper 	ATF_REQUIRE(0 < (pagesize = getpagesize()));
4424fdc3d75SEnji Cooper 
4434fdc3d75SEnji Cooper 	gen_test_path();
4444fdc3d75SEnji Cooper 
4454fdc3d75SEnji Cooper 	fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777);
4464fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
4474fdc3d75SEnji Cooper 
4484fdc3d75SEnji Cooper 	/* PROT_WRITE should fail with EACCES. */
44994ebd6f5SEnji Cooper 	page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
4504fdc3d75SEnji Cooper 	if (page != MAP_FAILED)
4514fdc3d75SEnji Cooper 		atf_tc_fail("mmap(PROT_WRITE) succeeded unexpectedly");
4524fdc3d75SEnji Cooper 
4534fdc3d75SEnji Cooper 	if (errno != EACCES)
4544fdc3d75SEnji Cooper 		atf_tc_fail("mmap(PROT_WRITE) didn't fail with EACCES; "
4554fdc3d75SEnji Cooper 		    "errno=%d", errno);
4564fdc3d75SEnji Cooper 
4574fdc3d75SEnji Cooper 	close(fd);
4584fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,
4594fdc3d75SEnji Cooper 	    "shm_unlink failed; errno=%d", errno);
4604fdc3d75SEnji Cooper }
4614fdc3d75SEnji Cooper 
4624fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_after_link);
4634fdc3d75SEnji Cooper ATF_TC_BODY(open_after_link, tc)
4644fdc3d75SEnji Cooper {
4654fdc3d75SEnji Cooper 	int fd;
4664fdc3d75SEnji Cooper 
4674fdc3d75SEnji Cooper 	gen_test_path();
4684fdc3d75SEnji Cooper 
4694fdc3d75SEnji Cooper 	fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777);
4704fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno);
4714fdc3d75SEnji Cooper 	close(fd);
4724fdc3d75SEnji Cooper 
4734fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, "shm_unlink failed: %d",
4744fdc3d75SEnji Cooper 	    errno);
4754fdc3d75SEnji Cooper 
4764fdc3d75SEnji Cooper 	shm_open_should_fail(test_path, O_RDONLY, 0777, ENOENT);
4774fdc3d75SEnji Cooper }
4784fdc3d75SEnji Cooper 
4794fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_invalid_path);
4804fdc3d75SEnji Cooper ATF_TC_BODY(open_invalid_path, tc)
4814fdc3d75SEnji Cooper {
4824fdc3d75SEnji Cooper 
4834fdc3d75SEnji Cooper 	shm_open_should_fail("blah", O_RDONLY, 0777, EINVAL);
4844fdc3d75SEnji Cooper }
4854fdc3d75SEnji Cooper 
4864fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_write_only);
4874fdc3d75SEnji Cooper ATF_TC_BODY(open_write_only, tc)
4884fdc3d75SEnji Cooper {
4894fdc3d75SEnji Cooper 
4904fdc3d75SEnji Cooper 	gen_test_path();
4914fdc3d75SEnji Cooper 
4924fdc3d75SEnji Cooper 	shm_open_should_fail(test_path, O_WRONLY, 0777, EINVAL);
4934fdc3d75SEnji Cooper }
4944fdc3d75SEnji Cooper 
4954fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_extra_flags);
4964fdc3d75SEnji Cooper ATF_TC_BODY(open_extra_flags, tc)
4974fdc3d75SEnji Cooper {
4984fdc3d75SEnji Cooper 
4994fdc3d75SEnji Cooper 	gen_test_path();
5004fdc3d75SEnji Cooper 
5014fdc3d75SEnji Cooper 	shm_open_should_fail(test_path, O_RDONLY | O_DIRECT, 0777, EINVAL);
5024fdc3d75SEnji Cooper }
5034fdc3d75SEnji Cooper 
5044fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_anon);
5054fdc3d75SEnji Cooper ATF_TC_BODY(open_anon, tc)
5064fdc3d75SEnji Cooper {
5074fdc3d75SEnji Cooper 	int fd;
5084fdc3d75SEnji Cooper 
5094fdc3d75SEnji Cooper 	fd = shm_open(SHM_ANON, O_RDWR, 0777);
5104fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
5114fdc3d75SEnji Cooper 	close(fd);
5124fdc3d75SEnji Cooper }
5134fdc3d75SEnji Cooper 
5144fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_anon_readonly);
5154fdc3d75SEnji Cooper ATF_TC_BODY(open_anon_readonly, tc)
5164fdc3d75SEnji Cooper {
5174fdc3d75SEnji Cooper 
5184fdc3d75SEnji Cooper 	shm_open_should_fail(SHM_ANON, O_RDONLY, 0777, EINVAL);
5194fdc3d75SEnji Cooper }
5204fdc3d75SEnji Cooper 
5214fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_bad_path_pointer);
5224fdc3d75SEnji Cooper ATF_TC_BODY(open_bad_path_pointer, tc)
5234fdc3d75SEnji Cooper {
5244fdc3d75SEnji Cooper 
5254fdc3d75SEnji Cooper 	shm_open_should_fail((char *)1024, O_RDONLY, 0777, EFAULT);
5264fdc3d75SEnji Cooper }
5274fdc3d75SEnji Cooper 
5284fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_path_too_long);
5294fdc3d75SEnji Cooper ATF_TC_BODY(open_path_too_long, tc)
5304fdc3d75SEnji Cooper {
5314fdc3d75SEnji Cooper 	char *page;
5324fdc3d75SEnji Cooper 
5334fdc3d75SEnji Cooper 	page = malloc(MAXPATHLEN + 1);
5344fdc3d75SEnji Cooper 	memset(page, 'a', MAXPATHLEN);
5354fdc3d75SEnji Cooper 	page[MAXPATHLEN] = '\0';
5364fdc3d75SEnji Cooper 	shm_open_should_fail(page, O_RDONLY, 0777, ENAMETOOLONG);
5374fdc3d75SEnji Cooper 	free(page);
5384fdc3d75SEnji Cooper }
5394fdc3d75SEnji Cooper 
5404fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_nonexisting_object);
5414fdc3d75SEnji Cooper ATF_TC_BODY(open_nonexisting_object, tc)
5424fdc3d75SEnji Cooper {
5434fdc3d75SEnji Cooper 
5444fdc3d75SEnji Cooper 	shm_open_should_fail("/notreallythere", O_RDONLY, 0777, ENOENT);
5454fdc3d75SEnji Cooper }
5464fdc3d75SEnji Cooper 
5474fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_create_existing_object);
5484fdc3d75SEnji Cooper ATF_TC_BODY(open_create_existing_object, tc)
5494fdc3d75SEnji Cooper {
5504fdc3d75SEnji Cooper 	int fd;
5514fdc3d75SEnji Cooper 
5524fdc3d75SEnji Cooper 	gen_test_path();
5534fdc3d75SEnji Cooper 
5544fdc3d75SEnji Cooper 	fd = shm_open(test_path, O_RDONLY|O_CREAT, 0777);
5554fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
5564fdc3d75SEnji Cooper 	close(fd);
5574fdc3d75SEnji Cooper 
5584fdc3d75SEnji Cooper 	shm_open_should_fail(test_path, O_RDONLY|O_CREAT|O_EXCL,
5594fdc3d75SEnji Cooper 	    0777, EEXIST);
5604fdc3d75SEnji Cooper 
5614fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,
5624fdc3d75SEnji Cooper 	    "shm_unlink failed; errno=%d", errno);
5634fdc3d75SEnji Cooper }
5644fdc3d75SEnji Cooper 
5654fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(trunc_resets_object);
5664fdc3d75SEnji Cooper ATF_TC_BODY(trunc_resets_object, tc)
5674fdc3d75SEnji Cooper {
5684fdc3d75SEnji Cooper 	struct stat sb;
5694fdc3d75SEnji Cooper 	int fd;
5704fdc3d75SEnji Cooper 
5714fdc3d75SEnji Cooper 	gen_test_path();
5724fdc3d75SEnji Cooper 
5734fdc3d75SEnji Cooper 	/* Create object and set size to 1024. */
5744fdc3d75SEnji Cooper 	fd = shm_open(test_path, O_RDWR | O_CREAT, 0777);
5754fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno);
5764fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(ftruncate(fd, 1024) != -1,
5774fdc3d75SEnji Cooper 	    "ftruncate failed; errno=%d", errno);
5784fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(fstat(fd, &sb) != -1,
5794fdc3d75SEnji Cooper 	    "fstat(1) failed; errno=%d", errno);
5804fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(sb.st_size == 1024, "size %d != 1024", (int)sb.st_size);
5814fdc3d75SEnji Cooper 	close(fd);
5824fdc3d75SEnji Cooper 
5834fdc3d75SEnji Cooper 	/* Open with O_TRUNC which should reset size to 0. */
5844fdc3d75SEnji Cooper 	fd = shm_open(test_path, O_RDWR | O_TRUNC, 0777);
5854fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(fd >= 0, "shm_open(2) failed; errno=%d", errno);
5864fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(fstat(fd, &sb) != -1,
5874fdc3d75SEnji Cooper 	    "fstat(2) failed; errno=%d", errno);
5884fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(sb.st_size == 0,
5894fdc3d75SEnji Cooper 	    "size was not 0 after truncation: %d", (int)sb.st_size);
5904fdc3d75SEnji Cooper 	close(fd);
5914fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,
5924fdc3d75SEnji Cooper 	    "shm_unlink failed; errno=%d", errno);
5934fdc3d75SEnji Cooper }
5944fdc3d75SEnji Cooper 
5954fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(unlink_bad_path_pointer);
5964fdc3d75SEnji Cooper ATF_TC_BODY(unlink_bad_path_pointer, tc)
5974fdc3d75SEnji Cooper {
5984fdc3d75SEnji Cooper 
5994fdc3d75SEnji Cooper 	shm_unlink_should_fail((char *)1024, EFAULT);
6004fdc3d75SEnji Cooper }
6014fdc3d75SEnji Cooper 
6024fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(unlink_path_too_long);
6034fdc3d75SEnji Cooper ATF_TC_BODY(unlink_path_too_long, tc)
6044fdc3d75SEnji Cooper {
6054fdc3d75SEnji Cooper 	char *page;
6064fdc3d75SEnji Cooper 
6074fdc3d75SEnji Cooper 	page = malloc(MAXPATHLEN + 1);
6084fdc3d75SEnji Cooper 	memset(page, 'a', MAXPATHLEN);
6094fdc3d75SEnji Cooper 	page[MAXPATHLEN] = '\0';
6104fdc3d75SEnji Cooper 	shm_unlink_should_fail(page, ENAMETOOLONG);
6114fdc3d75SEnji Cooper 	free(page);
6124fdc3d75SEnji Cooper }
6134fdc3d75SEnji Cooper 
6144fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(object_resize);
6154fdc3d75SEnji Cooper ATF_TC_BODY(object_resize, tc)
6164fdc3d75SEnji Cooper {
6174fdc3d75SEnji Cooper 	pid_t pid;
6184fdc3d75SEnji Cooper 	struct stat sb;
61994ebd6f5SEnji Cooper 	char *page;
62094ebd6f5SEnji Cooper 	int fd, pagesize, status;
62194ebd6f5SEnji Cooper 
62294ebd6f5SEnji Cooper 	ATF_REQUIRE(0 < (pagesize = getpagesize()));
6234fdc3d75SEnji Cooper 
6244fdc3d75SEnji Cooper 	/* Start off with a size of a single page. */
6254fdc3d75SEnji Cooper 	fd = shm_open(SHM_ANON, O_CREAT|O_RDWR, 0777);
6264fdc3d75SEnji Cooper 	if (fd < 0)
6274fdc3d75SEnji Cooper 		atf_tc_fail("shm_open failed; errno=%d", errno);
6284fdc3d75SEnji Cooper 
62994ebd6f5SEnji Cooper 	if (ftruncate(fd, pagesize) < 0)
6304fdc3d75SEnji Cooper 		atf_tc_fail("ftruncate(1) failed; errno=%d", errno);
6314fdc3d75SEnji Cooper 
6324fdc3d75SEnji Cooper 	if (fstat(fd, &sb) < 0)
6334fdc3d75SEnji Cooper 		atf_tc_fail("fstat(1) failed; errno=%d", errno);
6344fdc3d75SEnji Cooper 
63594ebd6f5SEnji Cooper 	if (sb.st_size != pagesize)
6364fdc3d75SEnji Cooper 		atf_tc_fail("first resize failed (%d != %d)",
63794ebd6f5SEnji Cooper 		    (int)sb.st_size, pagesize);
6384fdc3d75SEnji Cooper 
6394fdc3d75SEnji Cooper 	/* Write a '1' to the first byte. */
64094ebd6f5SEnji Cooper 	page = mmap(0, pagesize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
6414fdc3d75SEnji Cooper 	if (page == MAP_FAILED)
6424fdc3d75SEnji Cooper 		atf_tc_fail("mmap(1)");
6434fdc3d75SEnji Cooper 
6444fdc3d75SEnji Cooper 	page[0] = '1';
6454fdc3d75SEnji Cooper 
64694ebd6f5SEnji Cooper 	ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",
64794ebd6f5SEnji Cooper 	    errno);
6484fdc3d75SEnji Cooper 
6494fdc3d75SEnji Cooper 	/* Grow the object to 2 pages. */
65094ebd6f5SEnji Cooper 	if (ftruncate(fd, pagesize * 2) < 0)
6514fdc3d75SEnji Cooper 		atf_tc_fail("ftruncate(2) failed; errno=%d", errno);
6524fdc3d75SEnji Cooper 
6534fdc3d75SEnji Cooper 	if (fstat(fd, &sb) < 0)
6544fdc3d75SEnji Cooper 		atf_tc_fail("fstat(2) failed; errno=%d", errno);
6554fdc3d75SEnji Cooper 
65694ebd6f5SEnji Cooper 	if (sb.st_size != pagesize * 2)
6574fdc3d75SEnji Cooper 		atf_tc_fail("second resize failed (%d != %d)",
65894ebd6f5SEnji Cooper 		    (int)sb.st_size, pagesize * 2);
6594fdc3d75SEnji Cooper 
6604fdc3d75SEnji Cooper 	/* Check for '1' at the first byte. */
66194ebd6f5SEnji Cooper 	page = mmap(0, pagesize * 2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
6624fdc3d75SEnji Cooper 	if (page == MAP_FAILED)
6634fdc3d75SEnji Cooper 		atf_tc_fail("mmap(2) failed; errno=%d", errno);
6644fdc3d75SEnji Cooper 
6654fdc3d75SEnji Cooper 	if (page[0] != '1')
6664fdc3d75SEnji Cooper 		atf_tc_fail("'%c' != '1'", page[0]);
6674fdc3d75SEnji Cooper 
6684fdc3d75SEnji Cooper 	/* Write a '2' at the start of the second page. */
66994ebd6f5SEnji Cooper 	page[pagesize] = '2';
6704fdc3d75SEnji Cooper 
6714fdc3d75SEnji Cooper 	/* Shrink the object back to 1 page. */
67294ebd6f5SEnji Cooper 	if (ftruncate(fd, pagesize) < 0)
6734fdc3d75SEnji Cooper 		atf_tc_fail("ftruncate(3) failed; errno=%d", errno);
6744fdc3d75SEnji Cooper 
6754fdc3d75SEnji Cooper 	if (fstat(fd, &sb) < 0)
6764fdc3d75SEnji Cooper 		atf_tc_fail("fstat(3) failed; errno=%d", errno);
6774fdc3d75SEnji Cooper 
67894ebd6f5SEnji Cooper 	if (sb.st_size != pagesize)
6794fdc3d75SEnji Cooper 		atf_tc_fail("third resize failed (%d != %d)",
68094ebd6f5SEnji Cooper 		    (int)sb.st_size, pagesize);
6814fdc3d75SEnji Cooper 
6824fdc3d75SEnji Cooper 	/*
6834fdc3d75SEnji Cooper 	 * Fork a child process to make sure the second page is no
6844fdc3d75SEnji Cooper 	 * longer valid.
6854fdc3d75SEnji Cooper 	 */
6864fdc3d75SEnji Cooper 	pid = fork();
6874fdc3d75SEnji Cooper 	if (pid == -1)
6884fdc3d75SEnji Cooper 		atf_tc_fail("fork failed; errno=%d", errno);
6894fdc3d75SEnji Cooper 
6904fdc3d75SEnji Cooper 	if (pid == 0) {
6914fdc3d75SEnji Cooper 		struct rlimit lim;
6924fdc3d75SEnji Cooper 		char c;
6934fdc3d75SEnji Cooper 
6944fdc3d75SEnji Cooper 		/* Don't generate a core dump. */
69594ebd6f5SEnji Cooper 		ATF_REQUIRE(getrlimit(RLIMIT_CORE, &lim) == 0);
6964fdc3d75SEnji Cooper 		lim.rlim_cur = 0;
69794ebd6f5SEnji Cooper 		ATF_REQUIRE(setrlimit(RLIMIT_CORE, &lim) == 0);
6984fdc3d75SEnji Cooper 
6994fdc3d75SEnji Cooper 		/*
7004fdc3d75SEnji Cooper 		 * The previous ftruncate(2) shrunk the backing object
7014fdc3d75SEnji Cooper 		 * so that this address is no longer valid, so reading
7024f775512SJilles Tjoelker 		 * from it should trigger a SIGBUS.
7034fdc3d75SEnji Cooper 		 */
70494ebd6f5SEnji Cooper 		c = page[pagesize];
7054fdc3d75SEnji Cooper 		fprintf(stderr, "child: page 1: '%c'\n", c);
7064fdc3d75SEnji Cooper 		exit(0);
7074fdc3d75SEnji Cooper 	}
7084fdc3d75SEnji Cooper 
7094fdc3d75SEnji Cooper 	if (wait(&status) < 0)
7104fdc3d75SEnji Cooper 		atf_tc_fail("wait failed; errno=%d", errno);
7114fdc3d75SEnji Cooper 
7124f775512SJilles Tjoelker 	if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGBUS)
7134fdc3d75SEnji Cooper 		atf_tc_fail("child terminated with status %x", status);
7144fdc3d75SEnji Cooper 
7154fdc3d75SEnji Cooper 	/* Grow the object back to 2 pages. */
71694ebd6f5SEnji Cooper 	if (ftruncate(fd, pagesize * 2) < 0)
7174fdc3d75SEnji Cooper 		atf_tc_fail("ftruncate(2) failed; errno=%d", errno);
7184fdc3d75SEnji Cooper 
7194fdc3d75SEnji Cooper 	if (fstat(fd, &sb) < 0)
7204fdc3d75SEnji Cooper 		atf_tc_fail("fstat(2) failed; errno=%d", errno);
7214fdc3d75SEnji Cooper 
72294ebd6f5SEnji Cooper 	if (sb.st_size != pagesize * 2)
7234fdc3d75SEnji Cooper 		atf_tc_fail("fourth resize failed (%d != %d)",
72494ebd6f5SEnji Cooper 		    (int)sb.st_size, pagesize);
7254fdc3d75SEnji Cooper 
7264fdc3d75SEnji Cooper 	/*
7274fdc3d75SEnji Cooper 	 * Note that the mapping at 'page' for the second page is
7284fdc3d75SEnji Cooper 	 * still valid, and now that the shm object has been grown
7294fdc3d75SEnji Cooper 	 * back up to 2 pages, there is now memory backing this page
7304fdc3d75SEnji Cooper 	 * so the read will work.  However, the data should be zero
7314fdc3d75SEnji Cooper 	 * rather than '2' as the old data was thrown away when the
7324fdc3d75SEnji Cooper 	 * object was shrunk and the new pages when an object are
7334fdc3d75SEnji Cooper 	 * grown are zero-filled.
7344fdc3d75SEnji Cooper 	 */
73594ebd6f5SEnji Cooper 	if (page[pagesize] != 0)
7364fdc3d75SEnji Cooper 		atf_tc_fail("invalid data at %d: %x != 0",
73794ebd6f5SEnji Cooper 		    pagesize, (int)page[pagesize]);
7384fdc3d75SEnji Cooper 
7394fdc3d75SEnji Cooper 	close(fd);
7404fdc3d75SEnji Cooper }
7414fdc3d75SEnji Cooper 
7424fdc3d75SEnji Cooper /* Signal handler which does nothing. */
7434fdc3d75SEnji Cooper static void
7444fdc3d75SEnji Cooper ignoreit(int sig __unused)
7454fdc3d75SEnji Cooper {
7464fdc3d75SEnji Cooper 	;
7474fdc3d75SEnji Cooper }
7484fdc3d75SEnji Cooper 
7494fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(shm_functionality_across_fork);
7504fdc3d75SEnji Cooper ATF_TC_BODY(shm_functionality_across_fork, tc)
7514fdc3d75SEnji Cooper {
7524fdc3d75SEnji Cooper 	char *cp, c;
7534fdc3d75SEnji Cooper 	int error, desc, rv;
7544fdc3d75SEnji Cooper 	long scval;
7554fdc3d75SEnji Cooper 	sigset_t ss;
7564fdc3d75SEnji Cooper 	struct sigaction sa;
7574fdc3d75SEnji Cooper 	void *region;
7584fdc3d75SEnji Cooper 	size_t i, psize;
7594fdc3d75SEnji Cooper 
7604fdc3d75SEnji Cooper #ifndef _POSIX_SHARED_MEMORY_OBJECTS
7614fdc3d75SEnji Cooper 	printf("_POSIX_SHARED_MEMORY_OBJECTS is undefined\n");
7624fdc3d75SEnji Cooper #else
7634fdc3d75SEnji Cooper 	printf("_POSIX_SHARED_MEMORY_OBJECTS is defined as %ld\n",
7644fdc3d75SEnji Cooper 	       (long)_POSIX_SHARED_MEMORY_OBJECTS - 0);
7654fdc3d75SEnji Cooper 	if (_POSIX_SHARED_MEMORY_OBJECTS - 0 == -1)
7664fdc3d75SEnji Cooper 		printf("***Indicates this feature may be unsupported!\n");
7674fdc3d75SEnji Cooper #endif
7684fdc3d75SEnji Cooper 	errno = 0;
7694fdc3d75SEnji Cooper 	scval = sysconf(_SC_SHARED_MEMORY_OBJECTS);
7704fdc3d75SEnji Cooper 	if (scval == -1 && errno != 0) {
7714fdc3d75SEnji Cooper 		atf_tc_fail("sysconf(_SC_SHARED_MEMORY_OBJECTS) failed; "
7724fdc3d75SEnji Cooper 		    "errno=%d", errno);
7734fdc3d75SEnji Cooper 	} else {
7744fdc3d75SEnji Cooper 		printf("sysconf(_SC_SHARED_MEMORY_OBJECTS) returns %ld\n",
7754fdc3d75SEnji Cooper 		       scval);
7764fdc3d75SEnji Cooper 		if (scval == -1)
7774fdc3d75SEnji Cooper 			printf("***Indicates this feature is unsupported!\n");
7784fdc3d75SEnji Cooper 	}
7794fdc3d75SEnji Cooper 
7804fdc3d75SEnji Cooper 	errno = 0;
7814fdc3d75SEnji Cooper 	scval = sysconf(_SC_PAGESIZE);
7824fdc3d75SEnji Cooper 	if (scval == -1 && errno != 0) {
7834fdc3d75SEnji Cooper 		atf_tc_fail("sysconf(_SC_PAGESIZE) failed; errno=%d", errno);
78494ebd6f5SEnji Cooper 	} else if (scval <= 0) {
7854fdc3d75SEnji Cooper 		fprintf(stderr, "bogus return from sysconf(_SC_PAGESIZE): %ld",
7864fdc3d75SEnji Cooper 		    scval);
7874fdc3d75SEnji Cooper 		psize = 4096;
7884fdc3d75SEnji Cooper 	} else {
7894fdc3d75SEnji Cooper 		printf("sysconf(_SC_PAGESIZE) returns %ld\n", scval);
7904fdc3d75SEnji Cooper 		psize = scval;
7914fdc3d75SEnji Cooper 	}
7924fdc3d75SEnji Cooper 
7934fdc3d75SEnji Cooper 	gen_test_path();
7944fdc3d75SEnji Cooper 	desc = shm_open(test_path, O_EXCL | O_CREAT | O_RDWR, 0600);
7954fdc3d75SEnji Cooper 
7964fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(desc >= 0, "shm_open failed; errno=%d", errno);
7974fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(shm_unlink(test_path) == 0,
7984fdc3d75SEnji Cooper 	    "shm_unlink failed; errno=%d", errno);
7994fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(ftruncate(desc, (off_t)psize) != -1,
8004fdc3d75SEnji Cooper 	    "ftruncate failed; errno=%d", errno);
8014fdc3d75SEnji Cooper 
80294ebd6f5SEnji Cooper 	region = mmap(NULL, psize, PROT_READ | PROT_WRITE, MAP_SHARED, desc, 0);
8034fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(region != MAP_FAILED, "mmap failed; errno=%d", errno);
8044fdc3d75SEnji Cooper 	memset(region, '\377', psize);
8054fdc3d75SEnji Cooper 
8064fdc3d75SEnji Cooper 	sa.sa_flags = 0;
8074fdc3d75SEnji Cooper 	sa.sa_handler = ignoreit;
8084fdc3d75SEnji Cooper 	sigemptyset(&sa.sa_mask);
8094fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(sigaction(SIGUSR1, &sa, (struct sigaction *)0) == 0,
8104fdc3d75SEnji Cooper 	    "sigaction failed; errno=%d", errno);
8114fdc3d75SEnji Cooper 
8124fdc3d75SEnji Cooper 	sigemptyset(&ss);
8134fdc3d75SEnji Cooper 	sigaddset(&ss, SIGUSR1);
8144fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(sigprocmask(SIG_BLOCK, &ss, (sigset_t *)0) == 0,
8154fdc3d75SEnji Cooper 	    "sigprocmask failed; errno=%d", errno);
8164fdc3d75SEnji Cooper 
8174fdc3d75SEnji Cooper 	rv = fork();
8184fdc3d75SEnji Cooper 	ATF_REQUIRE_MSG(rv != -1, "fork failed; errno=%d", errno);
8194fdc3d75SEnji Cooper 	if (rv == 0) {
8204fdc3d75SEnji Cooper 		sigemptyset(&ss);
8214fdc3d75SEnji Cooper 		sigsuspend(&ss);
8224fdc3d75SEnji Cooper 
8234fdc3d75SEnji Cooper 		for (cp = region; cp < (char *)region + psize; cp++) {
8244fdc3d75SEnji Cooper 			if (*cp != '\151')
8254fdc3d75SEnji Cooper 				_exit(1);
8264fdc3d75SEnji Cooper 		}
8274fdc3d75SEnji Cooper 		if (lseek(desc, 0, SEEK_SET) == -1)
8284fdc3d75SEnji Cooper 			_exit(1);
8294fdc3d75SEnji Cooper 		for (i = 0; i < psize; i++) {
8304fdc3d75SEnji Cooper 			error = read(desc, &c, 1);
8314fdc3d75SEnji Cooper 			if (c != '\151')
8324fdc3d75SEnji Cooper 				_exit(1);
8334fdc3d75SEnji Cooper 		}
8344fdc3d75SEnji Cooper 		_exit(0);
8354fdc3d75SEnji Cooper 	} else {
8364fdc3d75SEnji Cooper 		int status;
8374fdc3d75SEnji Cooper 
8384fdc3d75SEnji Cooper 		memset(region, '\151', psize - 2);
8394fdc3d75SEnji Cooper 		error = pwrite(desc, region, 2, psize - 2);
8404fdc3d75SEnji Cooper 		if (error != 2) {
8414fdc3d75SEnji Cooper 			if (error >= 0)
8424fdc3d75SEnji Cooper 				atf_tc_fail("short write; %d bytes written",
8434fdc3d75SEnji Cooper 				    error);
8444fdc3d75SEnji Cooper 			else
8454fdc3d75SEnji Cooper 				atf_tc_fail("shmfd write");
8464fdc3d75SEnji Cooper 		}
8474fdc3d75SEnji Cooper 		kill(rv, SIGUSR1);
8484fdc3d75SEnji Cooper 		waitpid(rv, &status, 0);
8494fdc3d75SEnji Cooper 
8504fdc3d75SEnji Cooper 		if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
8514fdc3d75SEnji Cooper 			printf("Functionality test successful\n");
8524fdc3d75SEnji Cooper 		} else if (WIFEXITED(status)) {
8534fdc3d75SEnji Cooper 			atf_tc_fail("Child process exited with status %d",
8544fdc3d75SEnji Cooper 			    WEXITSTATUS(status));
8554fdc3d75SEnji Cooper 		} else {
8564fdc3d75SEnji Cooper 			atf_tc_fail("Child process terminated with %s",
8574fdc3d75SEnji Cooper 			    strsignal(WTERMSIG(status)));
8584fdc3d75SEnji Cooper 		}
8594fdc3d75SEnji Cooper 	}
86094ebd6f5SEnji Cooper 
86194ebd6f5SEnji Cooper 	ATF_REQUIRE_MSG(munmap(region, psize) == 0, "munmap failed; errno=%d",
86294ebd6f5SEnji Cooper 	    errno);
86394ebd6f5SEnji Cooper 	shm_unlink(test_path);
8644fdc3d75SEnji Cooper }
8654fdc3d75SEnji Cooper 
86695aa96f3SKyle Evans ATF_TC_WITHOUT_HEAD(cloexec);
86795aa96f3SKyle Evans ATF_TC_BODY(cloexec, tc)
86895aa96f3SKyle Evans {
86995aa96f3SKyle Evans 	int fd;
87095aa96f3SKyle Evans 
87195aa96f3SKyle Evans 	gen_test_path();
87295aa96f3SKyle Evans 
87395aa96f3SKyle Evans 	/* shm_open(2) is required to set FD_CLOEXEC */
87495aa96f3SKyle Evans 	fd = shm_open(SHM_ANON, O_RDWR, 0777);
87595aa96f3SKyle Evans 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
87695aa96f3SKyle Evans 	ATF_REQUIRE((fcntl(fd, F_GETFD) & FD_CLOEXEC) != 0);
87795aa96f3SKyle Evans 	close(fd);
87895aa96f3SKyle Evans 
87995aa96f3SKyle Evans 	/* Also make sure that named shm is correct */
88095aa96f3SKyle Evans 	fd = shm_open(test_path, O_CREAT | O_RDWR, 0600);
88195aa96f3SKyle Evans 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
88295aa96f3SKyle Evans 	ATF_REQUIRE((fcntl(fd, F_GETFD) & FD_CLOEXEC) != 0);
88395aa96f3SKyle Evans 	close(fd);
88495aa96f3SKyle Evans }
88595aa96f3SKyle Evans 
8865a391b57SKyle Evans ATF_TC_WITHOUT_HEAD(mode);
8875a391b57SKyle Evans ATF_TC_BODY(mode, tc)
8885a391b57SKyle Evans {
8895a391b57SKyle Evans 	struct stat st;
8905a391b57SKyle Evans 	int fd;
8915a391b57SKyle Evans 	mode_t restore_mask;
8925a391b57SKyle Evans 
8935a391b57SKyle Evans 	gen_test_path();
8945a391b57SKyle Evans 
8955a391b57SKyle Evans 	/* Remove inhibitions from umask */
8965a391b57SKyle Evans 	restore_mask = umask(0);
8975a391b57SKyle Evans 	fd = shm_open(test_path, O_CREAT | O_RDWR, 0600);
8985a391b57SKyle Evans 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
8995a391b57SKyle Evans 	ATF_REQUIRE(fstat(fd, &st) == 0);
9005a391b57SKyle Evans 	ATF_REQUIRE((st.st_mode & ACCESSPERMS) == 0600);
9015a391b57SKyle Evans 	close(fd);
9025a391b57SKyle Evans 	ATF_REQUIRE(shm_unlink(test_path) == 0);
9035a391b57SKyle Evans 
9045a391b57SKyle Evans 	fd = shm_open(test_path, O_CREAT | O_RDWR, 0660);
9055a391b57SKyle Evans 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
9065a391b57SKyle Evans 	ATF_REQUIRE(fstat(fd, &st) == 0);
9075a391b57SKyle Evans 	ATF_REQUIRE((st.st_mode & ACCESSPERMS) == 0660);
9085a391b57SKyle Evans 	close(fd);
9095a391b57SKyle Evans 	ATF_REQUIRE(shm_unlink(test_path) == 0);
9105a391b57SKyle Evans 
9115a391b57SKyle Evans 	fd = shm_open(test_path, O_CREAT | O_RDWR, 0666);
9125a391b57SKyle Evans 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
9135a391b57SKyle Evans 	ATF_REQUIRE(fstat(fd, &st) == 0);
9145a391b57SKyle Evans 	ATF_REQUIRE((st.st_mode & ACCESSPERMS) == 0666);
9155a391b57SKyle Evans 	close(fd);
9165a391b57SKyle Evans 	ATF_REQUIRE(shm_unlink(test_path) == 0);
9175a391b57SKyle Evans 
9185a391b57SKyle Evans 	umask(restore_mask);
9195a391b57SKyle Evans }
92095aa96f3SKyle Evans 
921*f1040532SKyle Evans ATF_TC_WITHOUT_HEAD(fallocate);
922*f1040532SKyle Evans ATF_TC_BODY(fallocate, tc)
923*f1040532SKyle Evans {
924*f1040532SKyle Evans 	struct stat st;
925*f1040532SKyle Evans 	int error, fd, sz;
926*f1040532SKyle Evans 
927*f1040532SKyle Evans 	/*
928*f1040532SKyle Evans 	 * Primitive test case for posix_fallocate with shmd.  Effectively
929*f1040532SKyle Evans 	 * expected to work like a smarter ftruncate that will grow the region
930*f1040532SKyle Evans 	 * as needed in a race-free way.
931*f1040532SKyle Evans 	 */
932*f1040532SKyle Evans 	fd = shm_open(SHM_ANON, O_RDWR, 0666);
933*f1040532SKyle Evans 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
934*f1040532SKyle Evans 	/* Set the initial size. */
935*f1040532SKyle Evans 	sz = 32;
936*f1040532SKyle Evans 	ATF_REQUIRE(ftruncate(fd, sz) == 0);
937*f1040532SKyle Evans 
938*f1040532SKyle Evans 	/* Now grow it. */
939*f1040532SKyle Evans 	error = 0;
940*f1040532SKyle Evans 	sz *= 2;
941*f1040532SKyle Evans 	ATF_REQUIRE_MSG((error = posix_fallocate(fd, 0, sz)) == 0,
942*f1040532SKyle Evans 	    "posix_fallocate failed; error=%d", error);
943*f1040532SKyle Evans 	ATF_REQUIRE(fstat(fd, &st) == 0);
944*f1040532SKyle Evans 	ATF_REQUIRE(st.st_size == sz);
945*f1040532SKyle Evans 	/* Attempt to shrink it; should succeed, but not change the size. */
946*f1040532SKyle Evans 	ATF_REQUIRE_MSG((error = posix_fallocate(fd, 0, sz / 2)) == 0,
947*f1040532SKyle Evans 	    "posix_fallocate failed; error=%d", error);
948*f1040532SKyle Evans 	ATF_REQUIRE(fstat(fd, &st) == 0);
949*f1040532SKyle Evans 	ATF_REQUIRE(st.st_size == sz);
950*f1040532SKyle Evans 	/* Grow it using an offset of sz and len of sz. */
951*f1040532SKyle Evans 	ATF_REQUIRE_MSG((error = posix_fallocate(fd, sz, sz)) == 0,
952*f1040532SKyle Evans 	    "posix_fallocate failed; error=%d", error);
953*f1040532SKyle Evans 	ATF_REQUIRE(fstat(fd, &st) == 0);
954*f1040532SKyle Evans 	ATF_REQUIRE(st.st_size == (sz * 2));
955*f1040532SKyle Evans 
956*f1040532SKyle Evans 	close(fd);
957*f1040532SKyle Evans }
958*f1040532SKyle Evans 
9594fdc3d75SEnji Cooper ATF_TP_ADD_TCS(tp)
9604fdc3d75SEnji Cooper {
9614fdc3d75SEnji Cooper 
9624fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, remap_object);
9639afb12baSDavid Bright 	ATF_TP_ADD_TC(tp, rename_from_anon);
9649afb12baSDavid Bright 	ATF_TP_ADD_TC(tp, rename_bad_path_pointer);
9659afb12baSDavid Bright 	ATF_TP_ADD_TC(tp, rename_from_nonexisting);
9669afb12baSDavid Bright 	ATF_TP_ADD_TC(tp, rename_to_anon);
9679afb12baSDavid Bright 	ATF_TP_ADD_TC(tp, rename_to_replace);
9689afb12baSDavid Bright 	ATF_TP_ADD_TC(tp, rename_to_noreplace);
9699afb12baSDavid Bright 	ATF_TP_ADD_TC(tp, rename_to_exchange);
9709afb12baSDavid Bright 	ATF_TP_ADD_TC(tp, rename_to_exchange_nonexisting);
9719afb12baSDavid Bright 	ATF_TP_ADD_TC(tp, rename_to_self);
9729afb12baSDavid Bright 	ATF_TP_ADD_TC(tp, rename_bad_flag);
9734fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, reopen_object);
9744fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, readonly_mmap_write);
9754fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, open_after_link);
9764fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, open_invalid_path);
9774fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, open_write_only);
9784fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, open_extra_flags);
9794fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, open_anon);
9804fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, open_anon_readonly);
9814fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, open_bad_path_pointer);
9824fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, open_path_too_long);
9834fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, open_nonexisting_object);
9844fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, open_create_existing_object);
9854fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, shm_functionality_across_fork);
9864fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, trunc_resets_object);
9874fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, unlink_bad_path_pointer);
9884fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, unlink_path_too_long);
9894fdc3d75SEnji Cooper 	ATF_TP_ADD_TC(tp, object_resize);
99095aa96f3SKyle Evans 	ATF_TP_ADD_TC(tp, cloexec);
9915a391b57SKyle Evans 	ATF_TP_ADD_TC(tp, mode);
992*f1040532SKyle Evans 	ATF_TP_ADD_TC(tp, fallocate);
9934fdc3d75SEnji Cooper 
9944fdc3d75SEnji Cooper 	return (atf_no_error());
9954fdc3d75SEnji Cooper }
996