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