1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) Zilogic Systems Pvt. Ltd., 2018
4*49cdfc7eSAndroid Build Coastguard Worker * Email: [email protected]
5*49cdfc7eSAndroid Build Coastguard Worker */
6*49cdfc7eSAndroid Build Coastguard Worker
7*49cdfc7eSAndroid Build Coastguard Worker /*\
8*49cdfc7eSAndroid Build Coastguard Worker * [Description]
9*49cdfc7eSAndroid Build Coastguard Worker *
10*49cdfc7eSAndroid Build Coastguard Worker * This code tests the functionality of statx system call.
11*49cdfc7eSAndroid Build Coastguard Worker *
12*49cdfc7eSAndroid Build Coastguard Worker * The metadata for normal file are tested against expected values:
13*49cdfc7eSAndroid Build Coastguard Worker *
14*49cdfc7eSAndroid Build Coastguard Worker * - gid
15*49cdfc7eSAndroid Build Coastguard Worker * - uid
16*49cdfc7eSAndroid Build Coastguard Worker * - mode
17*49cdfc7eSAndroid Build Coastguard Worker * - blocks
18*49cdfc7eSAndroid Build Coastguard Worker * - size
19*49cdfc7eSAndroid Build Coastguard Worker * - nlink
20*49cdfc7eSAndroid Build Coastguard Worker * - mnt_id
21*49cdfc7eSAndroid Build Coastguard Worker *
22*49cdfc7eSAndroid Build Coastguard Worker * The metadata for device file are tested against expected values:
23*49cdfc7eSAndroid Build Coastguard Worker *
24*49cdfc7eSAndroid Build Coastguard Worker * - MAJOR number
25*49cdfc7eSAndroid Build Coastguard Worker * - MINOR number
26*49cdfc7eSAndroid Build Coastguard Worker */
27*49cdfc7eSAndroid Build Coastguard Worker
28*49cdfc7eSAndroid Build Coastguard Worker #define _GNU_SOURCE
29*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
30*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
31*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
32*49cdfc7eSAndroid Build Coastguard Worker #include <sys/sysmacros.h>
33*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
34*49cdfc7eSAndroid Build Coastguard Worker #include "tst_safe_macros.h"
35*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/stat.h"
36*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/fcntl.h"
37*49cdfc7eSAndroid Build Coastguard Worker #include "tst_safe_stdio.h"
38*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
39*49cdfc7eSAndroid Build Coastguard Worker #include <inttypes.h>
40*49cdfc7eSAndroid Build Coastguard Worker
41*49cdfc7eSAndroid Build Coastguard Worker #define TESTFILE "test_file"
42*49cdfc7eSAndroid Build Coastguard Worker #define MNTPOINT "mntpoint/"
43*49cdfc7eSAndroid Build Coastguard Worker #define DEVICEFILE MNTPOINT"blk_dev"
44*49cdfc7eSAndroid Build Coastguard Worker #define MODE 0644
45*49cdfc7eSAndroid Build Coastguard Worker
46*49cdfc7eSAndroid Build Coastguard Worker #define SIZE 256
47*49cdfc7eSAndroid Build Coastguard Worker #define MAJOR 8
48*49cdfc7eSAndroid Build Coastguard Worker #define MINOR 1
49*49cdfc7eSAndroid Build Coastguard Worker
50*49cdfc7eSAndroid Build Coastguard Worker static int file_fd = -1;
51*49cdfc7eSAndroid Build Coastguard Worker
52*49cdfc7eSAndroid Build Coastguard Worker #ifdef HAVE_STRUCT_STATX_STX_MNT_ID
test_mnt_id(struct statx * buf)53*49cdfc7eSAndroid Build Coastguard Worker static void test_mnt_id(struct statx *buf)
54*49cdfc7eSAndroid Build Coastguard Worker {
55*49cdfc7eSAndroid Build Coastguard Worker FILE *file;
56*49cdfc7eSAndroid Build Coastguard Worker char line[PATH_MAX];
57*49cdfc7eSAndroid Build Coastguard Worker int pid, flag = 0;
58*49cdfc7eSAndroid Build Coastguard Worker unsigned int line_mjr, line_mnr;
59*49cdfc7eSAndroid Build Coastguard Worker uint64_t mnt_id;
60*49cdfc7eSAndroid Build Coastguard Worker
61*49cdfc7eSAndroid Build Coastguard Worker if (!(buf->stx_mask & STATX_MNT_ID)) {
62*49cdfc7eSAndroid Build Coastguard Worker tst_res(TCONF, "stx_mnt_id is not supported until linux 5.8");
63*49cdfc7eSAndroid Build Coastguard Worker return;
64*49cdfc7eSAndroid Build Coastguard Worker }
65*49cdfc7eSAndroid Build Coastguard Worker
66*49cdfc7eSAndroid Build Coastguard Worker file = SAFE_FOPEN("/proc/self/mountinfo", "r");
67*49cdfc7eSAndroid Build Coastguard Worker
68*49cdfc7eSAndroid Build Coastguard Worker while (fgets(line, sizeof(line), file)) {
69*49cdfc7eSAndroid Build Coastguard Worker if (sscanf(line, "%"SCNu64" %*d %d:%d", &mnt_id, &line_mjr, &line_mnr) != 3)
70*49cdfc7eSAndroid Build Coastguard Worker continue;
71*49cdfc7eSAndroid Build Coastguard Worker
72*49cdfc7eSAndroid Build Coastguard Worker if (line_mjr == buf->stx_dev_major && line_mnr == buf->stx_dev_minor) {
73*49cdfc7eSAndroid Build Coastguard Worker if (buf->stx_mnt_id == mnt_id) {
74*49cdfc7eSAndroid Build Coastguard Worker flag = 1;
75*49cdfc7eSAndroid Build Coastguard Worker break;
76*49cdfc7eSAndroid Build Coastguard Worker }
77*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "%s doesn't contain %"PRIu64" %d:%d",
78*49cdfc7eSAndroid Build Coastguard Worker line, (uint64_t)buf->stx_mnt_id, buf->stx_dev_major, buf->stx_dev_minor);
79*49cdfc7eSAndroid Build Coastguard Worker }
80*49cdfc7eSAndroid Build Coastguard Worker }
81*49cdfc7eSAndroid Build Coastguard Worker
82*49cdfc7eSAndroid Build Coastguard Worker SAFE_FCLOSE(file);
83*49cdfc7eSAndroid Build Coastguard Worker
84*49cdfc7eSAndroid Build Coastguard Worker if (flag)
85*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS,
86*49cdfc7eSAndroid Build Coastguard Worker "statx.stx_mnt_id equals to mount_id(%"PRIu64") in /proc/self/mountinfo",
87*49cdfc7eSAndroid Build Coastguard Worker mnt_id);
88*49cdfc7eSAndroid Build Coastguard Worker else
89*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
90*49cdfc7eSAndroid Build Coastguard Worker "statx.stx_mnt_id(%"PRIu64") doesn't exist in /proc/self/mountinfo",
91*49cdfc7eSAndroid Build Coastguard Worker (uint64_t)buf->stx_mnt_id);
92*49cdfc7eSAndroid Build Coastguard Worker
93*49cdfc7eSAndroid Build Coastguard Worker pid = getpid();
94*49cdfc7eSAndroid Build Coastguard Worker snprintf(line, PATH_MAX, "/proc/%d/fdinfo/%d", pid, file_fd);
95*49cdfc7eSAndroid Build Coastguard Worker TST_ASSERT_FILE_INT(line, "mnt_id:", buf->stx_mnt_id);
96*49cdfc7eSAndroid Build Coastguard Worker }
97*49cdfc7eSAndroid Build Coastguard Worker #endif
98*49cdfc7eSAndroid Build Coastguard Worker
test_normal_file(void)99*49cdfc7eSAndroid Build Coastguard Worker static void test_normal_file(void)
100*49cdfc7eSAndroid Build Coastguard Worker {
101*49cdfc7eSAndroid Build Coastguard Worker struct statx buff;
102*49cdfc7eSAndroid Build Coastguard Worker
103*49cdfc7eSAndroid Build Coastguard Worker TEST(statx(AT_FDCWD, TESTFILE, 0, 0, &buff));
104*49cdfc7eSAndroid Build Coastguard Worker if (TST_RET == 0)
105*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS,
106*49cdfc7eSAndroid Build Coastguard Worker "statx(AT_FDCWD, %s, 0, 0, &buff)", TESTFILE);
107*49cdfc7eSAndroid Build Coastguard Worker else
108*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TFAIL | TTERRNO,
109*49cdfc7eSAndroid Build Coastguard Worker "statx(AT_FDCWD, %s, 0, 0, &buff)", TESTFILE);
110*49cdfc7eSAndroid Build Coastguard Worker
111*49cdfc7eSAndroid Build Coastguard Worker if (geteuid() == buff.stx_uid)
112*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS, "stx_uid(%u) is correct", buff.stx_uid);
113*49cdfc7eSAndroid Build Coastguard Worker else
114*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "stx_uid(%u) is different from euid(%u)",
115*49cdfc7eSAndroid Build Coastguard Worker buff.stx_uid, geteuid());
116*49cdfc7eSAndroid Build Coastguard Worker
117*49cdfc7eSAndroid Build Coastguard Worker if (getegid() == buff.stx_gid)
118*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS, "stx_gid(%u) is correct", buff.stx_gid);
119*49cdfc7eSAndroid Build Coastguard Worker else
120*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "stx_gid(%u) is different from egid(%u)",
121*49cdfc7eSAndroid Build Coastguard Worker buff.stx_gid, getegid());
122*49cdfc7eSAndroid Build Coastguard Worker
123*49cdfc7eSAndroid Build Coastguard Worker if (buff.stx_size == SIZE)
124*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS,
125*49cdfc7eSAndroid Build Coastguard Worker "stx_size(%"PRIu64") is correct", (uint64_t)buff.stx_size);
126*49cdfc7eSAndroid Build Coastguard Worker else
127*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
128*49cdfc7eSAndroid Build Coastguard Worker "stx_size(%"PRIu64") is different from expected(%u)",
129*49cdfc7eSAndroid Build Coastguard Worker (uint64_t)buff.stx_size, SIZE);
130*49cdfc7eSAndroid Build Coastguard Worker
131*49cdfc7eSAndroid Build Coastguard Worker if ((buff.stx_mode & ~(S_IFMT)) == MODE)
132*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS, "stx_mode(%u) is correct", buff.stx_mode);
133*49cdfc7eSAndroid Build Coastguard Worker else
134*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "stx_mode(%u) is different from expected(%u)",
135*49cdfc7eSAndroid Build Coastguard Worker buff.stx_mode, MODE);
136*49cdfc7eSAndroid Build Coastguard Worker
137*49cdfc7eSAndroid Build Coastguard Worker if (buff.stx_blocks <= buff.stx_blksize/512 * 2)
138*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS, "stx_blocks(%"PRIu64") is valid",
139*49cdfc7eSAndroid Build Coastguard Worker (uint64_t)buff.stx_blocks);
140*49cdfc7eSAndroid Build Coastguard Worker else
141*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "stx_blocks(%"PRIu64") is invalid",
142*49cdfc7eSAndroid Build Coastguard Worker (uint64_t)buff.stx_blocks);
143*49cdfc7eSAndroid Build Coastguard Worker
144*49cdfc7eSAndroid Build Coastguard Worker if (buff.stx_nlink == 1)
145*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS, "stx_nlink(1) is correct");
146*49cdfc7eSAndroid Build Coastguard Worker else
147*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "stx_nlink(%u) is different from expected(1)",
148*49cdfc7eSAndroid Build Coastguard Worker buff.stx_nlink);
149*49cdfc7eSAndroid Build Coastguard Worker
150*49cdfc7eSAndroid Build Coastguard Worker #ifdef HAVE_STRUCT_STATX_STX_MNT_ID
151*49cdfc7eSAndroid Build Coastguard Worker test_mnt_id(&buff);
152*49cdfc7eSAndroid Build Coastguard Worker #else
153*49cdfc7eSAndroid Build Coastguard Worker tst_res(TCONF, "stx_mnt_id is not defined in struct statx");
154*49cdfc7eSAndroid Build Coastguard Worker #endif
155*49cdfc7eSAndroid Build Coastguard Worker }
156*49cdfc7eSAndroid Build Coastguard Worker
test_device_file(void)157*49cdfc7eSAndroid Build Coastguard Worker static void test_device_file(void)
158*49cdfc7eSAndroid Build Coastguard Worker {
159*49cdfc7eSAndroid Build Coastguard Worker struct statx buff;
160*49cdfc7eSAndroid Build Coastguard Worker
161*49cdfc7eSAndroid Build Coastguard Worker TEST(statx(AT_FDCWD, DEVICEFILE, 0, 0, &buff));
162*49cdfc7eSAndroid Build Coastguard Worker if (TST_RET == 0)
163*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS,
164*49cdfc7eSAndroid Build Coastguard Worker "statx(AT_FDCWD, %s, 0, 0, &buff)", DEVICEFILE);
165*49cdfc7eSAndroid Build Coastguard Worker else
166*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TFAIL | TTERRNO,
167*49cdfc7eSAndroid Build Coastguard Worker "statx(AT_FDCWD, %s, 0, 0, &buff)", DEVICEFILE);
168*49cdfc7eSAndroid Build Coastguard Worker
169*49cdfc7eSAndroid Build Coastguard Worker if (buff.stx_rdev_major == MAJOR)
170*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS, "stx_rdev_major(%u) is correct",
171*49cdfc7eSAndroid Build Coastguard Worker buff.stx_rdev_major);
172*49cdfc7eSAndroid Build Coastguard Worker else
173*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
174*49cdfc7eSAndroid Build Coastguard Worker "stx_rdev_major(%u) is different from expected(%u)",
175*49cdfc7eSAndroid Build Coastguard Worker buff.stx_rdev_major, MAJOR);
176*49cdfc7eSAndroid Build Coastguard Worker
177*49cdfc7eSAndroid Build Coastguard Worker if (buff.stx_rdev_minor == MINOR)
178*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS, "stx_rdev_minor(%u) is correct",
179*49cdfc7eSAndroid Build Coastguard Worker buff.stx_rdev_minor);
180*49cdfc7eSAndroid Build Coastguard Worker else
181*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
182*49cdfc7eSAndroid Build Coastguard Worker "stx_rdev_minor(%u) is different from expected(%u)",
183*49cdfc7eSAndroid Build Coastguard Worker buff.stx_rdev_minor, MINOR);
184*49cdfc7eSAndroid Build Coastguard Worker }
185*49cdfc7eSAndroid Build Coastguard Worker
186*49cdfc7eSAndroid Build Coastguard Worker
187*49cdfc7eSAndroid Build Coastguard Worker static struct tcase {
188*49cdfc7eSAndroid Build Coastguard Worker void (*tfunc)(void);
189*49cdfc7eSAndroid Build Coastguard Worker } tcases[] = {
190*49cdfc7eSAndroid Build Coastguard Worker {&test_normal_file},
191*49cdfc7eSAndroid Build Coastguard Worker {&test_device_file}
192*49cdfc7eSAndroid Build Coastguard Worker };
193*49cdfc7eSAndroid Build Coastguard Worker
run(unsigned int i)194*49cdfc7eSAndroid Build Coastguard Worker static void run(unsigned int i)
195*49cdfc7eSAndroid Build Coastguard Worker {
196*49cdfc7eSAndroid Build Coastguard Worker tcases[i].tfunc();
197*49cdfc7eSAndroid Build Coastguard Worker }
198*49cdfc7eSAndroid Build Coastguard Worker
setup(void)199*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
200*49cdfc7eSAndroid Build Coastguard Worker {
201*49cdfc7eSAndroid Build Coastguard Worker char data_buff[SIZE];
202*49cdfc7eSAndroid Build Coastguard Worker
203*49cdfc7eSAndroid Build Coastguard Worker umask(0);
204*49cdfc7eSAndroid Build Coastguard Worker
205*49cdfc7eSAndroid Build Coastguard Worker memset(data_buff, '@', sizeof(data_buff));
206*49cdfc7eSAndroid Build Coastguard Worker
207*49cdfc7eSAndroid Build Coastguard Worker file_fd = SAFE_OPEN(TESTFILE, O_RDWR|O_CREAT, MODE);
208*49cdfc7eSAndroid Build Coastguard Worker SAFE_WRITE(SAFE_WRITE_ALL, file_fd, data_buff, sizeof(data_buff));
209*49cdfc7eSAndroid Build Coastguard Worker
210*49cdfc7eSAndroid Build Coastguard Worker SAFE_MKNOD(DEVICEFILE, S_IFBLK | 0777, makedev(MAJOR, MINOR));
211*49cdfc7eSAndroid Build Coastguard Worker }
212*49cdfc7eSAndroid Build Coastguard Worker
cleanup(void)213*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
214*49cdfc7eSAndroid Build Coastguard Worker {
215*49cdfc7eSAndroid Build Coastguard Worker if (file_fd > -1)
216*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(file_fd);
217*49cdfc7eSAndroid Build Coastguard Worker }
218*49cdfc7eSAndroid Build Coastguard Worker
219*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
220*49cdfc7eSAndroid Build Coastguard Worker .test = run,
221*49cdfc7eSAndroid Build Coastguard Worker .tcnt = ARRAY_SIZE(tcases),
222*49cdfc7eSAndroid Build Coastguard Worker .setup = setup,
223*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup,
224*49cdfc7eSAndroid Build Coastguard Worker .min_kver = "4.11",
225*49cdfc7eSAndroid Build Coastguard Worker .needs_devfs = 1,
226*49cdfc7eSAndroid Build Coastguard Worker .mntpoint = MNTPOINT,
227*49cdfc7eSAndroid Build Coastguard Worker .needs_root = 1,
228*49cdfc7eSAndroid Build Coastguard Worker };
229