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 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 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 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 141 static void run(unsigned int i) 142 { 143 tcases[i].tfunc(); 144 } 145 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