t_access.c revision 273391
119370Spst/* $NetBSD: t_access.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
219370Spst
319370Spst/*-
419370Spst * Copyright (c) 2011 The NetBSD Foundation, Inc.
519370Spst * All rights reserved.
619370Spst *
719370Spst * This code is derived from software contributed to The NetBSD Foundation
819370Spst * by Jukka Ruohonen.
919370Spst *
1019370Spst * Redistribution and use in source and binary forms, with or without
1119370Spst * modification, are permitted provided that the following conditions
1219370Spst * are met:
1319370Spst * 1. Redistributions of source code must retain the above copyright
1419370Spst *    notice, this list of conditions and the following disclaimer.
1519370Spst * 2. Redistributions in binary form must reproduce the above copyright
1619370Spst *    notice, this list of conditions and the following disclaimer in the
1719370Spst *    documentation and/or other materials provided with the distribution.
1819370Spst *
1919370Spst * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2019370Spst * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2119370Spst * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2219370Spst * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2319370Spst * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2419370Spst * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2519370Spst * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2619370Spst * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2719370Spst * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2819370Spst * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2919370Spst * POSSIBILITY OF SUCH DAMAGE.
3019370Spst */
3119370Spst#include <sys/cdefs.h>
3219370Spst__RCSID("$NetBSD: t_access.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
3319370Spst
3419370Spst#include <errno.h>
3519370Spst#include <fcntl.h>
3619370Spst#include <limits.h>
3719370Spst#include <stdint.h>
3819370Spst#include <stdlib.h>
3919370Spst#include <unistd.h>
4019370Spst
4119370Spst#include <atf-c.h>
4219370Spst
4319370Spst#if defined(__FreeBSD__)
4419370Spst#include <sys/stat.h>
4519370Spst#endif
4619370Spst
4719370Spststatic const char path[] = "access";
4819370Spststatic const int mode[4] = { R_OK, W_OK, X_OK, F_OK };
4919370Spst
5019370SpstATF_TC_WITH_CLEANUP(access_access);
5119370SpstATF_TC_HEAD(access_access, tc)
5219370Spst{
5319370Spst	atf_tc_set_md_var(tc, "descr", "Test access(2) for EACCES");
5419370Spst	atf_tc_set_md_var(tc, "require.user", "unprivileged");
5519370Spst}
5619370Spst
5719370SpstATF_TC_BODY(access_access, tc)
5819370Spst{
5919370Spst	const int perm[3] = { 0200, 0400, 0000 };
6019370Spst	size_t i;
6119370Spst	int fd;
6219370Spst
6319370Spst	fd = open(path, O_RDONLY | O_CREAT);
6419370Spst
6519370Spst	if (fd < 0)
6619370Spst		return;
6719370Spst
6819370Spst	for (i = 0; i < __arraycount(mode) - 1; i++) {
6919370Spst
7019370Spst		ATF_REQUIRE(fchmod(fd, perm[i]) == 0);
7119370Spst
7219370Spst		errno = 0;
7319370Spst
7419370Spst		ATF_REQUIRE(access(path, mode[i]) != 0);
7519370Spst		ATF_REQUIRE(errno == EACCES);
7619370Spst	}
7719370Spst
7819370Spst	ATF_REQUIRE(close(fd) == 0);
7919370Spst}
8019370Spst
8119370SpstATF_TC_CLEANUP(access_access, tc)
8219370Spst{
8319370Spst	(void)unlink(path);
8419370Spst}
8519370Spst
8619370SpstATF_TC(access_fault);
8719370SpstATF_TC_HEAD(access_fault, tc)
8819370Spst{
8919370Spst	atf_tc_set_md_var(tc, "descr", "Test access(2) for EFAULT");
9019370Spst}
9119370Spst
9219370SpstATF_TC_BODY(access_fault, tc)
9319370Spst{
9419370Spst	size_t i;
9519370Spst
9619370Spst	for (i = 0; i < __arraycount(mode); i++) {
9719370Spst
9819370Spst		errno = 0;
9919370Spst
10019370Spst		ATF_REQUIRE(access(NULL, mode[i]) != 0);
10119370Spst		ATF_REQUIRE(errno == EFAULT);
10219370Spst
10319370Spst		errno = 0;
10419370Spst
10519370Spst		ATF_REQUIRE(access((char *)-1, mode[i]) != 0);
10619370Spst		ATF_REQUIRE(errno == EFAULT);
10719370Spst	}
10819370Spst}
10919370Spst
11019370SpstATF_TC(access_inval);
11119370SpstATF_TC_HEAD(access_inval, tc)
11219370Spst{
11319370Spst	atf_tc_set_md_var(tc, "descr", "Test access(2) for EINVAL");
11419370Spst}
11546283Sdfr
11646283SdfrATF_TC_BODY(access_inval, tc)
11746283Sdfr{
11846283Sdfr
11919370Spst	errno = 0;
12019370Spst
12119370Spst	ATF_REQUIRE(access("/usr", -1) != 0);
12219370Spst	ATF_REQUIRE(errno == EINVAL);
12319370Spst}
12419370Spst
12519370SpstATF_TC(access_notdir);
12619370SpstATF_TC_HEAD(access_notdir, tc)
12719370Spst{
12819370Spst	atf_tc_set_md_var(tc, "descr", "Test access(2) for ENOTDIR");
12919370Spst}
13019370Spst
13119370SpstATF_TC_BODY(access_notdir, tc)
13219370Spst{
13319370Spst	size_t i;
13419370Spst
13519370Spst	for (i = 0; i < __arraycount(mode); i++) {
13619370Spst
13719370Spst		errno = 0;
13819370Spst
13919370Spst		/*
14046283Sdfr		 *  IEEE Std 1003.1-2008 about ENOTDIR:
14146283Sdfr		 *
14246283Sdfr		 *  "A component of the path prefix is not a directory,
14319370Spst		 *   or the path argument contains at least one non-<slash>
14419370Spst		 *   character and ends with one or more trailing <slash>
14519370Spst		 *   characters and the last pathname component names an
14619370Spst		 *   existing file that is neither a directory nor a symbolic
14719370Spst		 *   link to a directory."
14819370Spst		 */
14919370Spst		ATF_REQUIRE(access("/etc/passwd//", mode[i]) != 0);
15019370Spst		ATF_REQUIRE(errno == ENOTDIR);
15119370Spst	}
15219370Spst}
15319370Spst
15419370SpstATF_TC(access_notexist);
15519370SpstATF_TC_HEAD(access_notexist, tc)
15619370Spst{
15719370Spst	atf_tc_set_md_var(tc, "descr", "Test access(2) for ENOENT");
15819370Spst}
15919370Spst
16019370SpstATF_TC_BODY(access_notexist, tc)
16119370Spst{
16219370Spst	size_t i;
16319370Spst
16419370Spst	for (i = 0; i < __arraycount(mode); i++) {
16519370Spst
16619370Spst		errno = 0;
16719370Spst
16819370Spst		ATF_REQUIRE(access("", mode[i]) != 0);
16919370Spst		ATF_REQUIRE(errno == ENOENT);
17019370Spst	}
17119370Spst}
17219370Spst
17319370SpstATF_TC(access_toolong);
17419370SpstATF_TC_HEAD(access_toolong, tc)
17519370Spst{
17619370Spst	atf_tc_set_md_var(tc, "descr", "Test access(2) for ENAMETOOLONG");
17719370Spst}
17819370Spst
17919370SpstATF_TC_BODY(access_toolong, tc)
18019370Spst{
18119370Spst	char *buf;
18219370Spst	size_t i;
18319370Spst
18419370Spst	buf = malloc(PATH_MAX);
18519370Spst
18619370Spst	if (buf == NULL)
18719370Spst		return;
18819370Spst
18919370Spst	for (i = 0; i < PATH_MAX; i++)
19019370Spst		buf[i] = 'x';
19119370Spst
19219370Spst	for (i = 0; i < __arraycount(mode); i++) {
19319370Spst
19419370Spst		errno = 0;
19519370Spst
19619370Spst		ATF_REQUIRE(access(buf, mode[i]) != 0);
19719370Spst		ATF_REQUIRE(errno == ENAMETOOLONG);
19819370Spst	}
199
200	free(buf);
201}
202
203ATF_TP_ADD_TCS(tp)
204{
205
206	ATF_TP_ADD_TC(tp, access_access);
207	ATF_TP_ADD_TC(tp, access_fault);
208	ATF_TP_ADD_TC(tp, access_inval);
209	ATF_TP_ADD_TC(tp, access_notdir);
210	ATF_TP_ADD_TC(tp, access_notexist);
211	ATF_TP_ADD_TC(tp, access_toolong);
212
213	return atf_no_error();
214}
215