xref: /netbsd-src/tests/kernel/t_fcntl.c (revision cf9621ed1677dc39e43af2ce437090e6e35a7b10)
1*cf9621edSriastradh /*	$NetBSD: t_fcntl.c,v 1.4 2023/08/05 08:05:16 riastradh Exp $	*/
20a76d2edSchristos 
30a76d2edSchristos /*-
40a76d2edSchristos  * Copyright (c) 2019 The NetBSD Foundation, Inc.
50a76d2edSchristos  * All rights reserved.
60a76d2edSchristos  *
70a76d2edSchristos  * This code is derived from software contributed to The NetBSD Foundation
80a76d2edSchristos  * by Christos Zoulas.
90a76d2edSchristos  *
100a76d2edSchristos  * Redistribution and use in source and binary forms, with or without
110a76d2edSchristos  * modification, are permitted provided that the following conditions
120a76d2edSchristos  * are met:
130a76d2edSchristos  * 1. Redistributions of source code must retain the above copyright
140a76d2edSchristos  *    notice, this list of conditions and the following disclaimer.
150a76d2edSchristos  * 2. Redistributions in binary form must reproduce the above copyright
160a76d2edSchristos  *    notice, this list of conditions and the following disclaimer in the
170a76d2edSchristos  *    documentation and/or other materials provided with the distribution.
180a76d2edSchristos  *
190a76d2edSchristos  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
200a76d2edSchristos  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
210a76d2edSchristos  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
220a76d2edSchristos  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
230a76d2edSchristos  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
240a76d2edSchristos  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
250a76d2edSchristos  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
260a76d2edSchristos  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
270a76d2edSchristos  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
280a76d2edSchristos  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
290a76d2edSchristos  * POSSIBILITY OF SUCH DAMAGE.
300a76d2edSchristos  */
310a76d2edSchristos 
320a76d2edSchristos #include <sys/param.h>
330a76d2edSchristos #include <sys/types.h>
34d3ba7ba3Schristos #include <sys/mman.h>
350a76d2edSchristos #include <atf-c.h>
360a76d2edSchristos #include <fcntl.h>
370a76d2edSchristos #include <errno.h>
380a76d2edSchristos #include <stdlib.h>
390a76d2edSchristos #include <string.h>
400a76d2edSchristos #include <unistd.h>
410a76d2edSchristos 
42d3ba7ba3Schristos ATF_TC(getpath_vnode);
ATF_TC_HEAD(getpath_vnode,tc)43d3ba7ba3Schristos ATF_TC_HEAD(getpath_vnode, tc)
440a76d2edSchristos {
450a76d2edSchristos 
46d3ba7ba3Schristos 	atf_tc_set_md_var(tc, "descr", "Checks fcntl(2) F_GETPATH for vnodes");
470a76d2edSchristos }
480a76d2edSchristos 
490a76d2edSchristos static const struct {
500a76d2edSchristos 	const char *name;
510a76d2edSchristos 	int rv;
520a76d2edSchristos } files[] = {
530a76d2edSchristos 	{ "/bin/ls", 0 },
540a76d2edSchristos 	{ "/bin/sh", 0 },
550a76d2edSchristos 	{ "/dev/zero", 0 },
560a76d2edSchristos 	{ "/dev/null", 0 },
57d35ed14fSchristos 	{ "/sbin/chown", 0 },
580a76d2edSchristos 	{ "/", ENOENT },
590a76d2edSchristos };
600a76d2edSchristos 
ATF_TC_BODY(getpath_vnode,tc)61d3ba7ba3Schristos ATF_TC_BODY(getpath_vnode, tc)
620a76d2edSchristos {
630a76d2edSchristos 	char path[MAXPATHLEN];
640a76d2edSchristos 	int fd, rv;
650a76d2edSchristos 
660a76d2edSchristos 	for (size_t i = 0; i < __arraycount(files); i++) {
670a76d2edSchristos 		fd = open(files[i].name, O_RDONLY|O_NOFOLLOW);
68d35ed14fSchristos 		ATF_REQUIRE_MSG(fd != -1, "Cannot open `%s'", files[i].name);
690a76d2edSchristos 		rv = fcntl(fd, F_GETPATH, path);
700a76d2edSchristos 		if (files[i].rv) {
710a76d2edSchristos 			ATF_REQUIRE_MSG(errno == files[i].rv,
720a76d2edSchristos 			    "Unexpected error %d != %d for `%s'", errno,
730a76d2edSchristos 			    files[i].rv, files[i].name);
740a76d2edSchristos 		} else {
750a76d2edSchristos 			ATF_REQUIRE_MSG(rv != -1,
760a76d2edSchristos 			    "Can't get path for `%s' (%s)", files[i].name,
770a76d2edSchristos 			    strerror(errno));
780a76d2edSchristos 			ATF_REQUIRE_MSG(strcmp(files[i].name, path) == 0,
790a76d2edSchristos 			    "Bad name `%s' != `%s'", path, files[i].name);
800a76d2edSchristos 		close(fd);
810a76d2edSchristos 		}
820a76d2edSchristos 	}
830a76d2edSchristos }
840a76d2edSchristos 
85d3ba7ba3Schristos ATF_TC(getpath_memfd);
ATF_TC_HEAD(getpath_memfd,tc)86d3ba7ba3Schristos ATF_TC_HEAD(getpath_memfd, tc)
87d3ba7ba3Schristos {
88d3ba7ba3Schristos 
89d3ba7ba3Schristos 	atf_tc_set_md_var(tc, "descr",
90d3ba7ba3Schristos 	    "Checks fcntl(2) F_GETPATH for fds created by memfd_create");
91d3ba7ba3Schristos }
92d3ba7ba3Schristos 
93d3ba7ba3Schristos #define	MEMFD_NAME(name)	{ name, "memfd:" name }
94d3ba7ba3Schristos static const struct {
95d3ba7ba3Schristos 	const char *bare;
96d3ba7ba3Schristos 	const char *prefixed;
97d3ba7ba3Schristos } memfd_names[] = {
98d3ba7ba3Schristos 	MEMFD_NAME(""),
99d3ba7ba3Schristos 	MEMFD_NAME("some text"),
100d3ba7ba3Schristos 	MEMFD_NAME("memfd:"),
101d3ba7ba3Schristos 	MEMFD_NAME("../\\"),
102d3ba7ba3Schristos };
103d3ba7ba3Schristos 
ATF_TC_BODY(getpath_memfd,tc)104d3ba7ba3Schristos ATF_TC_BODY(getpath_memfd, tc)
105d3ba7ba3Schristos {
106d3ba7ba3Schristos 	char path[MAXPATHLEN];
107d3ba7ba3Schristos 	int fd, rv;
108d3ba7ba3Schristos 
109d3ba7ba3Schristos 	for (size_t i = 0; i < __arraycount(memfd_names); i++) {
110d3ba7ba3Schristos 		fd = memfd_create(memfd_names[i].bare, 0);
111*cf9621edSriastradh 		ATF_CHECK_MSG(fd != -1, "Failed to create memfd (%s)",
112d3ba7ba3Schristos 		    strerror(errno));
113*cf9621edSriastradh 		if (fd == -1)
114*cf9621edSriastradh 			continue;
115d3ba7ba3Schristos 		rv = fcntl(fd, F_GETPATH, path);
116*cf9621edSriastradh 		ATF_CHECK_MSG(rv != -1, "Can't get path `%s' (%s)",
117d3ba7ba3Schristos 		    memfd_names[i].bare, strerror(errno));
118*cf9621edSriastradh 		if (rv == -1)
119*cf9621edSriastradh 			goto next;
120*cf9621edSriastradh 		ATF_CHECK_MSG(strcmp(memfd_names[i].prefixed, path) == 0,
121d3ba7ba3Schristos 		    "Bad name `%s' != `%s'", path, memfd_names[i].prefixed);
122*cf9621edSriastradh next:		close(fd);
123d3ba7ba3Schristos 	}
124d3ba7ba3Schristos }
125d3ba7ba3Schristos 
ATF_TP_ADD_TCS(tp)1260a76d2edSchristos ATF_TP_ADD_TCS(tp)
1270a76d2edSchristos {
128d3ba7ba3Schristos 	ATF_TP_ADD_TC(tp, getpath_vnode);
129d3ba7ba3Schristos 	ATF_TP_ADD_TC(tp, getpath_memfd);
1300a76d2edSchristos 
1310a76d2edSchristos 	return atf_no_error();
1320a76d2edSchristos }
133