1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) Zilogic Systems Pvt. Ltd., 2018
4 * Email: code@zilogic.com
5 */
6
7 /*
8 * Test statx
9 *
10 * This code tests the functionality of statx system call.
11 *
12 * TESTCASE 1:
13 * The metadata for normal file are tested against predefined values:
14 * 1) gid
15 * 2) uid
16 * 3) mode
17 * 4) blocks
18 * 5) size
19 *
20 * A file is created and metadata values are set with
21 * predefined values.
22 * Then the values obtained using statx is checked against
23 * the predefined values.
24 *
25 * TESTCASE 2:
26 * The metadata for device file are tested against predefined values:
27 * 1) MAJOR number
28 * 2) MINOR number
29 *
30 * A device file is created seperately using mknod(must be a root user).
31 * The major number and minor number are set while creation.
32 * Major and minor numbers obtained using statx is checked against
33 * predefined values.
34 * Minimum kernel version required is 4.11.
35 */
36
37 #define _GNU_SOURCE
38 #include <stdio.h>
39 #include <sys/types.h>
40 #include <sys/sysmacros.h>
41 #include "tst_test.h"
42 #include "tst_safe_macros.h"
43 #include "lapi/stat.h"
44 #include <string.h>
45 #include <inttypes.h>
46
47 #define TESTFILE "test_file"
48 #define MNTPOINT "mntpoint/"
49 #define DEVICEFILE MNTPOINT"blk_dev"
50 #define MODE 0644
51
52 #define SIZE 256
53 #define MAJOR 8
54 #define MINOR 1
55
test_normal_file(void)56 static void test_normal_file(void)
57 {
58 struct statx buff;
59
60 TEST(statx(AT_FDCWD, TESTFILE, 0, 0, &buff));
61 if (TST_RET == 0)
62 tst_res(TPASS,
63 "statx(AT_FDCWD, %s, 0, 0, &buff)", TESTFILE);
64 else
65 tst_brk(TFAIL | TTERRNO,
66 "statx(AT_FDCWD, %s, 0, 0, &buff)", TESTFILE);
67
68 if (geteuid() == buff.stx_uid)
69 tst_res(TPASS, "stx_uid(%u) is correct", buff.stx_uid);
70 else
71 tst_res(TFAIL, "stx_uid(%u) is different from euid(%u)",
72 buff.stx_uid, geteuid());
73
74 if (getegid() == buff.stx_gid)
75 tst_res(TPASS, "stx_gid(%u) is correct", buff.stx_gid);
76 else
77 tst_res(TFAIL, "stx_gid(%u) is different from egid(%u)",
78 buff.stx_gid, getegid());
79
80 if (buff.stx_size == SIZE)
81 tst_res(TPASS,
82 "stx_size(%"PRIu64") is correct", buff.stx_size);
83 else
84 tst_res(TFAIL,
85 "stx_size(%"PRIu64") is different from expected(%u)",
86 buff.stx_size, SIZE);
87
88 if ((buff.stx_mode & ~(S_IFMT)) == MODE)
89 tst_res(TPASS, "stx_mode(%u) is correct", buff.stx_mode);
90 else
91 tst_res(TFAIL, "stx_mode(%u) is different from expected(%u)",
92 buff.stx_mode, MODE);
93
94
95 if (buff.stx_blocks <= buff.stx_blksize/512)
96 tst_res(TPASS, "stx_blocks(%"PRIu64") is valid",
97 buff.stx_blocks);
98 else
99 tst_res(TFAIL, "stx_blocks(%"PRIu64") is invalid",
100 buff.stx_blocks);
101
102 }
103
test_device_file(void)104 static void test_device_file(void)
105 {
106 struct statx buff;
107
108 TEST(statx(AT_FDCWD, DEVICEFILE, 0, 0, &buff));
109 if (TST_RET == 0)
110 tst_res(TPASS,
111 "statx(AT_FDCWD, %s, 0, 0, &buff)", DEVICEFILE);
112 else
113 tst_brk(TFAIL | TTERRNO,
114 "statx(AT_FDCWD, %s, 0, 0, &buff)", DEVICEFILE);
115
116 if (buff.stx_rdev_major == MAJOR)
117 tst_res(TPASS, "stx_rdev_major(%u) is correct",
118 buff.stx_rdev_major);
119 else
120 tst_res(TFAIL,
121 "stx_rdev_major(%u) is different from expected(%u)",
122 buff.stx_rdev_major, MAJOR);
123
124 if (buff.stx_rdev_minor == MINOR)
125 tst_res(TPASS, "stx_rdev_minor(%u) is correct",
126 buff.stx_rdev_minor);
127 else
128 tst_res(TFAIL,
129 "stx_rdev_minor(%u) is different from expected(%u)",
130 buff.stx_rdev_minor, MINOR);
131 }
132
133
134 struct tcase {
135 void (*tfunc)(void);
136 } tcases[] = {
137 {&test_normal_file},
138 {&test_device_file}
139 };
140
run(unsigned int i)141 static void run(unsigned int i)
142 {
143 tcases[i].tfunc();
144 }
145
setup(void)146 static void setup(void)
147 {
148 char data_buff[SIZE];
149 int file_fd;
150
151 memset(data_buff, '@', sizeof(data_buff));
152
153 file_fd = SAFE_OPEN(TESTFILE, O_RDWR|O_CREAT, MODE);
154 SAFE_WRITE(1, file_fd, data_buff, sizeof(data_buff));
155 SAFE_CLOSE(file_fd);
156
157 SAFE_MKNOD(DEVICEFILE, S_IFBLK | 0777, makedev(MAJOR, MINOR));
158 }
159
160 static struct tst_test test = {
161 .test = run,
162 .tcnt = ARRAY_SIZE(tcases),
163 .setup = setup,
164 .min_kver = "4.11",
165 .needs_devfs = 1,
166 .mntpoint = MNTPOINT,
167 .needs_root = 1,
168 .needs_tmpdir = 1,
169 };
170