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 *  Call mmap() with prot parameter set to PROT_READ and with the file
22 *  descriptor being open for read, to  map a file creating mapped memory
23 *  with read access. The minimum file permissions should be 0444.
24 *
25 *  The call should succeed to create the mapped region with required
26 *  attributes.
27 *
28 * Expected Result:
29 *  mmap() should succeed returning the address of the mapped region,
30 *  the mapped region should contain the contents of the mapped file.
31 *
32 * HISTORY
33 *	07/2001 Ported by Wayne Boyer
34 */
35#include <stdio.h>
36#include <stdlib.h>
37#include <sys/types.h>
38#include <errno.h>
39#include <unistd.h>
40#include <fcntl.h>
41#include <string.h>
42#include <signal.h>
43#include <sys/stat.h>
44#include <sys/mman.h>
45
46#include "test.h"
47
48#define TEMPFILE	"mmapfile"
49
50char *TCID = "mmap02";
51int TST_TOTAL = 1;
52
53static char *addr;
54static char *dummy;
55static size_t page_sz;
56static int fildes;
57
58static void setup(void);
59static void cleanup(void);
60
61int main(int ac, char **av)
62{
63	int lc;
64
65	tst_parse_opts(ac, av, NULL, NULL);
66
67	setup();
68
69	for (lc = 0; TEST_LOOPING(lc); lc++) {
70
71		tst_count = 0;
72
73		/*
74		 * Call mmap to map the temporary file 'TEMPFILE'
75		 * with read access.
76		 */
77		errno = 0;
78		addr = mmap(0, page_sz, PROT_READ,
79			    MAP_FILE | MAP_SHARED, fildes, 0);
80
81		/* Check for the return value of mmap() */
82		if (addr == MAP_FAILED) {
83			tst_resm(TFAIL | TERRNO, "mmap of %s failed", TEMPFILE);
84			continue;
85		}
86
87		/*
88		 * Read the file contents into the dummy
89		 * string.
90		 */
91		if (read(fildes, dummy, page_sz) < 0) {
92			tst_brkm(TFAIL | TERRNO, cleanup,
93				 "reading %s failed", TEMPFILE);
94		}
95
96		/*
97		 * Check whether mapped memory region has
98		 * the file contents.
99		 */
100		if (memcmp(dummy, addr, page_sz)) {
101			tst_resm(TFAIL, "mapped memory area contains "
102				 "invalid data");
103		} else {
104			tst_resm(TPASS,
105				 "Functionality of mmap() successful");
106		}
107
108		/* Clean up things in case we are looping */
109		/* Unmap the mapped memory */
110		if (munmap(addr, page_sz) != 0) {
111			tst_brkm(TFAIL | TERRNO, cleanup, "munmapping failed");
112		}
113	}
114
115	cleanup();
116	tst_exit();
117}
118
119static void setup(void)
120{
121	char *tst_buff;
122
123	tst_sig(FORK, DEF_HANDLER, cleanup);
124
125	TEST_PAUSE;
126
127	page_sz = getpagesize();
128
129	/* Allocate space for the test buffer */
130	if ((tst_buff = calloc(page_sz, sizeof(char))) == NULL) {
131		tst_brkm(TFAIL, NULL, "calloc failed (tst_buff)");
132	}
133
134	/* Fill the test buffer with the known data */
135	memset(tst_buff, 'A', page_sz);
136
137	tst_tmpdir();
138
139	/* Creat a temporary file used for mapping */
140	if ((fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0666)) < 0) {
141		free(tst_buff);
142		tst_brkm(TFAIL | TERRNO, cleanup, "opening %s failed",
143			 TEMPFILE);
144	}
145
146	/* Write test buffer contents into temporary file */
147	if (write(fildes, tst_buff, page_sz) < page_sz) {
148		free(tst_buff);
149		tst_brkm(TFAIL | TERRNO, cleanup,
150			 "writing to %s failed", TEMPFILE);
151	}
152
153	/* Free the memory allocated for test buffer */
154	free(tst_buff);
155
156	/* Change Mode permissions on Temporary file */
157	if (fchmod(fildes, 0444) < 0) {
158		tst_brkm(TFAIL | TERRNO, cleanup, "fchmod(%s, 0444) failed",
159			 TEMPFILE);
160	}
161
162	/* Close the temporary file */
163	if (close(fildes) < 0) {
164		tst_brkm(TFAIL | TERRNO, cleanup, "closing %s failed",
165			 TEMPFILE);
166	}
167
168	/* Open the temporary file again, - Readonly mode */
169	if ((fildes = open(TEMPFILE, O_RDONLY)) < 0) {
170		tst_brkm(TFAIL, cleanup, "reopening %s readonly failed",
171			 TEMPFILE);
172	}
173
174	/* Allocate and initialize dummy string of system page size bytes */
175	if ((dummy = calloc(page_sz, sizeof(char))) == NULL) {
176		tst_brkm(TFAIL, cleanup, "calloc failed (dummy)");
177	}
178
179}
180
181static void cleanup(void)
182{
183	close(fildes);
184	free(dummy);
185	tst_rmdir();
186}
187