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 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