• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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