blob: b1c7c4a2651562161c14285961be3f07a45f7e78 [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
plars865695b2001-08-27 22:15:12 +000018 */
19
20/*
21 * Test Name: mmap01
22 *
23 * Test Description:
24 * Verify that, mmap() succeeds when used to map a file where size of the
25 * file is not a multiple of the page size, the memory area beyond the end
26 * of the file to the end of the page is accessible. Also, verify that
27 * this area is all zeroed and the modifications done to this area are
28 * not written to the file.
29 *
30 * Expected Result:
31 * mmap() should succeed returning the address of the mapped region.
32 * The memory area beyond the end of file to the end of page should be
33 * filled with zero.
34 * The changes beyond the end of file should not get written to the file.
35 *
36 * Algorithm:
37 * Setup:
38 * Setup signal handling.
39 * Pause for SIGUSR1 if option specified.
40 * Create temporary directory.
41 *
42 * Test:
43 * Loop if the proper options are given.
44 * Execute system call
45 * Check return code, if system call failed (return=-1)
subrata_modak56207ce2009-03-23 13:35:39 +000046 * Log the errno and Issue a FAIL message.
plars865695b2001-08-27 22:15:12 +000047 * Otherwise,
subrata_modak56207ce2009-03-23 13:35:39 +000048 * Verify the Functionality of system call
plars865695b2001-08-27 22:15:12 +000049 * if successful,
subrata_modak56207ce2009-03-23 13:35:39 +000050 * Issue Functionality-Pass message.
plars865695b2001-08-27 22:15:12 +000051 * Otherwise,
52 * Issue Functionality-Fail message.
53 * Cleanup:
54 * Print timing stats if options given
55 * Delete the temporary directory created.
56 *
57 * Usage: <for command-line>
58 * mmap01 [-c n] [-f] [-i n] [-I x] [-P x] [-t]
59 * where, -c n : Run n copies concurrently.
60 * -f : Turn off functionality Testing.
61 * -i n : Execute test n times.
62 * -I x : Execute test for x seconds.
63 * -P x : Pause for x seconds between iterations.
64 * -t : Turn on syscall timing.
65 *
66 * HISTORY
67 * 07/2001 Ported by Wayne Boyer
68 *
69 * RESTRICTIONS:
70 * None.
71 */
72
73#include <stdio.h>
74#include <stdlib.h>
75#include <sys/types.h>
76#include <errno.h>
77#include <unistd.h>
78#include <fcntl.h>
79#include <string.h>
80#include <signal.h>
plars85cbba32002-09-25 16:54:54 +000081#include <stdint.h>
plars865695b2001-08-27 22:15:12 +000082#include <sys/stat.h>
83#include <sys/mman.h>
subrata_modakc3270662008-05-02 06:28:13 +000084#include <sys/shm.h>
plars865695b2001-08-27 22:15:12 +000085
86#include "test.h"
87#include "usctest.h"
88
89#define TEMPFILE "mmapfile"
90
subrata_modak56207ce2009-03-23 13:35:39 +000091char *TCID = "mmap01"; /* Test program identifier. */
92int TST_TOTAL = 1; /* Total number of test cases. */
plars865695b2001-08-27 22:15:12 +000093char *addr; /* addr of memory mapped region */
94char *dummy; /* dummy string */
95size_t page_sz; /* system page size */
96size_t file_sz; /* mapped file size */
97int fildes; /* file descriptor for tempfile */
Garrett Cooper11d51042010-11-22 20:47:29 -080098char cmd_buffer[BUFSIZ]; /* command buffer to hold test command */
plars865695b2001-08-27 22:15:12 +000099
100void setup(); /* Main setup function of test */
101void cleanup(); /* cleanup function for the test */
102
subrata_modak56207ce2009-03-23 13:35:39 +0000103int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +0000104{
Cyril Hrubis89af32a2012-10-24 16:39:11 +0200105 int lc;
106 char *msg;
subrata_modakbdbaec52009-02-26 12:14:51 +0000107
plars865695b2001-08-27 22:15:12 +0000108 /* Parse standard options given to run the test. */
Garrett Cooper11d51042010-11-22 20:47:29 -0800109 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
plars865695b2001-08-27 22:15:12 +0000110 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
plars865695b2001-08-27 22:15:12 +0000111
plars865695b2001-08-27 22:15:12 +0000112 setup();
113
plars865695b2001-08-27 22:15:12 +0000114 for (lc = 0; TEST_LOOPING(lc); lc++) {
Garrett Cooper2c282152010-12-16 00:55:50 -0800115
subrata_modak56207ce2009-03-23 13:35:39 +0000116 Tst_count = 0;
plars865695b2001-08-27 22:15:12 +0000117
subrata_modak4bb656a2009-02-26 12:02:09 +0000118 /*
plars865695b2001-08-27 22:15:12 +0000119 * Call mmap to map the temporary file beyond EOF
subrata_modak56207ce2009-03-23 13:35:39 +0000120 * with write access.
plars865695b2001-08-27 22:15:12 +0000121 */
robbiewd5c21122002-03-22 16:22:40 +0000122 errno = 0;
123 addr = mmap(addr, page_sz, PROT_READ | PROT_WRITE,
subrata_modak56207ce2009-03-23 13:35:39 +0000124 MAP_FILE | MAP_SHARED | MAP_FIXED, fildes, 0);
plars865695b2001-08-27 22:15:12 +0000125
126 /* Check for the return value of mmap() */
robbiewd5c21122002-03-22 16:22:40 +0000127 if (addr == MAP_FAILED) {
Garrett Cooper11d51042010-11-22 20:47:29 -0800128 tst_resm(TFAIL|TERRNO, "mmap of %s failed", TEMPFILE);
plars865695b2001-08-27 22:15:12 +0000129 continue;
130 }
131 /*
132 * Perform functional verification if test
133 * executed without (-f) option.
134 */
135 if (STD_FUNCTIONAL_TEST) {
plars865695b2001-08-27 22:15:12 +0000136 /*
137 * Check if mapped memory area beyond EOF are
138 * zeros and changes beyond EOF are not written
139 * to file.
140 */
141 if (memcmp(&addr[file_sz], dummy, page_sz - file_sz)) {
Garrett Cooper11d51042010-11-22 20:47:29 -0800142 tst_brkm(TFAIL, cleanup,
143 "mapped memory area contains invalid "
144 "data");
plars865695b2001-08-27 22:15:12 +0000145 }
146
147 /*
148 * Initialize memory beyond file size
149 */
150 addr[file_sz] = 'X';
151 addr[file_sz + 1] = 'Y';
152 addr[file_sz + 2] = 'Z';
153
154 /*
155 * Synchronize the mapped memory region
156 * with the file.
157 */
158 if (msync(addr, page_sz, MS_SYNC) != 0) {
Garrett Cooper11d51042010-11-22 20:47:29 -0800159 tst_brkm(TFAIL|TERRNO, cleanup,
160 "failed to synchronize mapped file");
plars865695b2001-08-27 22:15:12 +0000161 }
162
163 /*
164 * Now, Search for the pattern 'XYZ' in the
165 * temporary file. The pattern should not be
166 * found and the return value should be 1.
167 */
Garrett Cooper11d51042010-11-22 20:47:29 -0800168 if (system(cmd_buffer) != 0) {
plars865695b2001-08-27 22:15:12 +0000169 tst_resm(TPASS,
Garrett Cooper11d51042010-11-22 20:47:29 -0800170 "Functionality of mmap() successful");
plars865695b2001-08-27 22:15:12 +0000171 } else {
172 tst_resm(TFAIL,
Garrett Cooper11d51042010-11-22 20:47:29 -0800173 "Specified pattern found in file");
plars865695b2001-08-27 22:15:12 +0000174 }
175 } else {
176 tst_resm(TPASS, "call succeeded");
177 }
178
179 /* Clean up things in case we are looping */
180 /* Unmap the mapped memory */
181 if (munmap(addr, page_sz) != 0) {
Garrett Cooper11d51042010-11-22 20:47:29 -0800182 tst_brkm(TFAIL|TERRNO, NULL, "munmap failed");
plars865695b2001-08-27 22:15:12 +0000183 }
Garrett Cooper2c282152010-12-16 00:55:50 -0800184 }
plars865695b2001-08-27 22:15:12 +0000185
plars865695b2001-08-27 22:15:12 +0000186 cleanup();
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800187 tst_exit();
Garrett Cooper2c282152010-12-16 00:55:50 -0800188
189}
plars865695b2001-08-27 22:15:12 +0000190
191/*
192 * setup() - performs all ONE TIME setup for this test.
193 *
subrata_modak56207ce2009-03-23 13:35:39 +0000194 * Get system page size, allocate and initialize the string dummy.
195 * Initialize addr such that it is more than one page below the break
196 * address of the process, and initialize one page region from addr
197 * with char 'A'.
198 * Creat a temporary directory and a file under it.
199 * Write some known data into file and get the size of the file.
plars865695b2001-08-27 22:15:12 +0000200 */
subrata_modak56207ce2009-03-23 13:35:39 +0000201void setup()
plars865695b2001-08-27 22:15:12 +0000202{
203 struct stat stat_buf;
subrata_modak56207ce2009-03-23 13:35:39 +0000204 char Path_name[PATH_MAX]; /* pathname of temporary file */
plars865695b2001-08-27 22:15:12 +0000205 char write_buf[] = "hello world\n";
206
plars865695b2001-08-27 22:15:12 +0000207 tst_sig(FORK, DEF_HANDLER, cleanup);
208
plars865695b2001-08-27 22:15:12 +0000209 TEST_PAUSE;
210
plars865695b2001-08-27 22:15:12 +0000211 tst_tmpdir();
212
213 /* Get the path of temporary file to be created */
214 if (getcwd(Path_name, sizeof(Path_name)) == NULL) {
Garrett Cooper11d51042010-11-22 20:47:29 -0800215 tst_brkm(TFAIL|TERRNO, cleanup,
216 "getcwd failed to get current working directory");
plars865695b2001-08-27 22:15:12 +0000217 }
218
219 /* Creat a temporary file used for mapping */
220 if ((fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0666)) < 0) {
Garrett Cooper11d51042010-11-22 20:47:29 -0800221 tst_brkm(TFAIL, cleanup, "opening %s failed", TEMPFILE);
plars865695b2001-08-27 22:15:12 +0000222 }
223
224 /* Write some data into temporary file */
225 if (write(fildes, write_buf, strlen(write_buf)) != strlen(write_buf)) {
Garrett Cooper11d51042010-11-22 20:47:29 -0800226 tst_brkm(TFAIL, cleanup, "writing to %s", TEMPFILE);
plars865695b2001-08-27 22:15:12 +0000227 }
subrata_modakbdbaec52009-02-26 12:14:51 +0000228
plars865695b2001-08-27 22:15:12 +0000229 /* Get the size of temporary file */
230 if (stat(TEMPFILE, &stat_buf) < 0) {
Garrett Cooper11d51042010-11-22 20:47:29 -0800231 tst_brkm(TFAIL|TERRNO, cleanup, "stat of %s failed",
232 TEMPFILE);
plars865695b2001-08-27 22:15:12 +0000233 }
234 file_sz = stat_buf.st_size;
235
236 /* Get the system page size */
237 if ((page_sz = getpagesize()) < 0) {
238 tst_brkm(TFAIL, cleanup,
Garrett Cooper11d51042010-11-22 20:47:29 -0800239 "getpagesize() fails to get system page size");
plars865695b2001-08-27 22:15:12 +0000240 }
241
242 /* Allocate and initialize dummy string of system page size bytes */
243 if ((dummy = (char *)calloc(page_sz, sizeof(char))) == NULL) {
Garrett Cooper11d51042010-11-22 20:47:29 -0800244 tst_brkm(TFAIL, cleanup, "calloc failed (dummy)");
plars865695b2001-08-27 22:15:12 +0000245 }
246
247 /*
subrata_modakc3270662008-05-02 06:28:13 +0000248 * Initialize addr to align with the first segment boundary address
249 * above the break address of the process.
plars865695b2001-08-27 22:15:12 +0000250 */
subrata_modak56207ce2009-03-23 13:35:39 +0000251 addr = (void *)(((intptr_t) sbrk(0) + (SHMLBA - 1)) & ~(SHMLBA - 1));
plars865695b2001-08-27 22:15:12 +0000252
subrata_modakc3270662008-05-02 06:28:13 +0000253 /* Set the break address of the process to the addr plus one
254 * page size.
255 */
subrata_modak56207ce2009-03-23 13:35:39 +0000256 if ((intptr_t) sbrk(SHMLBA + page_sz) == -1) {
Garrett Cooper11d51042010-11-22 20:47:29 -0800257 tst_brkm(TFAIL|TERRNO, cleanup,
258 "sbrk(SHMLBA + page_sz) failed");
plars865695b2001-08-27 22:15:12 +0000259 }
260
261 /* Initialize one page region from addr with 'A' */
262 memset(addr, 'A', page_sz);
263
264 /* Create the command which will be executed in the test */
Garrett Cooper11d51042010-11-22 20:47:29 -0800265 sprintf(cmd_buffer, "grep XYZ %s/%s > /dev/null", Path_name, TEMPFILE);
plars865695b2001-08-27 22:15:12 +0000266}
267
268/*
269 * cleanup() - performs all ONE TIME cleanup for this test at
270 * completion or premature exit.
subrata_modak56207ce2009-03-23 13:35:39 +0000271 * Free the memory allocated to dummy variable.
272 * Remove the temporary directory created.
plars865695b2001-08-27 22:15:12 +0000273 */
subrata_modak56207ce2009-03-23 13:35:39 +0000274void cleanup()
plars865695b2001-08-27 22:15:12 +0000275{
276 /*
277 * print timing stats if that option was specified.
278 */
subrata_modak56207ce2009-03-23 13:35:39 +0000279 close(fildes);
mridge20a6d422004-08-25 15:38:14 +0000280
plars865695b2001-08-27 22:15:12 +0000281 TEST_CLEANUP;
282
283 /* Free the memory allocated for dummy string */
284 if (dummy) {
285 free(dummy);
286 }
287
plars865695b2001-08-27 22:15:12 +0000288 tst_rmdir();
Chris Dearmanec6edca2012-10-17 19:54:01 -0700289}