1 /*
2  * Copyright (C) 2011  Red Hat, Inc.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of version 2 of the GNU General Public
6  * License as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it would be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * Further, this software is distributed without any warranty that it
13  * is free of the rightful claim of any third person regarding
14  * infringement or the like.  Any license provided herein, whether
15  * implied or otherwise, applies only to this software file.  Patent
16  * licenses, if any, provided herein do not apply to combinations of
17  * this program with other software, or any other product whatsoever.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301, USA.
23  */
24 
25 /*
26  * Basic tests for getxattr(2) and make sure getxattr(2) handles error
27  * conditions correctly.
28  *
29  * There are 4 test cases:
30  * 1. Get an non-existing attribute,
31  *    getxattr(2) should return -1 and set errno to ENOATTR
32  * 2. Buffer size is smaller than attribute value size,
33  *    getxattr(2) should return -1 and set errno to ERANGE
34  * 3. Get attribute, getxattr(2) should succeed
35  * 4. Verify the attribute got by getxattr(2) is same as the value we set
36  */
37 
38 #include "config.h"
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <unistd.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #ifdef HAVE_ATTR_XATTR_H
48 #include <attr/xattr.h>
49 #endif
50 #include "test.h"
51 
52 char *TCID = "getxattr01";
53 
54 #ifdef HAVE_ATTR_XATTR_H
55 #define XATTR_TEST_KEY "user.testkey"
56 #define XATTR_TEST_VALUE "this is a test value"
57 #define XATTR_TEST_VALUE_SIZE 20
58 #define BUFFSIZE 64
59 
60 static void setup(void);
61 static void cleanup(void);
62 
63 char filename[BUFSIZ];
64 
65 struct test_case {
66 	char *fname;
67 	char *key;
68 	char *value;
69 	size_t size;
70 	int exp_err;
71 };
72 struct test_case tc[] = {
73 	{			/* case 00, get non-existing attribute */
74 	 .fname = filename,
75 	 .key = "user.nosuchkey",
76 	 .value = NULL,
77 	 .size = BUFFSIZE - 1,
78 	 .exp_err = ENOATTR,
79 	 },
80 	{			/* case 01, small value buffer */
81 	 .fname = filename,
82 	 .key = XATTR_TEST_KEY,
83 	 .value = NULL,
84 	 .size = 1,
85 	 .exp_err = ERANGE,
86 	 },
87 	{			/* case 02, get existing attribute */
88 	 .fname = filename,
89 	 .key = XATTR_TEST_KEY,
90 	 .value = NULL,
91 	 .size = BUFFSIZE - 1,
92 	 .exp_err = 0,
93 	 },
94 };
95 
96 int TST_TOTAL = sizeof(tc) / sizeof(tc[0]) + 1;
97 
main(int argc,char * argv[])98 int main(int argc, char *argv[])
99 {
100 	int lc;
101 	int i;
102 
103 	tst_parse_opts(argc, argv, NULL, NULL);
104 
105 	setup();
106 
107 	for (lc = 0; TEST_LOOPING(lc); lc++) {
108 		tst_count = 0;
109 
110 		for (i = 0; i < ARRAY_SIZE(tc); i++) {
111 			TEST(getxattr(tc[i].fname, tc[i].key, tc[i].value,
112 				      tc[i].size));
113 
114 			if (TEST_ERRNO == tc[i].exp_err) {
115 				tst_resm(TPASS | TTERRNO, "expected behavior");
116 			} else {
117 				tst_resm(TFAIL | TTERRNO, "unexpected behavior"
118 					 "- expected errno %d - Got",
119 					 tc[i].exp_err);
120 			}
121 		}
122 
123 		if (strcmp(tc[i - 1].value, XATTR_TEST_VALUE))
124 			tst_resm(TFAIL, "Wrong value, expect \"%s\" got \"%s\"",
125 				 XATTR_TEST_VALUE, tc[i - 1].value);
126 		else
127 			tst_resm(TPASS, "Got the right value");
128 	}
129 
130 	cleanup();
131 	tst_exit();
132 }
133 
setup(void)134 static void setup(void)
135 {
136 	int fd;
137 	int i;
138 
139 	tst_require_root();
140 
141 	tst_tmpdir();
142 
143 	/* Create test file and setup initial xattr */
144 	snprintf(filename, BUFSIZ, "getxattr01testfile");
145 	fd = creat(filename, 0644);
146 	if (fd == -1)
147 		tst_brkm(TBROK | TERRNO, cleanup, "Create test file(%s) failed",
148 			 filename);
149 	close(fd);
150 	if (setxattr(filename, XATTR_TEST_KEY, XATTR_TEST_VALUE,
151 		     strlen(XATTR_TEST_VALUE), XATTR_CREATE) == -1) {
152 		if (errno == ENOTSUP) {
153 			tst_brkm(TCONF, cleanup, "No xattr support in fs or "
154 				 "mount without user_xattr option");
155 		}
156 	}
157 
158 	/* Prepare test cases */
159 	for (i = 0; i <  ARRAY_SIZE(tc); i++) {
160 		tc[i].value = malloc(BUFFSIZE);
161 		if (tc[i].value == NULL) {
162 			tst_brkm(TBROK | TERRNO, cleanup,
163 				 "Cannot allocate memory");
164 		}
165 	}
166 
167 	TEST_PAUSE;
168 }
169 
cleanup(void)170 static void cleanup(void)
171 {
172 	tst_rmdir();
173 }
174 #else /* HAVE_ATTR_XATTR_H */
main(int argc,char * argv[])175 int main(int argc, char *argv[])
176 {
177 	tst_brkm(TCONF, NULL, "<attr/xattr.h> does not exist.");
178 }
179 #endif
180