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() to map a file creating a mapped region with read access
22 *  under the following conditions -
23 *	- The prot parameter is set to PROT_READ
24 *	- The file descriptor is open for writing.
25 *
26 *  The call should fail to map the file.
27 *
28 * Expected Result:
29 *  mmap() should fail returning -1 and errno should get set to EACCES.
30 *
31 * HISTORY
32 *	07/2001 Ported by Wayne Boyer
33 */
34#include <stdio.h>
35#include <stdlib.h>
36#include <sys/types.h>
37#include <errno.h>
38#include <unistd.h>
39#include <fcntl.h>
40#include <string.h>
41#include <signal.h>
42#include <sys/stat.h>
43#include <sys/mman.h>
44
45#include "test.h"
46
47#define TEMPFILE	"mmapfile"
48
49char *TCID = "mmap06";
50int TST_TOTAL = 1;
51
52static size_t page_sz;
53static char *addr;
54static int fildes;
55
56static void setup(void);
57static void cleanup(void);
58
59int main(int ac, char **av)
60{
61	int lc;
62
63	tst_parse_opts(ac, av, NULL, NULL);
64
65	setup();
66
67	for (lc = 0; TEST_LOOPING(lc); lc++) {
68
69		tst_count = 0;
70
71		/*
72		 * Call mmap to map the temporary file 'TEMPFILE'
73		 * with read access.
74		 */
75		errno = 0;
76		addr = mmap(0, page_sz, PROT_READ,
77			    MAP_FILE | MAP_SHARED, fildes, 0);
78		TEST_ERRNO = errno;
79
80		/* Check for the return value of mmap() */
81		if (addr != MAP_FAILED) {
82			tst_resm(TFAIL | TERRNO,
83				 "mmap() returned invalid value, expected: %p",
84				 MAP_FAILED);
85			/* Unmap the mapped memory */
86			if (munmap(addr, page_sz) != 0) {
87				tst_resm(TBROK, "munmap() failed");
88				cleanup();
89			}
90			continue;
91		}
92		if (TEST_ERRNO == EACCES) {
93			tst_resm(TPASS, "mmap failed with EACCES");
94		} else {
95			tst_resm(TFAIL | TERRNO,
96				 "mmap failed with unexpected errno");
97		}
98	}
99	cleanup();
100	tst_exit();
101
102}
103
104static void setup(void)
105{
106	char *tst_buff;
107
108	tst_sig(NOFORK, DEF_HANDLER, cleanup);
109
110	TEST_PAUSE;
111
112	page_sz = getpagesize();
113
114	/* Allocate space for the test buffer */
115	if ((tst_buff = calloc(page_sz, sizeof(char))) == NULL) {
116		tst_brkm(TFAIL, NULL, "calloc() failed (tst_buff)");
117	}
118
119	/* Fill the test buffer with the known data */
120	memset(tst_buff, 'A', page_sz);
121
122	tst_tmpdir();
123
124	/* Creat a temporary file used for mapping */
125	if ((fildes = open(TEMPFILE, O_WRONLY | O_CREAT, 0666)) < 0) {
126		free(tst_buff);
127		tst_brkm(TFAIL, cleanup, "opening %s failed", TEMPFILE);
128	}
129
130	/* Write test buffer contents into temporary file */
131	if (write(fildes, tst_buff, page_sz) < page_sz) {
132		free(tst_buff);
133		tst_brkm(TFAIL, cleanup, "writing to %s failed", TEMPFILE);
134	}
135
136	free(tst_buff);
137}
138
139static void cleanup(void)
140{
141	close(fildes);
142	tst_rmdir();
143}
144