xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/getxattr/getxattr02.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2011  Red Hat, Inc.
4  * Copyright (c) Linux Test Project, 2012-2022
5  * Copyright (c) 2023 Marius Kittler <[email protected]>
6  */
7 
8 /*\
9  * [Description]
10  *
11  * In the user.* namespace, only regular files and directories can
12  * have extended attributes. Otherwise getxattr(2) will return -1
13  * and set errno to ENODATA.
14  *
15  * There are 4 test cases:
16  *
17  * - Get attribute from a FIFO, setxattr(2) should return -1 and
18  *    set errno to ENODATA
19  * - Get attribute from a char special file, setxattr(2) should
20  *    return -1 and set errno to ENODATA
21  * - Get attribute from a block special file, setxattr(2) should
22  *    return -1 and set errno to ENODATA
23  * - Get attribute from a UNIX domain socket, setxattr(2) should
24  *    return -1 and set errno to ENODATA
25  */
26 
27 #include <sys/types.h>
28 #include <sys/sysmacros.h>
29 #include <sys/xattr.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 
33 #include "tst_res_flags.h"
34 #include "tst_test.h"
35 #include "tst_test_macros.h"
36 
37 #define MNTPOINT "mntpoint"
38 #define FNAME MNTPOINT"/getxattr02"
39 #define XATTR_TEST_KEY "user.testkey"
40 
41 #define FIFO "getxattr02fifo"
42 #define CHR  "getxattr02chr"
43 #define BLK  "getxattr02blk"
44 #define SOCK "getxattr02sock"
45 
46 static struct test_case {
47 	const char *desc;
48 	char *fname;
49 	int mode;
50 } tcases[] = {
51 	{
52 	 .desc = "get attr from fifo",
53 	 .fname = FNAME FIFO,
54 	 .mode = S_IFIFO,
55 	},
56 	{
57 	 .desc = "get attr from char special",
58 	 .fname = FNAME CHR,
59 	 .mode = S_IFCHR,
60 	},
61 	{
62 	 .desc = "get attr from block special",
63 	 .fname = FNAME BLK,
64 	 .mode = S_IFBLK,
65 	},
66 	{
67 	 .desc = "get attr from UNIX domain socket",
68 	 .fname = FNAME SOCK,
69 	 .mode = S_IFSOCK,
70 	},
71 };
72 
run(unsigned int i)73 static void run(unsigned int i)
74 {
75 	char buf[BUFSIZ];
76 	struct test_case *tc = &tcases[i];
77 	dev_t dev = tc->mode == S_IFCHR ? makedev(1, 3) : 0u;
78 
79 	if (mknod(tc->fname, tc->mode | 0777, dev) < 0)
80 		tst_brk(TBROK | TERRNO, "create %s (mode %i) failed (%s)",
81 				tc->fname, tc->mode, tc->desc);
82 
83 	TEST(getxattr(tc->fname, XATTR_TEST_KEY, buf, BUFSIZ));
84 	if (TST_RET == -1 && TST_ERR == ENODATA)
85 		tst_res(TPASS | TTERRNO, "%s: expected return value",
86 				tc->desc);
87 	else
88 		tst_res(TFAIL | TTERRNO,
89 				"%s: unexpected return value - expected errno %d - got",
90 				tc->desc, ENODATA);
91 
92 	unlink(tc->fname);
93 }
94 
setup(void)95 static void setup(void)
96 {
97 	/* assert xattr support in the current filesystem */
98 	SAFE_TOUCH(FNAME, 0644, NULL);
99 	TEST(setxattr(FNAME, "user.test", "test", 4, XATTR_CREATE));
100 	if (TST_ERR == ENOTSUP)
101 		tst_brk(TCONF,
102 			"No xattr support in fs or mount without user_xattr option");
103 	else if (TST_RET != 0)
104 		tst_brk(TBROK | TTERRNO, "setxattr failed");
105 }
106 
107 static struct tst_test test = {
108 	.all_filesystems = 1,
109 	.needs_root = 1,
110 	.mntpoint = MNTPOINT,
111 	.mount_device = 1,
112 	.skip_filesystems = (const char *const []) {
113 			"ramfs",
114 			"nfs",
115 			NULL
116 	},
117 	.setup = setup,
118 	.test = run,
119 	.tcnt = ARRAY_SIZE(tcases)
120 };
121