t_mincore.c revision 1.1
1/* $NetBSD: t_mincore.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
2
3/*-
4 * Copyright (c) 2011 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jukka Ruohonen.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31#include <sys/cdefs.h>
32__RCSID("$NetBSD: t_mincore.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
33
34#include <sys/mman.h>
35
36#include <atf-c.h>
37#include <errno.h>
38#include <fcntl.h>
39#include <stdlib.h>
40#include <unistd.h>
41
42static long		page = 0;
43static const char	path[] = "mincore";
44
45ATF_TC(mincore_err);
46ATF_TC_HEAD(mincore_err, tc)
47{
48	atf_tc_set_md_var(tc, "descr", "Test errors from mincore(2)");
49}
50
51ATF_TC_BODY(mincore_err, tc)
52{
53	char *map, *vec;
54
55	map = mmap(NULL, page, PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
56	vec = malloc(page);
57
58	ATF_REQUIRE(vec != NULL);
59	ATF_REQUIRE(map != MAP_FAILED);
60
61	errno = 0;
62	ATF_REQUIRE_ERRNO(EINVAL, mincore(map, 0, vec) == -1);
63
64	errno = 0;
65	ATF_REQUIRE_ERRNO(ENOMEM, mincore(0, page, vec) == -1);
66
67	errno = 0;
68	ATF_REQUIRE_ERRNO(EFAULT, mincore(map, page, (void *)-1) == -1);
69
70	free(vec);
71	ATF_REQUIRE(munmap(map, page) == 0);
72}
73
74ATF_TC_WITH_CLEANUP(mincore_incore);
75ATF_TC_HEAD(mincore_incore, tc)
76{
77	atf_tc_set_md_var(tc, "descr", "Test that mincore(2) works");
78}
79
80ATF_TC_BODY(mincore_incore, tc)
81{
82	char *buf, *vec, *map = MAP_FAILED;
83	const char *str = NULL;
84	const size_t n = 3;
85	ssize_t tot;
86	int fd, rv;
87	size_t i, j;
88
89	/*
90	 * Create a temporary file, write
91	 * few pages to it, and map the file.
92	 */
93	buf = calloc(n, page);
94	vec = calloc(n, page);
95
96	if (buf == NULL || vec == NULL)
97		return;
98
99	for (i = 0; i < (size_t)page * n; i++)
100		buf[i] = 'x';
101
102	fd = open(path, O_RDWR | O_CREAT, 0600);
103
104	if (fd < 0) {
105		str = "failed to open";
106		goto out;
107	}
108
109	tot = 0;
110
111	while (tot < page * (long)n) {
112
113		rv = write(fd, buf, sizeof(buf));
114
115		if (rv < 0) {
116			str = "failed to write";
117			goto out;
118		}
119
120		tot += rv;
121	}
122
123	map = mmap(NULL, page * n, PROT_READ | PROT_WRITE,
124	    MAP_FILE | MAP_PRIVATE, fd, 0);
125
126	if (map == MAP_FAILED) {
127		str = "failed to map";
128		goto out;
129	}
130
131	/*
132	 * Lock the mapping such that only
133	 * in-core page status is returned.
134	 */
135	if (mlock(map, page * n) != 0) {
136		str = "failed to lock";
137		goto out;
138	}
139
140	if (mincore(map, page * n, vec) != 0) {
141		str = "mincore failed";
142		goto out;
143	}
144
145	/*
146	 * Check that the in-core pages
147	 * match the locked pages.
148	 */
149	for (i = j = 0; i < (size_t)page * n; i++) {
150
151		if (vec[i] != 0)
152			j++;
153	}
154
155	if (j != n)
156		str = "mismatch of in-core pages";
157
158out:
159	free(buf);
160	free(vec);
161
162	(void)close(fd);
163	(void)unlink(path);
164
165	if (map != MAP_FAILED) {
166		(void)munlock(map, page);
167		(void)munmap(map, page);
168	}
169
170	if (str != NULL)
171		atf_tc_fail("%s", str);
172}
173
174ATF_TC_CLEANUP(mincore_incore, tc)
175{
176	(void)unlink(path);
177}
178
179ATF_TP_ADD_TCS(tp)
180{
181
182	page = sysconf(_SC_PAGESIZE);
183	ATF_REQUIRE(page >= 0);
184
185	ATF_TP_ADD_TC(tp, mincore_err);
186	ATF_TP_ADD_TC(tp, mincore_incore);
187
188	return atf_no_error();
189}
190