1f08c3bdfSopenharmony_ci/******************************************************************************
2f08c3bdfSopenharmony_ci *
3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines  Corp., 2006
4f08c3bdfSopenharmony_ci *  Author: Yi Yang <yyangcdl@cn.ibm.com>
5f08c3bdfSopenharmony_ci * Copyright (c) Cyril Hrubis 2014 <chrubis@suse.cz>
6f08c3bdfSopenharmony_ci *
7f08c3bdfSopenharmony_ci * This program is free software;  you can redistribute it and/or modify
8f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by
9f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or
10f08c3bdfSopenharmony_ci * (at your option) any later version.
11f08c3bdfSopenharmony_ci *
12f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful,
13f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY;  without even the implied warranty of
14f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15f08c3bdfSopenharmony_ci * the GNU General Public License for more details.
16f08c3bdfSopenharmony_ci *
17f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License
18f08c3bdfSopenharmony_ci * along with this program;  if not, write to the Free Software
19f08c3bdfSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20f08c3bdfSopenharmony_ci *
21f08c3bdfSopenharmony_ci * DESCRIPTION
22f08c3bdfSopenharmony_ci *  This test case will verify basic function of mknodat
23f08c3bdfSopenharmony_ci *  added by kernel 2.6.16 or up.
24f08c3bdfSopenharmony_ci *
25f08c3bdfSopenharmony_ci *****************************************************************************/
26f08c3bdfSopenharmony_ci
27f08c3bdfSopenharmony_ci#define _GNU_SOURCE
28f08c3bdfSopenharmony_ci
29f08c3bdfSopenharmony_ci#include <sys/types.h>
30f08c3bdfSopenharmony_ci#include <sys/stat.h>
31f08c3bdfSopenharmony_ci#include <stdlib.h>
32f08c3bdfSopenharmony_ci#include <errno.h>
33f08c3bdfSopenharmony_ci#include <string.h>
34f08c3bdfSopenharmony_ci#include <signal.h>
35f08c3bdfSopenharmony_ci#include "test.h"
36f08c3bdfSopenharmony_ci#include "safe_macros.h"
37f08c3bdfSopenharmony_ci#include "lapi/fcntl.h"
38f08c3bdfSopenharmony_ci#include "mknodat.h"
39f08c3bdfSopenharmony_ci
40f08c3bdfSopenharmony_ci#define PATHNAME "mknodattestdir"
41f08c3bdfSopenharmony_ci
42f08c3bdfSopenharmony_cistatic void setup(void);
43f08c3bdfSopenharmony_cistatic void cleanup(void);
44f08c3bdfSopenharmony_cistatic void clean(void);
45f08c3bdfSopenharmony_ci
46f08c3bdfSopenharmony_cistatic char testfilepath[256];
47f08c3bdfSopenharmony_cistatic char testfile[256];
48f08c3bdfSopenharmony_cistatic char testfile2[256];
49f08c3bdfSopenharmony_cistatic char testfile3[256];
50f08c3bdfSopenharmony_ci
51f08c3bdfSopenharmony_cistatic int dir_fd, fd;
52f08c3bdfSopenharmony_cistatic int fd_invalid = 100;
53f08c3bdfSopenharmony_cistatic int fd_atcwd = AT_FDCWD;
54f08c3bdfSopenharmony_ci
55f08c3bdfSopenharmony_cistatic struct test_case {
56f08c3bdfSopenharmony_ci	int *dir_fd;
57f08c3bdfSopenharmony_ci	const char *name;
58f08c3bdfSopenharmony_ci	int exp_ret;
59f08c3bdfSopenharmony_ci	int exp_errno;
60f08c3bdfSopenharmony_ci} test_cases[] = {
61f08c3bdfSopenharmony_ci	{&dir_fd, testfile, 0, 0},
62f08c3bdfSopenharmony_ci	{&dir_fd, testfile3, 0, 0},
63f08c3bdfSopenharmony_ci	{&fd, testfile2, -1, ENOTDIR},
64f08c3bdfSopenharmony_ci	{&fd_invalid, testfile, -1, EBADF},
65f08c3bdfSopenharmony_ci	{&fd_atcwd, testfile, 0, 0}
66f08c3bdfSopenharmony_ci};
67f08c3bdfSopenharmony_ci
68f08c3bdfSopenharmony_cichar *TCID = "mknodat01";
69f08c3bdfSopenharmony_ciint TST_TOTAL = ARRAY_SIZE(test_cases);
70f08c3bdfSopenharmony_ci
71f08c3bdfSopenharmony_cistatic dev_t dev;
72f08c3bdfSopenharmony_ci
73f08c3bdfSopenharmony_cistatic void verify_mknodat(struct test_case *test)
74f08c3bdfSopenharmony_ci{
75f08c3bdfSopenharmony_ci	TEST(mknodat(*test->dir_fd, test->name, S_IFREG, dev));
76f08c3bdfSopenharmony_ci
77f08c3bdfSopenharmony_ci	if (TEST_RETURN != test->exp_ret) {
78f08c3bdfSopenharmony_ci		tst_resm(TFAIL | TTERRNO,
79f08c3bdfSopenharmony_ci		         "mknodat() returned %ld, expected %d",
80f08c3bdfSopenharmony_ci			 TEST_RETURN, test->exp_ret);
81f08c3bdfSopenharmony_ci		return;
82f08c3bdfSopenharmony_ci	}
83f08c3bdfSopenharmony_ci
84f08c3bdfSopenharmony_ci	if (TEST_ERRNO != test->exp_errno) {
85f08c3bdfSopenharmony_ci		tst_resm(TFAIL | TTERRNO,
86f08c3bdfSopenharmony_ci		         "mknodat() returned wrong errno, expected %d",
87f08c3bdfSopenharmony_ci			 test->exp_errno);
88f08c3bdfSopenharmony_ci		return;
89f08c3bdfSopenharmony_ci	}
90f08c3bdfSopenharmony_ci
91f08c3bdfSopenharmony_ci	tst_resm(TPASS | TTERRNO, "mknodat() returned %ld", TEST_RETURN);
92f08c3bdfSopenharmony_ci}
93f08c3bdfSopenharmony_ci
94f08c3bdfSopenharmony_ciint main(int ac, char **av)
95f08c3bdfSopenharmony_ci{
96f08c3bdfSopenharmony_ci	int lc;
97f08c3bdfSopenharmony_ci	int i;
98f08c3bdfSopenharmony_ci
99f08c3bdfSopenharmony_ci	tst_parse_opts(ac, av, NULL, NULL);
100f08c3bdfSopenharmony_ci
101f08c3bdfSopenharmony_ci	setup();
102f08c3bdfSopenharmony_ci
103f08c3bdfSopenharmony_ci	for (lc = 0; TEST_LOOPING(lc); lc++) {
104f08c3bdfSopenharmony_ci		tst_count = 0;
105f08c3bdfSopenharmony_ci
106f08c3bdfSopenharmony_ci		for (i = 0; i < TST_TOTAL; i++)
107f08c3bdfSopenharmony_ci			verify_mknodat(test_cases + i);
108f08c3bdfSopenharmony_ci
109f08c3bdfSopenharmony_ci		/* clean created nodes before next run */
110f08c3bdfSopenharmony_ci		clean();
111f08c3bdfSopenharmony_ci	}
112f08c3bdfSopenharmony_ci
113f08c3bdfSopenharmony_ci	cleanup();
114f08c3bdfSopenharmony_ci	tst_exit();
115f08c3bdfSopenharmony_ci}
116f08c3bdfSopenharmony_ci
117f08c3bdfSopenharmony_cistatic void setup(void)
118f08c3bdfSopenharmony_ci{
119f08c3bdfSopenharmony_ci	char *tmpdir;
120f08c3bdfSopenharmony_ci
121f08c3bdfSopenharmony_ci	tst_sig(NOFORK, DEF_HANDLER, cleanup);
122f08c3bdfSopenharmony_ci
123f08c3bdfSopenharmony_ci	TEST_PAUSE;
124f08c3bdfSopenharmony_ci
125f08c3bdfSopenharmony_ci	tst_tmpdir();
126f08c3bdfSopenharmony_ci
127f08c3bdfSopenharmony_ci	/* Initialize test dir and file names */
128f08c3bdfSopenharmony_ci	tmpdir = tst_get_tmpdir();
129f08c3bdfSopenharmony_ci	sprintf(testfilepath, PATHNAME"/mknodattestfile%d", getpid());
130f08c3bdfSopenharmony_ci	sprintf(testfile, "mknodattestfile%d", getpid());
131f08c3bdfSopenharmony_ci	sprintf(testfile2, "mknodattestfile2%d", getpid());
132f08c3bdfSopenharmony_ci	sprintf(testfile3, "%s/mknodattestfile3%d", tmpdir, getpid());
133f08c3bdfSopenharmony_ci	free(tmpdir);
134f08c3bdfSopenharmony_ci
135f08c3bdfSopenharmony_ci	SAFE_MKDIR(cleanup, PATHNAME, 0700);
136f08c3bdfSopenharmony_ci
137f08c3bdfSopenharmony_ci	dir_fd = SAFE_OPEN(cleanup, PATHNAME, O_DIRECTORY);
138f08c3bdfSopenharmony_ci	fd = SAFE_OPEN(cleanup, testfile2, O_CREAT | O_RDWR, 0600);
139f08c3bdfSopenharmony_ci}
140f08c3bdfSopenharmony_ci
141f08c3bdfSopenharmony_cistatic void clean(void)
142f08c3bdfSopenharmony_ci{
143f08c3bdfSopenharmony_ci	SAFE_UNLINK(cleanup, testfilepath);
144f08c3bdfSopenharmony_ci	SAFE_UNLINK(cleanup, testfile3);
145f08c3bdfSopenharmony_ci	SAFE_UNLINK(cleanup, testfile);
146f08c3bdfSopenharmony_ci}
147f08c3bdfSopenharmony_ci
148f08c3bdfSopenharmony_cistatic void cleanup(void)
149f08c3bdfSopenharmony_ci{
150f08c3bdfSopenharmony_ci	if (dir_fd > 0 && close(dir_fd))
151f08c3bdfSopenharmony_ci		tst_resm(TWARN | TERRNO, "Failed to close(dir_fd)");
152f08c3bdfSopenharmony_ci
153f08c3bdfSopenharmony_ci	if (fd > 0 && close(fd))
154f08c3bdfSopenharmony_ci		tst_resm(TWARN | TERRNO, "Failed to close(fd)");
155f08c3bdfSopenharmony_ci
156f08c3bdfSopenharmony_ci	tst_rmdir();
157f08c3bdfSopenharmony_ci}
158