1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) Linux Test Project, 2009-2021
4 * Copyright (c) 2016 Oracle and/or its affiliates. All Rights Reserved.
5 * Copyright (c) International Business Machines  Corp., 2006
6 * Author: Yi Yang <yyangcdl@cn.ibm.com>
7 */
8
9/*\
10 * [Description]
11 * Basic unlinkat() test.
12 */
13
14#include "tst_test.h"
15#include "lapi/syscalls.h"
16#include "tst_safe_stdio.h"
17#include "lapi/fcntl.h"
18
19static const char pathname[] = "unlinkattestdir",
20		  subpathname[] = "unlinkatsubtestdir",
21		  subpathdir[] = "unlinkattestdir/unlinkatsubtestdir",
22		  testfile[] = "unlinkattestfile.txt",
23		  testfile2[] = "unlinkattestdir/unlinkattestfile.txt";
24
25static char *testfile3;
26
27static int fd;
28static int getfd(int i)
29{
30	if (i == 2)
31		fd = SAFE_OPEN(testfile3, O_CREAT | O_RDWR, 0600);
32	else
33		fd = SAFE_OPEN(pathname, O_DIRECTORY);
34
35	return fd;
36}
37
38static struct tcase {
39	int fd;
40	const char *filename;
41	int flag;
42	int exp_errno;
43} tc[] = {
44	{0, testfile, 0, 0},
45	{0, NULL, 0, 0},
46	{0, testfile, 0, ENOTDIR},
47	{100, testfile, 0, EBADF},
48	{0, testfile, 9999, EINVAL},
49	{AT_FDCWD, testfile, 0, 0},
50	{0, subpathname, AT_REMOVEDIR, 0},
51};
52
53static void run(unsigned int i)
54{
55	int fd3 = -1;
56
57	/* tesfile2 will be unlinked by test0. */
58	if (access(testfile2, F_OK))
59		SAFE_FILE_PRINTF(testfile2, testfile2);
60
61	/* testfile3 will be unlined by test1. */
62	if (access(testfile3, F_OK))
63		fd3 = SAFE_OPEN(testfile3, O_CREAT | O_RDWR, 0600);
64
65	/* subpathdir will be unlinked by test6. */
66	if (access(subpathdir, F_OK))
67		SAFE_MKDIR(subpathdir, 0700);
68
69	/* testfile must exist except test1 and test6. */
70	if (access(testfile, F_OK))
71		SAFE_FILE_PRINTF(testfile, testfile);
72
73	if (tc[i].fd)
74		TEST(unlinkat(tc[i].fd, tc[i].filename, tc[i].flag));
75	else
76		TEST(unlinkat(getfd(i), tc[i].filename, tc[i].flag));
77
78	if (TST_ERR == tc[i].exp_errno)
79		tst_res(TPASS | TTERRNO, "unlinkat() returned expected errno");
80	else
81		tst_res(TFAIL | TTERRNO, "unlinkat() failed");
82
83	if (!tc[i].fd)
84		SAFE_CLOSE(fd);
85
86	if (fd3 > 0)
87		SAFE_CLOSE(fd3);
88}
89
90static void setup(void)
91{
92	char buf[PATH_MAX];
93	SAFE_GETCWD(buf, PATH_MAX);
94	SAFE_ASPRINTF(&testfile3, "%s/unlinkatfile3.txt", buf);
95	tc[1].filename = testfile3;
96
97	SAFE_MKDIR(pathname, 0700);
98}
99
100static void cleanup(void)
101{
102	SAFE_UNLINK(testfile);
103	SAFE_UNLINK(testfile2);
104	SAFE_RMDIR(pathname);
105}
106
107static struct tst_test test = {
108	.needs_tmpdir = 1,
109	.tcnt = ARRAY_SIZE(tc),
110	.setup = setup,
111	.test = run,
112	.cleanup = cleanup,
113};
114