1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2021 FUJITSU LIMITED. All rights reserved.
4 * Author: Yang Xu <xuyang2018.jy@fujitsu.com>
5 */
6
7 /*\
8 * [Description]
9 *
10 * This case tests whether the attributes field of statx received expected value
11 * by using flags in the stx_attributes_mask field of statx.
12 * File set with following flags by using SAFE_IOCTL:
13 *
14 * - STATX_ATTR_COMPRESSED: The file is compressed by the filesystem.
15 * - STATX_ATTR_IMMUTABLE: The file cannot be modified.
16 * - STATX_ATTR_APPEND: The file can only be opened in append mode for writing.
17 * - STATX_ATTR_NODUMP: File is not a candidate for backup when a backup
18 * program such as dump(8) is run.
19 *
20 * Two directories are tested.
21 * First directory has all flags set. Second directory has no flags set.
22 */
23
24 #define _GNU_SOURCE
25 #include "tst_test.h"
26 #include "lapi/fs.h"
27 #include <stdlib.h>
28 #include "lapi/stat.h"
29
30 #define MOUNT_POINT "mntpoint"
31 #define TESTDIR_FLAGGED MOUNT_POINT"/test_dir1"
32 #define TESTDIR_UNFLAGGED MOUNT_POINT"/test_dir2"
33
34 static int fd, clear_flags;
35 static int supp_compr = 1, supp_append = 1, supp_immutable = 1, supp_nodump = 1;
36
run(unsigned int flag)37 static void run(unsigned int flag)
38 {
39 struct statx buf;
40
41 TEST(statx(AT_FDCWD, flag ? TESTDIR_FLAGGED : TESTDIR_UNFLAGGED, 0, 0, &buf));
42 if (TST_RET == 0)
43 tst_res(TPASS,
44 "sys_statx(AT_FDCWD, %s, 0, 0, &buf)",
45 flag ? TESTDIR_FLAGGED : TESTDIR_UNFLAGGED);
46 else
47 tst_brk(TFAIL | TTERRNO,
48 "sys_statx(AT_FDCWD, %s, 0, 0, &buf)",
49 flag ? TESTDIR_FLAGGED : TESTDIR_UNFLAGGED);
50
51 if (supp_compr) {
52 if (buf.stx_attributes & STATX_ATTR_COMPRESSED)
53 tst_res(flag ? TPASS : TFAIL,
54 "STATX_ATTR_COMPRESSED flag is set");
55 else
56 tst_res(flag ? TFAIL : TPASS,
57 "STATX_ATTR_COMPRESSED flag is not set");
58 }
59 if (supp_append) {
60 if (buf.stx_attributes & STATX_ATTR_APPEND)
61 tst_res(flag ? TPASS : TFAIL,
62 "STATX_ATTR_APPEND flag is set");
63 else
64 tst_res(flag ? TFAIL : TPASS,
65 "STATX_ATTR_APPEND flag is not set");
66 }
67 if (supp_immutable) {
68 if (buf.stx_attributes & STATX_ATTR_IMMUTABLE)
69 tst_res(flag ? TPASS : TFAIL,
70 "STATX_ATTR_IMMUTABLE flag is set");
71 else
72 tst_res(flag ? TFAIL : TPASS,
73 "STATX_ATTR_IMMUTABLE flag is not set");
74 }
75 if (supp_nodump) {
76 if (buf.stx_attributes & STATX_ATTR_NODUMP)
77 tst_res(flag ? TPASS : TFAIL,
78 "STATX_ATTR_NODUMP flag is set");
79 else
80 tst_res(flag ? TFAIL : TPASS,
81 "STATX_ATTR_NODUMP flag is not set");
82 }
83 }
84
caid_flags_setup(void)85 static void caid_flags_setup(void)
86 {
87 int attr, ret;
88
89 fd = SAFE_OPEN(TESTDIR_FLAGGED, O_RDONLY | O_DIRECTORY);
90
91 ret = ioctl(fd, FS_IOC_GETFLAGS, &attr);
92 if (ret < 0) {
93 if (errno == ENOTTY)
94 tst_brk(TCONF | TERRNO, "FS_IOC_GETFLAGS not supported");
95
96 /* ntfs3g fuse fs returns wrong errno for unimplemented ioctls */
97 if (!strcmp(tst_device->fs_type, "ntfs")) {
98 tst_brk(TCONF | TERRNO,
99 "ntfs3g does not support FS_IOC_GETFLAGS");
100 }
101
102 tst_brk(TBROK | TERRNO, "ioctl(%i, FS_IOC_GETFLAGS, ...)", fd);
103 }
104
105 if (supp_compr)
106 attr |= FS_COMPR_FL;
107 if (supp_append)
108 attr |= FS_APPEND_FL;
109 if (supp_immutable)
110 attr |= FS_IMMUTABLE_FL;
111 if (supp_nodump)
112 attr |= FS_NODUMP_FL;
113
114 ret = ioctl(fd, FS_IOC_SETFLAGS, &attr);
115 if (ret < 0)
116 tst_brk(TBROK | TERRNO, "ioctl(%i, FS_IOC_SETFLAGS, %i)", fd, attr);
117
118 clear_flags = 1;
119 }
120
setup(void)121 static void setup(void)
122 {
123 struct statx buf;
124
125 SAFE_MKDIR(TESTDIR_FLAGGED, 0777);
126 SAFE_MKDIR(TESTDIR_UNFLAGGED, 0777);
127
128 TEST(statx(AT_FDCWD, TESTDIR_FLAGGED, 0, 0, &buf));
129 if (TST_RET == -1)
130 tst_brk(TFAIL | TTERRNO,
131 "sys_statx(AT_FDCWD, %s, 0, 0, &buf)", TESTDIR_FLAGGED);
132
133 if ((buf.stx_attributes_mask & FS_COMPR_FL) == 0) {
134 supp_compr = 0;
135 tst_res(TCONF, "filesystem doesn't support FS_COMPR_FL");
136 }
137 if ((buf.stx_attributes_mask & FS_APPEND_FL) == 0) {
138 supp_append = 0;
139 tst_res(TCONF, "filesystem doesn't support FS_APPEND_FL");
140 }
141 if ((buf.stx_attributes_mask & FS_IMMUTABLE_FL) == 0) {
142 supp_immutable = 0;
143 tst_res(TCONF, "filesystem doesn't support FS_IMMUTABLE_FL");
144 }
145 if ((buf.stx_attributes_mask & FS_NODUMP_FL) == 0) {
146 supp_nodump = 0;
147 tst_res(TCONF, "filesystem doesn't support FS_NODUMP_FL");
148 }
149 if (!(supp_compr || supp_append || supp_immutable || supp_nodump))
150 tst_brk(TCONF,
151 "filesystem doesn't support the above any attr, skip it");
152
153 caid_flags_setup();
154 }
155
cleanup(void)156 static void cleanup(void)
157 {
158 int attr;
159
160 if (clear_flags) {
161 SAFE_IOCTL(fd, FS_IOC_GETFLAGS, &attr);
162 attr &= ~(FS_COMPR_FL | FS_APPEND_FL | FS_IMMUTABLE_FL | FS_NODUMP_FL);
163 SAFE_IOCTL(fd, FS_IOC_SETFLAGS, &attr);
164 }
165
166 if (fd > 0)
167 SAFE_CLOSE(fd);
168 }
169
170 static struct tst_test test = {
171 .test = run,
172 .tcnt = 2,
173 .setup = setup,
174 .cleanup = cleanup,
175 .needs_root = 1,
176 .all_filesystems = 1,
177 .mount_device = 1,
178 .mntpoint = MOUNT_POINT,
179 .min_kver = "4.11",
180 };
181