1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) Zilogic Systems Pvt. Ltd., 2018
4f08c3bdfSopenharmony_ci * Email: code@zilogic.com
5f08c3bdfSopenharmony_ci */
6f08c3bdfSopenharmony_ci
7f08c3bdfSopenharmony_ci/*\
8f08c3bdfSopenharmony_ci * [Description]
9f08c3bdfSopenharmony_ci *
10f08c3bdfSopenharmony_ci * This code tests the following flags with statx syscall:
11f08c3bdfSopenharmony_ci *
12f08c3bdfSopenharmony_ci * - AT_EMPTY_PATH
13f08c3bdfSopenharmony_ci * - AT_SYMLINK_NOFOLLOW
14f08c3bdfSopenharmony_ci *
15f08c3bdfSopenharmony_ci * A test file and a link for it is created.
16f08c3bdfSopenharmony_ci *
17f08c3bdfSopenharmony_ci * To check empty path flag, test file fd alone is passed.
18f08c3bdfSopenharmony_ci * Predefined size of testfile is checked against obtained value.
19f08c3bdfSopenharmony_ci *
20f08c3bdfSopenharmony_ci * To check symlink no follow flag, the linkname is statxed.
21f08c3bdfSopenharmony_ci * To ensure that link is not dereferenced, obtained inode is compared
22f08c3bdfSopenharmony_ci * with test file inode.
23f08c3bdfSopenharmony_ci */
24f08c3bdfSopenharmony_ci
25f08c3bdfSopenharmony_ci#define _GNU_SOURCE
26f08c3bdfSopenharmony_ci#include <stdio.h>
27f08c3bdfSopenharmony_ci#include <inttypes.h>
28f08c3bdfSopenharmony_ci#include "tst_test.h"
29f08c3bdfSopenharmony_ci#include "tst_safe_macros.h"
30f08c3bdfSopenharmony_ci#include "lapi/stat.h"
31f08c3bdfSopenharmony_ci#include "lapi/fcntl.h"
32f08c3bdfSopenharmony_ci
33f08c3bdfSopenharmony_ci#define TESTFILE "test_temp"
34f08c3bdfSopenharmony_ci#define LINK_FILE "test_temp_ln"
35f08c3bdfSopenharmony_ci#define MODE 0644
36f08c3bdfSopenharmony_ci#define SIZE 14
37f08c3bdfSopenharmony_ci
38f08c3bdfSopenharmony_cistatic int file_fd;
39f08c3bdfSopenharmony_ci
40f08c3bdfSopenharmony_cistatic void test_empty_path(void)
41f08c3bdfSopenharmony_ci{
42f08c3bdfSopenharmony_ci	struct statx buf;
43f08c3bdfSopenharmony_ci
44f08c3bdfSopenharmony_ci	TEST(statx(file_fd, "", AT_EMPTY_PATH, 0, &buf));
45f08c3bdfSopenharmony_ci	if (TST_RET == 0)
46f08c3bdfSopenharmony_ci		tst_res(TPASS,
47f08c3bdfSopenharmony_ci			"statx(file_fd, \"\", AT_EMPTY_PATH, 0, &buf)");
48f08c3bdfSopenharmony_ci	else
49f08c3bdfSopenharmony_ci		tst_brk(TFAIL | TTERRNO,
50f08c3bdfSopenharmony_ci			"statx(file_fd, \"\", AT_EMPTY_PATH, 0, &buff)");
51f08c3bdfSopenharmony_ci
52f08c3bdfSopenharmony_ci	if (buf.stx_size == SIZE)
53f08c3bdfSopenharmony_ci		tst_res(TPASS,
54f08c3bdfSopenharmony_ci			"stx_size(%"PRIu64") is correct", (uint64_t)buf.stx_size);
55f08c3bdfSopenharmony_ci	else
56f08c3bdfSopenharmony_ci		tst_res(TFAIL,
57f08c3bdfSopenharmony_ci			"stx_size(%"PRIu64") is not same as expected(%u)",
58f08c3bdfSopenharmony_ci			(uint64_t)buf.stx_size, SIZE);
59f08c3bdfSopenharmony_ci
60f08c3bdfSopenharmony_ci}
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_cistatic void test_sym_link(void)
63f08c3bdfSopenharmony_ci{
64f08c3bdfSopenharmony_ci	struct statx fbuf;
65f08c3bdfSopenharmony_ci	struct statx lbuf;
66f08c3bdfSopenharmony_ci
67f08c3bdfSopenharmony_ci	TEST(statx(AT_FDCWD, TESTFILE, 0, 0, &fbuf));
68f08c3bdfSopenharmony_ci
69f08c3bdfSopenharmony_ci	if (TST_RET == 0)
70f08c3bdfSopenharmony_ci		tst_res(TPASS,
71f08c3bdfSopenharmony_ci			"statx(AT_FDCWD, %s, 0, 0, &fbuf)", TESTFILE);
72f08c3bdfSopenharmony_ci	else
73f08c3bdfSopenharmony_ci		tst_brk(TFAIL | TTERRNO,
74f08c3bdfSopenharmony_ci			"statx(AT_FDCWD, %s, 0, 0, &fbuf)", TESTFILE);
75f08c3bdfSopenharmony_ci
76f08c3bdfSopenharmony_ci	TEST(statx(AT_FDCWD, LINK_FILE, AT_SYMLINK_NOFOLLOW, 0, &lbuf));
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_ci	if (TST_RET == 0)
79f08c3bdfSopenharmony_ci		tst_res(TPASS,
80f08c3bdfSopenharmony_ci			"statx(AT_FDCWD, %s, AT_SYMLINK_NOFOLLOW, 0,&lbuf)",
81f08c3bdfSopenharmony_ci			LINK_FILE);
82f08c3bdfSopenharmony_ci	else
83f08c3bdfSopenharmony_ci		tst_brk(TFAIL | TTERRNO,
84f08c3bdfSopenharmony_ci			"statx(AT_FDCWD, %s, AT_SYMLINK_NOFOLLOW, 0,&lbuf)",
85f08c3bdfSopenharmony_ci			LINK_FILE);
86f08c3bdfSopenharmony_ci
87f08c3bdfSopenharmony_ci	if (fbuf.stx_ino != lbuf.stx_ino)
88f08c3bdfSopenharmony_ci		tst_res(TPASS, "Statx symlink flag worked as expected");
89f08c3bdfSopenharmony_ci	else
90f08c3bdfSopenharmony_ci		tst_res(TFAIL,
91f08c3bdfSopenharmony_ci			"Statx symlink flag failed to work as expected");
92f08c3bdfSopenharmony_ci}
93f08c3bdfSopenharmony_ci
94f08c3bdfSopenharmony_cistatic struct tcase {
95f08c3bdfSopenharmony_ci	void (*tfunc)(void);
96f08c3bdfSopenharmony_ci} tcases[] = {
97f08c3bdfSopenharmony_ci	{&test_empty_path},
98f08c3bdfSopenharmony_ci	{&test_sym_link}
99f08c3bdfSopenharmony_ci};
100f08c3bdfSopenharmony_ci
101f08c3bdfSopenharmony_cistatic void run(unsigned int i)
102f08c3bdfSopenharmony_ci{
103f08c3bdfSopenharmony_ci	tcases[i].tfunc();
104f08c3bdfSopenharmony_ci}
105f08c3bdfSopenharmony_ci
106f08c3bdfSopenharmony_cistatic void setup(void)
107f08c3bdfSopenharmony_ci{
108f08c3bdfSopenharmony_ci	char data_buf[SIZE] = "LinusTorvalds";
109f08c3bdfSopenharmony_ci
110f08c3bdfSopenharmony_ci	file_fd = SAFE_OPEN(TESTFILE, O_RDWR | O_CREAT, MODE);
111f08c3bdfSopenharmony_ci	SAFE_WRITE(SAFE_WRITE_ANY, file_fd, data_buf, sizeof(data_buf));
112f08c3bdfSopenharmony_ci
113f08c3bdfSopenharmony_ci	SAFE_SYMLINK(TESTFILE, LINK_FILE);
114f08c3bdfSopenharmony_ci}
115f08c3bdfSopenharmony_ci
116f08c3bdfSopenharmony_cistatic void cleanup(void)
117f08c3bdfSopenharmony_ci{
118f08c3bdfSopenharmony_ci	if (file_fd > 0)
119f08c3bdfSopenharmony_ci		SAFE_CLOSE(file_fd);
120f08c3bdfSopenharmony_ci}
121f08c3bdfSopenharmony_ci
122f08c3bdfSopenharmony_cistatic struct tst_test test = {
123f08c3bdfSopenharmony_ci	.test = run,
124f08c3bdfSopenharmony_ci	.tcnt = ARRAY_SIZE(tcases),
125f08c3bdfSopenharmony_ci	.setup = setup,
126f08c3bdfSopenharmony_ci	.cleanup = cleanup,
127f08c3bdfSopenharmony_ci	.min_kver = "4.11",
128f08c3bdfSopenharmony_ci	.needs_tmpdir = 1,
129f08c3bdfSopenharmony_ci};
130