blob: e6b8e87c643f7069d16cbe4b501a1c0689994554 [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
Cyril Hrubis5efee332013-06-04 20:14:58 +02002 * Copyright (c) International Business Machines Corp., 2001
plars865695b2001-08-27 22:15:12 +00003 *
Cyril Hrubis5efee332013-06-04 20:14:58 +02004 * 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.
plars865695b2001-08-27 22:15:12 +00008 *
Cyril Hrubis5efee332013-06-04 20:14:58 +02009 * 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.
plars865695b2001-08-27 22:15:12 +000013 *
Cyril Hrubis5efee332013-06-04 20:14:58 +020014 * 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
plars865695b2001-08-27 22:15:12 +000017 */
18
19/*
plars865695b2001-08-27 22:15:12 +000020 * 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 *
plars865695b2001-08-27 22:15:12 +000033 * HISTORY
34 * 07/2001 Ported by Wayne Boyer
plars865695b2001-08-27 22:15:12 +000035 */
plars865695b2001-08-27 22:15:12 +000036#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>
plars85cbba32002-09-25 16:54:54 +000044#include <stdint.h>
plars865695b2001-08-27 22:15:12 +000045#include <sys/stat.h>
46#include <sys/mman.h>
subrata_modakc3270662008-05-02 06:28:13 +000047#include <sys/shm.h>
plars865695b2001-08-27 22:15:12 +000048
49#include "test.h"
plars865695b2001-08-27 22:15:12 +000050
51#define TEMPFILE "mmapfile"
52
Cyril Hrubisfdce7d52013-04-04 18:35:48 +020053char *TCID = "mmap01";
54int TST_TOTAL = 1;
plars865695b2001-08-27 22:15:12 +000055
Cyril Hrubis5efee332013-06-04 20:14:58 +020056static char *addr;
57static char *dummy;
58static size_t page_sz;
59static size_t file_sz;
60static int fildes;
61static char cmd_buffer[BUFSIZ];
62
63static void setup(void);
64static void cleanup(void);
plars865695b2001-08-27 22:15:12 +000065
subrata_modak56207ce2009-03-23 13:35:39 +000066int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +000067{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020068 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020069 const char *msg;
subrata_modakbdbaec52009-02-26 12:14:51 +000070
Garrett Cooper11d51042010-11-22 20:47:29 -080071 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
plars865695b2001-08-27 22:15:12 +000072 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
plars865695b2001-08-27 22:15:12 +000073
plars865695b2001-08-27 22:15:12 +000074 setup();
75
plars865695b2001-08-27 22:15:12 +000076 for (lc = 0; TEST_LOOPING(lc); lc++) {
Garrett Cooper2c282152010-12-16 00:55:50 -080077
Caspar Zhangd59a6592013-03-07 14:59:12 +080078 tst_count = 0;
plars865695b2001-08-27 22:15:12 +000079
subrata_modak4bb656a2009-02-26 12:02:09 +000080 /*
plars865695b2001-08-27 22:15:12 +000081 * Call mmap to map the temporary file beyond EOF
subrata_modak56207ce2009-03-23 13:35:39 +000082 * with write access.
plars865695b2001-08-27 22:15:12 +000083 */
robbiewd5c21122002-03-22 16:22:40 +000084 errno = 0;
85 addr = mmap(addr, page_sz, PROT_READ | PROT_WRITE,
subrata_modak56207ce2009-03-23 13:35:39 +000086 MAP_FILE | MAP_SHARED | MAP_FIXED, fildes, 0);
plars865695b2001-08-27 22:15:12 +000087
88 /* Check for the return value of mmap() */
robbiewd5c21122002-03-22 16:22:40 +000089 if (addr == MAP_FAILED) {
Wanlong Gao354ebb42012-12-07 10:10:04 +080090 tst_resm(TFAIL | TERRNO, "mmap of %s failed", TEMPFILE);
plars865695b2001-08-27 22:15:12 +000091 continue;
92 }
Cyril Hrubis5efee332013-06-04 20:14:58 +020093
Cyril Hrubise38b9612014-06-02 17:20:57 +020094 /*
95 * Check if mapped memory area beyond EOF are
96 * zeros and changes beyond EOF are not written
97 * to file.
98 */
99 if (memcmp(&addr[file_sz], dummy, page_sz - file_sz)) {
100 tst_brkm(TFAIL, cleanup,
101 "mapped memory area contains invalid "
102 "data");
103 }
plars865695b2001-08-27 22:15:12 +0000104
Cyril Hrubise38b9612014-06-02 17:20:57 +0200105 /*
106 * Initialize memory beyond file size
107 */
108 addr[file_sz] = 'X';
109 addr[file_sz + 1] = 'Y';
110 addr[file_sz + 2] = 'Z';
plars865695b2001-08-27 22:15:12 +0000111
Cyril Hrubise38b9612014-06-02 17:20:57 +0200112 /*
113 * Synchronize the mapped memory region
114 * with the file.
115 */
116 if (msync(addr, page_sz, MS_SYNC) != 0) {
117 tst_brkm(TFAIL | TERRNO, cleanup,
118 "failed to synchronize mapped file");
119 }
plars865695b2001-08-27 22:15:12 +0000120
Cyril Hrubise38b9612014-06-02 17:20:57 +0200121 /*
122 * Now, Search for the pattern 'XYZ' in the
123 * temporary file. The pattern should not be
124 * found and the return value should be 1.
125 */
126 if (system(cmd_buffer) != 0) {
127 tst_resm(TPASS,
128 "Functionality of mmap() successful");
plars865695b2001-08-27 22:15:12 +0000129 } else {
Cyril Hrubise38b9612014-06-02 17:20:57 +0200130 tst_resm(TFAIL,
131 "Specified pattern found in file");
plars865695b2001-08-27 22:15:12 +0000132 }
133
134 /* Clean up things in case we are looping */
135 /* Unmap the mapped memory */
136 if (munmap(addr, page_sz) != 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800137 tst_brkm(TFAIL | TERRNO, NULL, "munmap failed");
plars865695b2001-08-27 22:15:12 +0000138 }
Garrett Cooper2c282152010-12-16 00:55:50 -0800139 }
plars865695b2001-08-27 22:15:12 +0000140
plars865695b2001-08-27 22:15:12 +0000141 cleanup();
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800142 tst_exit();
Garrett Cooper2c282152010-12-16 00:55:50 -0800143}
plars865695b2001-08-27 22:15:12 +0000144
Cyril Hrubis5efee332013-06-04 20:14:58 +0200145static void setup(void)
plars865695b2001-08-27 22:15:12 +0000146{
147 struct stat stat_buf;
Cyril Hrubis5efee332013-06-04 20:14:58 +0200148 char Path_name[PATH_MAX];
plars865695b2001-08-27 22:15:12 +0000149 char write_buf[] = "hello world\n";
150
plars865695b2001-08-27 22:15:12 +0000151 tst_sig(FORK, DEF_HANDLER, cleanup);
152
plars865695b2001-08-27 22:15:12 +0000153 TEST_PAUSE;
154
plars865695b2001-08-27 22:15:12 +0000155 tst_tmpdir();
156
157 /* Get the path of temporary file to be created */
158 if (getcwd(Path_name, sizeof(Path_name)) == NULL) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800159 tst_brkm(TFAIL | TERRNO, cleanup,
Garrett Cooper11d51042010-11-22 20:47:29 -0800160 "getcwd failed to get current working directory");
plars865695b2001-08-27 22:15:12 +0000161 }
162
163 /* Creat a temporary file used for mapping */
164 if ((fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0666)) < 0) {
Garrett Cooper11d51042010-11-22 20:47:29 -0800165 tst_brkm(TFAIL, cleanup, "opening %s failed", TEMPFILE);
plars865695b2001-08-27 22:15:12 +0000166 }
167
168 /* Write some data into temporary file */
169 if (write(fildes, write_buf, strlen(write_buf)) != strlen(write_buf)) {
Garrett Cooper11d51042010-11-22 20:47:29 -0800170 tst_brkm(TFAIL, cleanup, "writing to %s", TEMPFILE);
plars865695b2001-08-27 22:15:12 +0000171 }
subrata_modakbdbaec52009-02-26 12:14:51 +0000172
plars865695b2001-08-27 22:15:12 +0000173 /* Get the size of temporary file */
174 if (stat(TEMPFILE, &stat_buf) < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800175 tst_brkm(TFAIL | TERRNO, cleanup, "stat of %s failed",
176 TEMPFILE);
plars865695b2001-08-27 22:15:12 +0000177 }
178 file_sz = stat_buf.st_size;
179
Cyril Hrubisec22fb22013-06-04 20:37:05 +0200180 page_sz = getpagesize();
plars865695b2001-08-27 22:15:12 +0000181
182 /* Allocate and initialize dummy string of system page size bytes */
Cyril Hrubis5efee332013-06-04 20:14:58 +0200183 if ((dummy = calloc(page_sz, sizeof(char))) == NULL) {
Garrett Cooper11d51042010-11-22 20:47:29 -0800184 tst_brkm(TFAIL, cleanup, "calloc failed (dummy)");
plars865695b2001-08-27 22:15:12 +0000185 }
186
187 /*
subrata_modakc3270662008-05-02 06:28:13 +0000188 * Initialize addr to align with the first segment boundary address
189 * above the break address of the process.
plars865695b2001-08-27 22:15:12 +0000190 */
subrata_modak56207ce2009-03-23 13:35:39 +0000191 addr = (void *)(((intptr_t) sbrk(0) + (SHMLBA - 1)) & ~(SHMLBA - 1));
plars865695b2001-08-27 22:15:12 +0000192
subrata_modakc3270662008-05-02 06:28:13 +0000193 /* Set the break address of the process to the addr plus one
194 * page size.
195 */
subrata_modak56207ce2009-03-23 13:35:39 +0000196 if ((intptr_t) sbrk(SHMLBA + page_sz) == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800197 tst_brkm(TFAIL | TERRNO, cleanup,
198 "sbrk(SHMLBA + page_sz) failed");
plars865695b2001-08-27 22:15:12 +0000199 }
200
201 /* Initialize one page region from addr with 'A' */
202 memset(addr, 'A', page_sz);
203
204 /* Create the command which will be executed in the test */
Garrett Cooper11d51042010-11-22 20:47:29 -0800205 sprintf(cmd_buffer, "grep XYZ %s/%s > /dev/null", Path_name, TEMPFILE);
plars865695b2001-08-27 22:15:12 +0000206}
207
Cyril Hrubis5efee332013-06-04 20:14:58 +0200208static void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000209{
subrata_modak56207ce2009-03-23 13:35:39 +0000210 close(fildes);
Cyril Hrubis5efee332013-06-04 20:14:58 +0200211 free(dummy);
plars865695b2001-08-27 22:15:12 +0000212 tst_rmdir();
Chris Dearmanec6edca2012-10-17 19:54:01 -0700213}