2 * Copyright (c) 2006 Robert N. M. Watson
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/param.h>
32 #include <sys/resource.h>
34 #include <sys/syscall.h>
48 #define TEST_PATH_LEN 256
49 static char test_path[TEST_PATH_LEN];
50 static char test_path2[TEST_PATH_LEN];
51 static unsigned int test_path_idx = 0;
54 gen_a_test_path(char *path)
56 snprintf(path, TEST_PATH_LEN, "/%s/tmp.XXXXXX%d",
57 getenv("TMPDIR") == NULL ? "/tmp" : getenv("TMPDIR"),
62 ATF_REQUIRE_MSG(mkstemp(path) != -1,
63 "mkstemp failed; errno=%d", errno);
64 ATF_REQUIRE_MSG(unlink(path) == 0,
65 "unlink failed; errno=%d", errno);
71 gen_a_test_path(test_path);
77 gen_a_test_path(test_path2);
81 * Attempt a shm_open() that should fail with an expected error of 'error'.
84 shm_open_should_fail(const char *path, int flags, mode_t mode, int error)
88 fd = shm_open(path, flags, mode);
89 ATF_CHECK_MSG(fd == -1, "shm_open didn't fail");
90 ATF_CHECK_MSG(error == errno,
91 "shm_open didn't fail with expected errno; errno=%d; expected "
92 "errno=%d", errno, error);
96 * Attempt a shm_unlink() that should fail with an expected error of 'error'.
99 shm_unlink_should_fail(const char *path, int error)
102 ATF_CHECK_MSG(shm_unlink(path) == -1, "shm_unlink didn't fail");
103 ATF_CHECK_MSG(error == errno,
104 "shm_unlink didn't fail with expected errno; errno=%d; expected "
105 "errno=%d", errno, error);
109 * Open the test object and write a value to the first byte. Returns valid fd
110 * on success and -1 on failure.
113 scribble_object(const char *path, char value)
118 ATF_REQUIRE(0 < (pagesize = getpagesize()));
120 fd = shm_open(path, O_CREAT|O_EXCL|O_RDWR, 0777);
121 if (fd < 0 && errno == EEXIST) {
122 if (shm_unlink(test_path) < 0)
123 atf_tc_fail("shm_unlink");
124 fd = shm_open(test_path, O_CREAT | O_EXCL | O_RDWR, 0777);
127 atf_tc_fail("shm_open failed; errno=%d", errno);
128 if (ftruncate(fd, pagesize) < 0)
129 atf_tc_fail("ftruncate failed; errno=%d", errno);
131 page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
132 if (page == MAP_FAILED)
133 atf_tc_fail("mmap failed; errno=%d", errno);
136 ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",
143 * Fail the test case if the 'path' does not refer to an shm whose first byte
144 * is equal to expected_value
147 verify_object(const char *path, char expected_value)
153 ATF_REQUIRE(0 < (pagesize = getpagesize()));
155 fd = shm_open(path, O_RDONLY, 0777);
157 atf_tc_fail("shm_open failed in verify_object; errno=%d, path=%s",
160 page = mmap(0, pagesize, PROT_READ, MAP_SHARED, fd, 0);
161 if (page == MAP_FAILED)
162 atf_tc_fail("mmap(1)");
163 if (page[0] != expected_value)
164 atf_tc_fail("Renamed object has incorrect value; has"
165 "%d (0x%x, '%c'), expected %d (0x%x, '%c')\n",
166 page[0], page[0], isprint(page[0]) ? page[0] : ' ',
167 expected_value, expected_value,
168 isprint(expected_value) ? expected_value : ' ');
169 ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",
174 ATF_TC_WITHOUT_HEAD(remap_object);
175 ATF_TC_BODY(remap_object, tc)
180 ATF_REQUIRE(0 < (pagesize = getpagesize()));
183 fd = scribble_object(test_path, '1');
185 page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
186 if (page == MAP_FAILED)
187 atf_tc_fail("mmap(2) failed; errno=%d", errno);
190 atf_tc_fail("missing data ('%c' != '1')", page[0]);
193 ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",
196 ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,
197 "shm_unlink failed; errno=%d", errno);
200 ATF_TC_WITHOUT_HEAD(rename_from_anon);
201 ATF_TC_BODY(rename_from_anon, tc)
206 rc = shm_rename(SHM_ANON, test_path, 0);
208 atf_tc_fail("shm_rename from SHM_ANON succeeded unexpectedly");
211 ATF_TC_WITHOUT_HEAD(rename_bad_path_pointer);
212 ATF_TC_BODY(rename_bad_path_pointer, tc)
214 const char *bad_path;
217 bad_path = (const char *)0x1;
220 rc = shm_rename(test_path, bad_path, 0);
222 atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly");
224 rc = shm_rename(bad_path, test_path, 0);
226 atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly");
229 ATF_TC_WITHOUT_HEAD(rename_from_nonexisting);
230 ATF_TC_BODY(rename_from_nonexisting, tc)
236 rc = shm_rename(test_path, test_path2, 0);
238 atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly");
241 atf_tc_fail("Expected ENOENT to rename of nonexistent shm; got %d",
245 ATF_TC_WITHOUT_HEAD(rename_to_anon);
246 ATF_TC_BODY(rename_to_anon, tc)
251 rc = shm_rename(test_path, SHM_ANON, 0);
253 atf_tc_fail("shm_rename to SHM_ANON succeeded unexpectedly");
256 ATF_TC_WITHOUT_HEAD(rename_to_replace);
257 ATF_TC_BODY(rename_to_replace, tc)
263 // Some contents we can verify later
264 expected_value = 'g';
267 fd = scribble_object(test_path, expected_value);
270 // Give the other some different value so we can detect success
272 fd2 = scribble_object(test_path2, 'h');
275 ATF_REQUIRE_MSG(shm_rename(test_path, test_path2, 0) == 0,
276 "shm_rename failed; errno=%d", errno);
278 // Read back renamed; verify contents
279 verify_object(test_path2, expected_value);
282 ATF_TC_WITHOUT_HEAD(rename_to_noreplace);
283 ATF_TC_BODY(rename_to_noreplace, tc)
285 char expected_value_from;
286 char expected_value_to;
291 // Some contents we can verify later
292 expected_value_from = 'g';
294 fd_from = scribble_object(test_path, expected_value_from);
297 // Give the other some different value so we can detect success
298 expected_value_to = 'h';
300 fd_to = scribble_object(test_path2, expected_value_to);
303 rc = shm_rename(test_path, test_path2, SHM_RENAME_NOREPLACE);
304 ATF_REQUIRE_MSG((rc == -1) && (errno == EEXIST),
305 "shm_rename didn't fail as expected; errno: %d; return: %d", errno,
308 // Read back renamed; verify contents
309 verify_object(test_path2, expected_value_to);
312 ATF_TC_WITHOUT_HEAD(rename_to_exchange);
313 ATF_TC_BODY(rename_to_exchange, tc)
315 char expected_value_from;
316 char expected_value_to;
320 // Some contents we can verify later
321 expected_value_from = 'g';
323 fd_from = scribble_object(test_path, expected_value_from);
326 // Give the other some different value so we can detect success
327 expected_value_to = 'h';
329 fd_to = scribble_object(test_path2, expected_value_to);
332 ATF_REQUIRE_MSG(shm_rename(test_path, test_path2,
333 SHM_RENAME_EXCHANGE) == 0,
334 "shm_rename failed; errno=%d", errno);
336 // Read back renamed; verify contents
337 verify_object(test_path, expected_value_to);
338 verify_object(test_path2, expected_value_from);
341 ATF_TC_WITHOUT_HEAD(rename_to_exchange_nonexisting);
342 ATF_TC_BODY(rename_to_exchange_nonexisting, tc)
344 char expected_value_from;
347 // Some contents we can verify later
348 expected_value_from = 'g';
350 fd_from = scribble_object(test_path, expected_value_from);
355 ATF_REQUIRE_MSG(shm_rename(test_path, test_path2,
356 SHM_RENAME_EXCHANGE) == 0,
357 "shm_rename failed; errno=%d", errno);
359 // Read back renamed; verify contents
360 verify_object(test_path2, expected_value_from);
363 ATF_TC_WITHOUT_HEAD(rename_to_self);
364 ATF_TC_BODY(rename_to_self, tc)
369 expected_value = 't';
372 fd = scribble_object(test_path, expected_value);
375 ATF_REQUIRE_MSG(shm_rename(test_path, test_path, 0) == 0,
376 "shm_rename failed; errno=%d", errno);
378 verify_object(test_path, expected_value);
381 ATF_TC_WITHOUT_HEAD(rename_bad_flag);
382 ATF_TC_BODY(rename_bad_flag, tc)
387 /* Make sure we don't fail out due to ENOENT */
390 fd = scribble_object(test_path, 'd');
392 fd = scribble_object(test_path2, 'd');
396 * Note: if we end up with enough flags that we use all the bits,
397 * then remove this test completely.
399 rc = shm_rename(test_path, test_path2, INT_MIN);
400 ATF_REQUIRE_MSG((rc == -1) && (errno == EINVAL),
401 "shm_rename should have failed with EINVAL; got: return=%d, "
402 "errno=%d", rc, errno);
405 ATF_TC_WITHOUT_HEAD(reopen_object);
406 ATF_TC_BODY(reopen_object, tc)
411 ATF_REQUIRE(0 < (pagesize = getpagesize()));
414 fd = scribble_object(test_path, '1');
417 fd = shm_open(test_path, O_RDONLY, 0777);
419 atf_tc_fail("shm_open(2) failed; errno=%d", errno);
421 page = mmap(0, pagesize, PROT_READ, MAP_SHARED, fd, 0);
422 if (page == MAP_FAILED)
423 atf_tc_fail("mmap(2) failed; errno=%d", errno);
426 atf_tc_fail("missing data ('%c' != '1')", page[0]);
428 ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",
431 ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,
432 "shm_unlink failed; errno=%d", errno);
435 ATF_TC_WITHOUT_HEAD(readonly_mmap_write);
436 ATF_TC_BODY(readonly_mmap_write, tc)
441 ATF_REQUIRE(0 < (pagesize = getpagesize()));
445 fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777);
446 ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
448 /* PROT_WRITE should fail with EACCES. */
449 page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
450 if (page != MAP_FAILED)
451 atf_tc_fail("mmap(PROT_WRITE) succeeded unexpectedly");
454 atf_tc_fail("mmap(PROT_WRITE) didn't fail with EACCES; "
458 ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,
459 "shm_unlink failed; errno=%d", errno);
462 ATF_TC_WITHOUT_HEAD(open_after_link);
463 ATF_TC_BODY(open_after_link, tc)
469 fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777);
470 ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno);
473 ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, "shm_unlink failed: %d",
476 shm_open_should_fail(test_path, O_RDONLY, 0777, ENOENT);
479 ATF_TC_WITHOUT_HEAD(open_invalid_path);
480 ATF_TC_BODY(open_invalid_path, tc)
483 shm_open_should_fail("blah", O_RDONLY, 0777, EINVAL);
486 ATF_TC_WITHOUT_HEAD(open_write_only);
487 ATF_TC_BODY(open_write_only, tc)
492 shm_open_should_fail(test_path, O_WRONLY, 0777, EINVAL);
495 ATF_TC_WITHOUT_HEAD(open_extra_flags);
496 ATF_TC_BODY(open_extra_flags, tc)
501 shm_open_should_fail(test_path, O_RDONLY | O_DIRECT, 0777, EINVAL);
504 ATF_TC_WITHOUT_HEAD(open_anon);
505 ATF_TC_BODY(open_anon, tc)
509 fd = shm_open(SHM_ANON, O_RDWR, 0777);
510 ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
514 ATF_TC_WITHOUT_HEAD(open_anon_readonly);
515 ATF_TC_BODY(open_anon_readonly, tc)
518 shm_open_should_fail(SHM_ANON, O_RDONLY, 0777, EINVAL);
521 ATF_TC_WITHOUT_HEAD(open_bad_path_pointer);
522 ATF_TC_BODY(open_bad_path_pointer, tc)
525 shm_open_should_fail((char *)1024, O_RDONLY, 0777, EFAULT);
528 ATF_TC_WITHOUT_HEAD(open_path_too_long);
529 ATF_TC_BODY(open_path_too_long, tc)
533 page = malloc(MAXPATHLEN + 1);
534 memset(page, 'a', MAXPATHLEN);
535 page[MAXPATHLEN] = '\0';
536 shm_open_should_fail(page, O_RDONLY, 0777, ENAMETOOLONG);
540 ATF_TC_WITHOUT_HEAD(open_nonexisting_object);
541 ATF_TC_BODY(open_nonexisting_object, tc)
544 shm_open_should_fail("/notreallythere", O_RDONLY, 0777, ENOENT);
547 ATF_TC_WITHOUT_HEAD(open_create_existing_object);
548 ATF_TC_BODY(open_create_existing_object, tc)
554 fd = shm_open(test_path, O_RDONLY|O_CREAT, 0777);
555 ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
558 shm_open_should_fail(test_path, O_RDONLY|O_CREAT|O_EXCL,
561 ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,
562 "shm_unlink failed; errno=%d", errno);
565 ATF_TC_WITHOUT_HEAD(trunc_resets_object);
566 ATF_TC_BODY(trunc_resets_object, tc)
573 /* Create object and set size to 1024. */
574 fd = shm_open(test_path, O_RDWR | O_CREAT, 0777);
575 ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno);
576 ATF_REQUIRE_MSG(ftruncate(fd, 1024) != -1,
577 "ftruncate failed; errno=%d", errno);
578 ATF_REQUIRE_MSG(fstat(fd, &sb) != -1,
579 "fstat(1) failed; errno=%d", errno);
580 ATF_REQUIRE_MSG(sb.st_size == 1024, "size %d != 1024", (int)sb.st_size);
583 /* Open with O_TRUNC which should reset size to 0. */
584 fd = shm_open(test_path, O_RDWR | O_TRUNC, 0777);
585 ATF_REQUIRE_MSG(fd >= 0, "shm_open(2) failed; errno=%d", errno);
586 ATF_REQUIRE_MSG(fstat(fd, &sb) != -1,
587 "fstat(2) failed; errno=%d", errno);
588 ATF_REQUIRE_MSG(sb.st_size == 0,
589 "size was not 0 after truncation: %d", (int)sb.st_size);
591 ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,
592 "shm_unlink failed; errno=%d", errno);
595 ATF_TC_WITHOUT_HEAD(unlink_bad_path_pointer);
596 ATF_TC_BODY(unlink_bad_path_pointer, tc)
599 shm_unlink_should_fail((char *)1024, EFAULT);
602 ATF_TC_WITHOUT_HEAD(unlink_path_too_long);
603 ATF_TC_BODY(unlink_path_too_long, tc)
607 page = malloc(MAXPATHLEN + 1);
608 memset(page, 'a', MAXPATHLEN);
609 page[MAXPATHLEN] = '\0';
610 shm_unlink_should_fail(page, ENAMETOOLONG);
614 ATF_TC_WITHOUT_HEAD(object_resize);
615 ATF_TC_BODY(object_resize, tc)
620 int fd, pagesize, status;
622 ATF_REQUIRE(0 < (pagesize = getpagesize()));
624 /* Start off with a size of a single page. */
625 fd = shm_open(SHM_ANON, O_CREAT|O_RDWR, 0777);
627 atf_tc_fail("shm_open failed; errno=%d", errno);
629 if (ftruncate(fd, pagesize) < 0)
630 atf_tc_fail("ftruncate(1) failed; errno=%d", errno);
632 if (fstat(fd, &sb) < 0)
633 atf_tc_fail("fstat(1) failed; errno=%d", errno);
635 if (sb.st_size != pagesize)
636 atf_tc_fail("first resize failed (%d != %d)",
637 (int)sb.st_size, pagesize);
639 /* Write a '1' to the first byte. */
640 page = mmap(0, pagesize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
641 if (page == MAP_FAILED)
642 atf_tc_fail("mmap(1)");
646 ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",
649 /* Grow the object to 2 pages. */
650 if (ftruncate(fd, pagesize * 2) < 0)
651 atf_tc_fail("ftruncate(2) failed; errno=%d", errno);
653 if (fstat(fd, &sb) < 0)
654 atf_tc_fail("fstat(2) failed; errno=%d", errno);
656 if (sb.st_size != pagesize * 2)
657 atf_tc_fail("second resize failed (%d != %d)",
658 (int)sb.st_size, pagesize * 2);
660 /* Check for '1' at the first byte. */
661 page = mmap(0, pagesize * 2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
662 if (page == MAP_FAILED)
663 atf_tc_fail("mmap(2) failed; errno=%d", errno);
666 atf_tc_fail("'%c' != '1'", page[0]);
668 /* Write a '2' at the start of the second page. */
669 page[pagesize] = '2';
671 /* Shrink the object back to 1 page. */
672 if (ftruncate(fd, pagesize) < 0)
673 atf_tc_fail("ftruncate(3) failed; errno=%d", errno);
675 if (fstat(fd, &sb) < 0)
676 atf_tc_fail("fstat(3) failed; errno=%d", errno);
678 if (sb.st_size != pagesize)
679 atf_tc_fail("third resize failed (%d != %d)",
680 (int)sb.st_size, pagesize);
683 * Fork a child process to make sure the second page is no
688 atf_tc_fail("fork failed; errno=%d", errno);
694 /* Don't generate a core dump. */
695 ATF_REQUIRE(getrlimit(RLIMIT_CORE, &lim) == 0);
697 ATF_REQUIRE(setrlimit(RLIMIT_CORE, &lim) == 0);
700 * The previous ftruncate(2) shrunk the backing object
701 * so that this address is no longer valid, so reading
702 * from it should trigger a SIGBUS.
705 fprintf(stderr, "child: page 1: '%c'\n", c);
709 if (wait(&status) < 0)
710 atf_tc_fail("wait failed; errno=%d", errno);
712 if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGBUS)
713 atf_tc_fail("child terminated with status %x", status);
715 /* Grow the object back to 2 pages. */
716 if (ftruncate(fd, pagesize * 2) < 0)
717 atf_tc_fail("ftruncate(2) failed; errno=%d", errno);
719 if (fstat(fd, &sb) < 0)
720 atf_tc_fail("fstat(2) failed; errno=%d", errno);
722 if (sb.st_size != pagesize * 2)
723 atf_tc_fail("fourth resize failed (%d != %d)",
724 (int)sb.st_size, pagesize);
727 * Note that the mapping at 'page' for the second page is
728 * still valid, and now that the shm object has been grown
729 * back up to 2 pages, there is now memory backing this page
730 * so the read will work. However, the data should be zero
731 * rather than '2' as the old data was thrown away when the
732 * object was shrunk and the new pages when an object are
733 * grown are zero-filled.
735 if (page[pagesize] != 0)
736 atf_tc_fail("invalid data at %d: %x != 0",
737 pagesize, (int)page[pagesize]);
742 /* Signal handler which does nothing. */
744 ignoreit(int sig __unused)
749 ATF_TC_WITHOUT_HEAD(shm_functionality_across_fork);
750 ATF_TC_BODY(shm_functionality_across_fork, tc)
760 #ifndef _POSIX_SHARED_MEMORY_OBJECTS
761 printf("_POSIX_SHARED_MEMORY_OBJECTS is undefined\n");
763 printf("_POSIX_SHARED_MEMORY_OBJECTS is defined as %ld\n",
764 (long)_POSIX_SHARED_MEMORY_OBJECTS - 0);
765 if (_POSIX_SHARED_MEMORY_OBJECTS - 0 == -1)
766 printf("***Indicates this feature may be unsupported!\n");
769 scval = sysconf(_SC_SHARED_MEMORY_OBJECTS);
770 if (scval == -1 && errno != 0) {
771 atf_tc_fail("sysconf(_SC_SHARED_MEMORY_OBJECTS) failed; "
774 printf("sysconf(_SC_SHARED_MEMORY_OBJECTS) returns %ld\n",
777 printf("***Indicates this feature is unsupported!\n");
781 scval = sysconf(_SC_PAGESIZE);
782 if (scval == -1 && errno != 0) {
783 atf_tc_fail("sysconf(_SC_PAGESIZE) failed; errno=%d", errno);
784 } else if (scval <= 0) {
785 fprintf(stderr, "bogus return from sysconf(_SC_PAGESIZE): %ld",
789 printf("sysconf(_SC_PAGESIZE) returns %ld\n", scval);
794 desc = shm_open(test_path, O_EXCL | O_CREAT | O_RDWR, 0600);
796 ATF_REQUIRE_MSG(desc >= 0, "shm_open failed; errno=%d", errno);
797 ATF_REQUIRE_MSG(shm_unlink(test_path) == 0,
798 "shm_unlink failed; errno=%d", errno);
799 ATF_REQUIRE_MSG(ftruncate(desc, (off_t)psize) != -1,
800 "ftruncate failed; errno=%d", errno);
802 region = mmap(NULL, psize, PROT_READ | PROT_WRITE, MAP_SHARED, desc, 0);
803 ATF_REQUIRE_MSG(region != MAP_FAILED, "mmap failed; errno=%d", errno);
804 memset(region, '\377', psize);
807 sa.sa_handler = ignoreit;
808 sigemptyset(&sa.sa_mask);
809 ATF_REQUIRE_MSG(sigaction(SIGUSR1, &sa, (struct sigaction *)0) == 0,
810 "sigaction failed; errno=%d", errno);
813 sigaddset(&ss, SIGUSR1);
814 ATF_REQUIRE_MSG(sigprocmask(SIG_BLOCK, &ss, (sigset_t *)0) == 0,
815 "sigprocmask failed; errno=%d", errno);
818 ATF_REQUIRE_MSG(rv != -1, "fork failed; errno=%d", errno);
823 for (cp = region; cp < (char *)region + psize; cp++) {
827 if (lseek(desc, 0, SEEK_SET) == -1)
829 for (i = 0; i < psize; i++) {
830 error = read(desc, &c, 1);
838 memset(region, '\151', psize - 2);
839 error = pwrite(desc, region, 2, psize - 2);
842 atf_tc_fail("short write; %d bytes written",
845 atf_tc_fail("shmfd write");
848 waitpid(rv, &status, 0);
850 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
851 printf("Functionality test successful\n");
852 } else if (WIFEXITED(status)) {
853 atf_tc_fail("Child process exited with status %d",
854 WEXITSTATUS(status));
856 atf_tc_fail("Child process terminated with %s",
857 strsignal(WTERMSIG(status)));
861 ATF_REQUIRE_MSG(munmap(region, psize) == 0, "munmap failed; errno=%d",
863 shm_unlink(test_path);
866 ATF_TC_WITHOUT_HEAD(cloexec);
867 ATF_TC_BODY(cloexec, tc)
873 /* shm_open(2) is required to set FD_CLOEXEC */
874 fd = shm_open(SHM_ANON, O_RDWR, 0777);
875 ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
876 ATF_REQUIRE((fcntl(fd, F_GETFD) & FD_CLOEXEC) != 0);
879 /* Also make sure that named shm is correct */
880 fd = shm_open(test_path, O_CREAT | O_RDWR, 0600);
881 ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
882 ATF_REQUIRE((fcntl(fd, F_GETFD) & FD_CLOEXEC) != 0);
886 ATF_TC_WITHOUT_HEAD(mode);
887 ATF_TC_BODY(mode, tc)
895 /* Remove inhibitions from umask */
896 restore_mask = umask(0);
897 fd = shm_open(test_path, O_CREAT | O_RDWR, 0600);
898 ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
899 ATF_REQUIRE(fstat(fd, &st) == 0);
900 ATF_REQUIRE((st.st_mode & ACCESSPERMS) == 0600);
902 ATF_REQUIRE(shm_unlink(test_path) == 0);
904 fd = shm_open(test_path, O_CREAT | O_RDWR, 0660);
905 ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
906 ATF_REQUIRE(fstat(fd, &st) == 0);
907 ATF_REQUIRE((st.st_mode & ACCESSPERMS) == 0660);
909 ATF_REQUIRE(shm_unlink(test_path) == 0);
911 fd = shm_open(test_path, O_CREAT | O_RDWR, 0666);
912 ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
913 ATF_REQUIRE(fstat(fd, &st) == 0);
914 ATF_REQUIRE((st.st_mode & ACCESSPERMS) == 0666);
916 ATF_REQUIRE(shm_unlink(test_path) == 0);
921 ATF_TC_WITHOUT_HEAD(fallocate);
922 ATF_TC_BODY(fallocate, tc)
928 * Primitive test case for posix_fallocate with shmd. Effectively
929 * expected to work like a smarter ftruncate that will grow the region
930 * as needed in a race-free way.
932 fd = shm_open(SHM_ANON, O_RDWR, 0666);
933 ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
934 /* Set the initial size. */
936 ATF_REQUIRE(ftruncate(fd, sz) == 0);
941 ATF_REQUIRE_MSG((error = posix_fallocate(fd, 0, sz)) == 0,
942 "posix_fallocate failed; error=%d", error);
943 ATF_REQUIRE(fstat(fd, &st) == 0);
944 ATF_REQUIRE(st.st_size == sz);
945 /* Attempt to shrink it; should succeed, but not change the size. */
946 ATF_REQUIRE_MSG((error = posix_fallocate(fd, 0, sz / 2)) == 0,
947 "posix_fallocate failed; error=%d", error);
948 ATF_REQUIRE(fstat(fd, &st) == 0);
949 ATF_REQUIRE(st.st_size == sz);
950 /* Grow it using an offset of sz and len of sz. */
951 ATF_REQUIRE_MSG((error = posix_fallocate(fd, sz, sz)) == 0,
952 "posix_fallocate failed; error=%d", error);
953 ATF_REQUIRE(fstat(fd, &st) == 0);
954 ATF_REQUIRE(st.st_size == (sz * 2));
962 ATF_TP_ADD_TC(tp, remap_object);
963 ATF_TP_ADD_TC(tp, rename_from_anon);
964 ATF_TP_ADD_TC(tp, rename_bad_path_pointer);
965 ATF_TP_ADD_TC(tp, rename_from_nonexisting);
966 ATF_TP_ADD_TC(tp, rename_to_anon);
967 ATF_TP_ADD_TC(tp, rename_to_replace);
968 ATF_TP_ADD_TC(tp, rename_to_noreplace);
969 ATF_TP_ADD_TC(tp, rename_to_exchange);
970 ATF_TP_ADD_TC(tp, rename_to_exchange_nonexisting);
971 ATF_TP_ADD_TC(tp, rename_to_self);
972 ATF_TP_ADD_TC(tp, rename_bad_flag);
973 ATF_TP_ADD_TC(tp, reopen_object);
974 ATF_TP_ADD_TC(tp, readonly_mmap_write);
975 ATF_TP_ADD_TC(tp, open_after_link);
976 ATF_TP_ADD_TC(tp, open_invalid_path);
977 ATF_TP_ADD_TC(tp, open_write_only);
978 ATF_TP_ADD_TC(tp, open_extra_flags);
979 ATF_TP_ADD_TC(tp, open_anon);
980 ATF_TP_ADD_TC(tp, open_anon_readonly);
981 ATF_TP_ADD_TC(tp, open_bad_path_pointer);
982 ATF_TP_ADD_TC(tp, open_path_too_long);
983 ATF_TP_ADD_TC(tp, open_nonexisting_object);
984 ATF_TP_ADD_TC(tp, open_create_existing_object);
985 ATF_TP_ADD_TC(tp, shm_functionality_across_fork);
986 ATF_TP_ADD_TC(tp, trunc_resets_object);
987 ATF_TP_ADD_TC(tp, unlink_bad_path_pointer);
988 ATF_TP_ADD_TC(tp, unlink_path_too_long);
989 ATF_TP_ADD_TC(tp, object_resize);
990 ATF_TP_ADD_TC(tp, cloexec);
991 ATF_TP_ADD_TC(tp, mode);
992 ATF_TP_ADD_TC(tp, fallocate);
994 return (atf_no_error());