1 | #include <assert.h> |
2 | #include <errno.h> |
3 | #include <stdio.h> |
4 | #include <stdlib.h> |
5 | #include <unistd.h> |
6 | #include <sys/mman.h> |
7 | |
8 | |
9 | static int |
10 | do_test (void) |
11 | { |
12 | int result = 0; |
13 | FILE *fp; |
14 | size_t c; |
15 | char buf[1000]; |
16 | int fd; |
17 | unsigned char *ptr; |
18 | size_t ps = sysconf (_SC_PAGESIZE); |
19 | void *mem; |
20 | |
21 | /* Create a file and put some data in it. */ |
22 | fp = tmpfile (); |
23 | if (fp == NULL) |
24 | { |
25 | printf (format: "Cannot create temporary file: %m\n" ); |
26 | return 1; |
27 | } |
28 | fd = fileno (fp); |
29 | |
30 | for (c = 0; c < sizeof (buf); ++c) |
31 | buf[c] = '0' + (c % 10); |
32 | |
33 | for (c = 0; c < (ps * 4) / sizeof (buf); ++c) |
34 | if (fwrite (buf, 1, sizeof (buf), fp) != sizeof (buf)) |
35 | { |
36 | printf (format: "`fwrite' failed: %m\n" ); |
37 | return 1; |
38 | } |
39 | fflush (fp); |
40 | assert (ps + 1000 < c * sizeof (buf)); |
41 | |
42 | /* First try something which is not allowed: map at an offset which is |
43 | not modulo the pagesize. */ |
44 | ptr = mmap (NULL, len: 1000, PROT_READ, MAP_SHARED, fd: fd, offset: ps - 1); |
45 | if (ptr != MAP_FAILED) |
46 | { |
47 | puts (s: "mapping at offset with mod pagesize != 0 succeeded!" ); |
48 | result = 1; |
49 | } |
50 | else if (errno != EINVAL && errno != ENOSYS) |
51 | { |
52 | puts (s: "wrong error value for mapping at offset with mod pagesize != 0: %m (should be EINVAL)" ); |
53 | result = 1; |
54 | } |
55 | |
56 | /* Try the same for mmap64. */ |
57 | ptr = mmap64 (NULL, len: 1000, PROT_READ, MAP_SHARED, fd: fd, offset: ps - 1); |
58 | if (ptr != MAP_FAILED) |
59 | { |
60 | puts (s: "mapping at offset with mod pagesize != 0 succeeded!" ); |
61 | result = 1; |
62 | } |
63 | else if (errno != EINVAL && errno != ENOSYS) |
64 | { |
65 | puts (s: "wrong error value for mapping at offset with mod pagesize != 0: %m (should be EINVAL)" ); |
66 | result = 1; |
67 | } |
68 | |
69 | /* And the same for private mapping. */ |
70 | ptr = mmap (NULL, len: 1000, PROT_READ, MAP_PRIVATE, fd: fd, offset: ps - 1); |
71 | if (ptr != MAP_FAILED) |
72 | { |
73 | puts (s: "mapping at offset with mod pagesize != 0 succeeded!" ); |
74 | result = 1; |
75 | } |
76 | else if (errno != EINVAL && errno != ENOSYS) |
77 | { |
78 | puts (s: "wrong error value for mapping at offset with mod pagesize != 0: %m (should be EINVAL)" ); |
79 | result = 1; |
80 | } |
81 | |
82 | /* Try the same for mmap64. */ |
83 | ptr = mmap64 (NULL, len: 1000, PROT_READ, MAP_PRIVATE, fd: fd, offset: ps - 1); |
84 | if (ptr != MAP_FAILED) |
85 | { |
86 | puts (s: "mapping at offset with mod pagesize != 0 succeeded!" ); |
87 | result = 1; |
88 | } |
89 | else if (errno != EINVAL && errno != ENOSYS) |
90 | { |
91 | puts (s: "wrong error value for mapping at offset with mod pagesize != 0: %m (should be EINVAL)" ); |
92 | result = 1; |
93 | } |
94 | |
95 | /* Get a valid address. */ |
96 | mem = malloc (size: 2 * ps); |
97 | if (mem != NULL) |
98 | { |
99 | /* Now we map at an address which is not mod pagesize. */ |
100 | ptr = mmap (addr: mem + 1, len: 1000, PROT_READ, MAP_SHARED | MAP_FIXED, fd: fd, offset: ps); |
101 | if (ptr != MAP_FAILED) |
102 | { |
103 | puts (s: "mapping at address with mod pagesize != 0 succeeded!" ); |
104 | result = 1; |
105 | } |
106 | else if (errno != EINVAL && errno != ENOSYS) |
107 | { |
108 | puts (s: "wrong error value for mapping at address with mod pagesize != 0: %m (should be EINVAL)" ); |
109 | result = 1; |
110 | } |
111 | |
112 | /* Try the same for mmap64. */ |
113 | ptr = mmap64 (addr: mem + 1, len: 1000, PROT_READ, MAP_SHARED | MAP_FIXED, fd: fd, offset: ps); |
114 | if (ptr != MAP_FAILED) |
115 | { |
116 | puts (s: "mapping at address with mod pagesize != 0 succeeded!" ); |
117 | result = 1; |
118 | } |
119 | else if (errno != EINVAL && errno != ENOSYS) |
120 | { |
121 | puts (s: "wrong error value for mapping at address with mod pagesize != 0: %m (should be EINVAL)" ); |
122 | result = 1; |
123 | } |
124 | |
125 | /* And again for MAP_PRIVATE. */ |
126 | ptr = mmap (addr: mem + 1, len: 1000, PROT_READ, MAP_PRIVATE | MAP_FIXED, fd: fd, offset: ps); |
127 | if (ptr != MAP_FAILED) |
128 | { |
129 | puts (s: "mapping at address with mod pagesize != 0 succeeded!" ); |
130 | result = 1; |
131 | } |
132 | else if (errno != EINVAL && errno != ENOSYS) |
133 | { |
134 | puts (s: "wrong error value for mapping at address with mod pagesize != 0: %m (should be EINVAL)" ); |
135 | result = 1; |
136 | } |
137 | |
138 | /* Try the same for mmap64. */ |
139 | ptr = mmap64 (addr: mem + 1, len: 1000, PROT_READ, MAP_PRIVATE | MAP_FIXED, fd: fd, offset: ps); |
140 | if (ptr != MAP_FAILED) |
141 | { |
142 | puts (s: "mapping at address with mod pagesize != 0 succeeded!" ); |
143 | result = 1; |
144 | } |
145 | else if (errno != EINVAL && errno != ENOSYS) |
146 | { |
147 | puts (s: "wrong error value for mapping at address with mod pagesize != 0: %m (should be EINVAL)" ); |
148 | result = 1; |
149 | } |
150 | |
151 | free (ptr: mem); |
152 | } |
153 | |
154 | /* Now map the memory and see whether the content of the mapped area |
155 | is correct. */ |
156 | ptr = mmap (NULL, len: 1000, PROT_READ, MAP_SHARED, fd: fd, offset: ps); |
157 | if (ptr == MAP_FAILED) |
158 | { |
159 | if (errno != ENOSYS) |
160 | { |
161 | printf (format: "cannot mmap file: %m\n" ); |
162 | result = 1; |
163 | } |
164 | } |
165 | else |
166 | { |
167 | for (c = ps; c < ps + 1000; ++c) |
168 | if (ptr[c - ps] != '0' + (c % 10)) |
169 | { |
170 | printf (format: "wrong data mapped at offset %zd\n" , c); |
171 | result = 1; |
172 | } |
173 | } |
174 | |
175 | /* And for mmap64. */ |
176 | ptr = mmap64 (NULL, len: 1000, PROT_READ, MAP_SHARED, fd: fd, offset: ps); |
177 | if (ptr == MAP_FAILED) |
178 | { |
179 | if (errno != ENOSYS) |
180 | { |
181 | printf (format: "cannot mmap file: %m\n" ); |
182 | result = 1; |
183 | } |
184 | } |
185 | else |
186 | { |
187 | for (c = ps; c < ps + 1000; ++c) |
188 | if (ptr[c - ps] != '0' + (c % 10)) |
189 | { |
190 | printf (format: "wrong data mapped at offset %zd\n" , c); |
191 | result = 1; |
192 | } |
193 | } |
194 | |
195 | /* That's it. */ |
196 | return result; |
197 | } |
198 | |
199 | #define TEST_FUNCTION do_test () |
200 | #include "../test-skeleton.c" |
201 | |