// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) Zilogic Systems Pvt. Ltd., 2018 * Email: code@zilogic.com */ /* * Test statx * * This code tests if the attributes field of statx received expected value. * File set with following flags by using SAFE_IOCTL: * 1) STATX_ATTR_COMPRESSED - The file is compressed by the filesystem. * 2) STATX_ATTR_IMMUTABLE - The file cannot be modified. * 3) STATX_ATTR_APPEND - The file can only be opened in append mode for * writing. * 4) STATX_ATTR_NODUMP - File is not a candidate for backup when a backup * program such as dump(8) is run. * * Two directories are tested. * First directory has all flags set. * Second directory has no flags set. * * Minimum kernel version required is 4.11. */ #define _GNU_SOURCE #include "tst_test.h" #include "lapi/fs.h" #include <stdlib.h> #include "lapi/stat.h" #define MOUNT_POINT "mntpoint" #define TESTDIR_FLAGGED MOUNT_POINT"/test_dir1" #define TESTDIR_UNFLAGGED MOUNT_POINT"/test_dir2" static int fd, clear_flags; static void test_flagged(void) { struct statx buf; TEST(statx(AT_FDCWD, TESTDIR_FLAGGED, 0, 0, &buf)); if (TST_RET == 0) tst_res(TPASS, "sys_statx(AT_FDCWD, %s, 0, 0, &buf)", TESTDIR_FLAGGED); else tst_brk(TFAIL | TTERRNO, "sys_statx(AT_FDCWD, %s, 0, 0, &buf)", TESTDIR_FLAGGED); if (buf.stx_attributes & STATX_ATTR_COMPRESSED) tst_res(TPASS, "STATX_ATTR_COMPRESSED flag is set"); else tst_res(TFAIL, "STATX_ATTR_COMPRESSED flag is not set"); if (buf.stx_attributes & STATX_ATTR_APPEND) tst_res(TPASS, "STATX_ATTR_APPEND flag is set"); else tst_res(TFAIL, "STATX_ATTR_APPEND flag is not set"); if (buf.stx_attributes & STATX_ATTR_IMMUTABLE) tst_res(TPASS, "STATX_ATTR_IMMUTABLE flag is set"); else tst_res(TFAIL, "STATX_ATTR_IMMUTABLE flag is not set"); if (buf.stx_attributes & STATX_ATTR_NODUMP) tst_res(TPASS, "STATX_ATTR_NODUMP flag is set"); else tst_res(TFAIL, "STATX_ATTR_NODUMP flag is not set"); } static void test_unflagged(void) { struct statx buf; TEST(statx(AT_FDCWD, TESTDIR_UNFLAGGED, 0, 0, &buf)); if (TST_RET == 0) tst_res(TPASS, "sys_statx(AT_FDCWD, %s, 0, 0, &buf)", TESTDIR_UNFLAGGED); else tst_brk(TFAIL | TTERRNO, "sys_statx(AT_FDCWD, %s, 0, 0, &buf)", TESTDIR_UNFLAGGED); if ((buf.stx_attributes & STATX_ATTR_COMPRESSED) == 0) tst_res(TPASS, "STATX_ATTR_COMPRESSED flag is not set"); else tst_res(TFAIL, "STATX_ATTR_COMPRESSED flag is set"); if ((buf.stx_attributes & STATX_ATTR_APPEND) == 0) tst_res(TPASS, "STATX_ATTR_APPEND flag is not set"); else tst_res(TFAIL, "STATX_ATTR_APPEND flag is set"); if ((buf.stx_attributes & STATX_ATTR_IMMUTABLE) == 0) tst_res(TPASS, "STATX_ATTR_IMMUTABLE flag is not set"); else tst_res(TFAIL, "STATX_ATTR_IMMUTABLE flag is set"); if ((buf.stx_attributes & STATX_ATTR_NODUMP) == 0) tst_res(TPASS, "STATX_ATTR_NODUMP flag is not set"); else tst_res(TFAIL, "STATX_ATTR_NODUMP flag is set"); } struct test_cases { void (*tfunc)(void); } tcases[] = { {&test_flagged}, {&test_unflagged}, }; static void run(unsigned int i) { tcases[i].tfunc(); } static void caid_flags_setup(void) { int attr, ret; fd = SAFE_OPEN(TESTDIR_FLAGGED, O_RDONLY | O_DIRECTORY); ret = ioctl(fd, FS_IOC_GETFLAGS, &attr); if (ret < 0) { if (errno == ENOTTY) tst_brk(TCONF | TERRNO, "FS_IOC_GETFLAGS not supported"); /* ntfs3g fuse fs returns wrong errno for unimplemented ioctls */ if (!strcmp(tst_device->fs_type, "ntfs")) { tst_brk(TCONF | TERRNO, "ntfs3g does not support FS_IOC_GETFLAGS"); } tst_brk(TBROK | TERRNO, "ioctl(%i, FS_IOC_GETFLAGS, ...)", fd); } attr |= FS_COMPR_FL | FS_APPEND_FL | FS_IMMUTABLE_FL | FS_NODUMP_FL; ret = ioctl(fd, FS_IOC_SETFLAGS, &attr); if (ret < 0) { if (errno == EOPNOTSUPP) tst_brk(TCONF, "Flags not supported"); tst_brk(TBROK | TERRNO, "ioctl(%i, FS_IOC_SETFLAGS, %i)", fd, attr); } clear_flags = 1; } static void setup(void) { SAFE_MKDIR(TESTDIR_FLAGGED, 0777); SAFE_MKDIR(TESTDIR_UNFLAGGED, 0777); if (!strcmp(tst_device->fs_type, "btrfs") && tst_kvercmp(4, 13, 0) < 0) tst_brk(TCONF, "Btrfs statx() supported since 4.13"); caid_flags_setup(); } static void cleanup(void) { int attr; if (clear_flags) { SAFE_IOCTL(fd, FS_IOC_GETFLAGS, &attr); attr &= ~(FS_COMPR_FL | FS_APPEND_FL | FS_IMMUTABLE_FL | FS_NODUMP_FL); SAFE_IOCTL(fd, FS_IOC_SETFLAGS, &attr); } if (fd > 0) SAFE_CLOSE(fd); } static struct tst_test test = { .test = run, .tcnt = ARRAY_SIZE(tcases), .setup = setup, .cleanup = cleanup, .needs_root = 1, .all_filesystems = 1, .mount_device = 1, .needs_tmpdir = 1, .mntpoint = MOUNT_POINT, .min_kver = "4.11", };