1 /* 2 * Copyright (c) 2024 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29 #include <darwintest.h> 30 #include <darwintest_utils.h> 31 32 #include <errno.h> 33 #include <stdio.h> 34 #include <fcntl.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <sys/mman.h> 38 39 T_GLOBAL_META( 40 T_META_NAMESPACE("xnu.vm"), 41 T_META_RADAR_COMPONENT_NAME("xnu"), 42 T_META_RADAR_COMPONENT_VERSION("VM")); 43 44 T_DECL(direct_write_cow, 45 "test direct write() to file mapped with MAP_PRIVATE", T_META_TAG_VM_PREFERRED) 46 { 47 int fd; 48 int ret; 49 char tmpf[PATH_MAX] = ""; 50 char *map_shared_addr, *map_private_addr; 51 size_t file_size; 52 ssize_t num_bytes; 53 char *buf; 54 55 T_SETUPBEGIN; 56 57 strlcpy(tmpf, dt_tmpdir(), PATH_MAX); 58 strlcat(tmpf, "/cow_direct_write.txt", PATH_MAX); 59 T_LOG("file name: <%s>\n", tmpf); 60 fd = open(tmpf, O_RDWR | O_CREAT | O_TRUNC, 0644); 61 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, "open()"); 62 63 file_size = PAGE_SIZE; 64 ret = ftruncate(fd, (off_t) file_size); 65 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, "ftruncate()"); 66 67 ret = fcntl(fd, F_NOCACHE, true); 68 T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "fcntl(F_NOCACHE)"); 69 70 buf = valloc(file_size); 71 T_QUIET; T_ASSERT_NOTNULL(buf, "valloc()"); 72 73 memset(buf, 'a', file_size); 74 num_bytes = pwrite(fd, buf, file_size, 0); 75 T_QUIET; T_EXPECT_POSIX_SUCCESS(num_bytes, "write()"); 76 T_QUIET; T_EXPECT_EQ(num_bytes, (ssize_t) file_size, "wrote <file_size> bytes"); 77 78 map_shared_addr = mmap(NULL, file_size, PROT_READ, MAP_FILE | MAP_SHARED, fd, 0); 79 T_QUIET; T_ASSERT_POSIX_SUCCESS(map_shared_addr, "mmap(MAP_SHARE)"); 80 // T_ASSERT_EQ(map_addr[0], 'a', 1); /* that would pollute the buffer cache... */ 81 82 map_private_addr = mmap(NULL, file_size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0); 83 T_QUIET; T_ASSERT_POSIX_SUCCESS(map_private_addr, "mmap(MAP_PRIVATE)"); 84 // T_ASSERT_EQ(map_addr[0], 'a', 1); /* that would pollute the buffer cache... */ 85 86 T_SETUPEND; 87 88 memset(buf, 'b', file_size); 89 num_bytes = pwrite(fd, buf, file_size, 0); 90 T_QUIET; T_EXPECT_POSIX_SUCCESS(num_bytes, "write()"); 91 T_QUIET; T_EXPECT_EQ(num_bytes, (ssize_t) file_size, "wrote <file_size> bytes"); 92 93 T_ASSERT_EQ(map_shared_addr[0], 'b', "shared mapping was modified"); 94 T_ASSERT_EQ(map_private_addr[0], 'a', "private mapping was not modified"); 95 } 96