1 /* 2 * Copyright (c) International Business Machines Corp., 2001 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12 * the GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 /* 20 * Test Description: 21 * Verify that, mmap() succeeds when used to map a file where size of the 22 * file is not a multiple of the page size, the memory area beyond the end 23 * of the file to the end of the page is accessible. Also, verify that 24 * this area is all zeroed and the modifications done to this area are 25 * not written to the file. 26 * 27 * Expected Result: 28 * mmap() should succeed returning the address of the mapped region. 29 * The memory area beyond the end of file to the end of page should be 30 * filled with zero. 31 * The changes beyond the end of file should not get written to the file. 32 * 33 * HISTORY 34 * 07/2001 Ported by Wayne Boyer 35 */ 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <sys/types.h> 39 #include <errno.h> 40 #include <unistd.h> 41 #include <fcntl.h> 42 #include <string.h> 43 #include <signal.h> 44 #include <stdint.h> 45 #include <sys/stat.h> 46 #include <sys/mman.h> 47 #include <sys/shm.h> 48 49 #include "test.h" 50 51 #define TEMPFILE "mmapfile" 52 53 char *TCID = "mmap01"; 54 int TST_TOTAL = 1; 55 56 static char *addr; 57 static char *dummy; 58 static size_t page_sz; 59 static size_t file_sz; 60 static int fildes; 61 static char cmd_buffer[BUFSIZ]; 62 63 static void setup(void); 64 static void cleanup(void); 65 66 int main(int ac, char **av) 67 { 68 int lc; 69 70 tst_parse_opts(ac, av, NULL, NULL); 71 72 setup(); 73 74 for (lc = 0; TEST_LOOPING(lc); lc++) { 75 76 tst_count = 0; 77 78 /* 79 * Call mmap to map the temporary file beyond EOF 80 * with write access. 81 */ 82 errno = 0; 83 addr = mmap(NULL, page_sz, PROT_READ | PROT_WRITE, 84 MAP_FILE | MAP_SHARED, fildes, 0); 85 86 /* Check for the return value of mmap() */ 87 if (addr == MAP_FAILED) { 88 tst_resm(TFAIL | TERRNO, "mmap of %s failed", TEMPFILE); 89 continue; 90 } 91 92 /* 93 * Check if mapped memory area beyond EOF are 94 * zeros and changes beyond EOF are not written 95 * to file. 96 */ 97 if (memcmp(&addr[file_sz], dummy, page_sz - file_sz)) { 98 tst_brkm(TFAIL, cleanup, 99 "mapped memory area contains invalid " 100 "data"); 101 } 102 103 /* 104 * Initialize memory beyond file size 105 */ 106 addr[file_sz] = 'X'; 107 addr[file_sz + 1] = 'Y'; 108 addr[file_sz + 2] = 'Z'; 109 110 /* 111 * Synchronize the mapped memory region 112 * with the file. 113 */ 114 if (msync(addr, page_sz, MS_SYNC) != 0) { 115 tst_brkm(TFAIL | TERRNO, cleanup, 116 "failed to synchronize mapped file"); 117 } 118 119 /* 120 * Now, Search for the pattern 'XYZ' in the 121 * temporary file. The pattern should not be 122 * found and the return value should be 1. 123 */ 124 if (system(cmd_buffer) != 0) { 125 tst_resm(TPASS, 126 "Functionality of mmap() successful"); 127 } else { 128 tst_resm(TFAIL, 129 "Specified pattern found in file"); 130 } 131 132 /* Clean up things in case we are looping */ 133 /* Unmap the mapped memory */ 134 if (munmap(addr, page_sz) != 0) { 135 tst_brkm(TFAIL | TERRNO, NULL, "munmap failed"); 136 } 137 } 138 139 cleanup(); 140 tst_exit(); 141 } 142 143 static void setup(void) 144 { 145 struct stat stat_buf; 146 char Path_name[PATH_MAX]; 147 char write_buf[] = "hello world\n"; 148 149 tst_sig(FORK, DEF_HANDLER, cleanup); 150 151 TEST_PAUSE; 152 153 tst_tmpdir(); 154 155 /* Get the path of temporary file to be created */ 156 if (getcwd(Path_name, sizeof(Path_name)) == NULL) { 157 tst_brkm(TFAIL | TERRNO, cleanup, 158 "getcwd failed to get current working directory"); 159 } 160 161 /* Creat a temporary file used for mapping */ 162 if ((fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0666)) < 0) { 163 tst_brkm(TFAIL, cleanup, "opening %s failed", TEMPFILE); 164 } 165 166 /* Write some data into temporary file */ 167 if (write(fildes, write_buf, strlen(write_buf)) != strlen(write_buf)) { 168 tst_brkm(TFAIL, cleanup, "writing to %s", TEMPFILE); 169 } 170 171 /* Get the size of temporary file */ 172 if (stat(TEMPFILE, &stat_buf) < 0) { 173 tst_brkm(TFAIL | TERRNO, cleanup, "stat of %s failed", 174 TEMPFILE); 175 } 176 file_sz = stat_buf.st_size; 177 178 page_sz = getpagesize(); 179 180 /* Allocate and initialize dummy string of system page size bytes */ 181 if ((dummy = calloc(page_sz, sizeof(char))) == NULL) { 182 tst_brkm(TFAIL, cleanup, "calloc failed (dummy)"); 183 } 184 185 /* Create the command which will be executed in the test */ 186 sprintf(cmd_buffer, "grep XYZ %s/%s > /dev/null", Path_name, TEMPFILE); 187 } 188 189 static void cleanup(void) 190 { 191 close(fildes); 192 free(dummy); 193 tst_rmdir(); 194 } 195