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 setxattr(2) and make sure setxattr(2) handles error 27 * conditions correctly. 28 * 29 * There are 7 test cases: 30 * 1. Any other flags being set except XATTR_CREATE and XATTR_REPLACE, 31 * setxattr(2) should return -1 and set errno to EINVAL 32 * 2. With XATTR_REPLACE flag set but the attribute does not exist, 33 * setxattr(2) should return -1 and set errno to ENOATTR 34 * 3. Create new attr with name length greater than XATTR_NAME_MAX(255) 35 * setxattr(2) should return -1 and set errno to ERANGE 36 * 4. Create new attr whose value length is greater than XATTR_SIZE_MAX(65536) 37 * setxattr(2) should return -1 and set errno to E2BIG 38 * 5. Create new attr whose value length is zero, 39 * setxattr(2) should succeed 40 * 6. Replace the attr value without XATTR_REPLACE flag being set, 41 * setxattr(2) should return -1 and set errno to EEXIST 42 * 7. Replace attr value with XATTR_REPLACE flag being set, 43 * setxattr(2) should succeed 44 */ 45 46 #include "config.h" 47 #include <sys/types.h> 48 #include <sys/stat.h> 49 #include <sys/wait.h> 50 #include <errno.h> 51 #include <fcntl.h> 52 #include <unistd.h> 53 #include <signal.h> 54 #include <stdio.h> 55 #include <stdlib.h> 56 #include <string.h> 57 #ifdef HAVE_ATTR_XATTR_H 58 #include <attr/xattr.h> 59 #endif 60 #include "test.h" 61 62 char *TCID = "setxattr01"; 63 64 #ifdef HAVE_ATTR_XATTR_H 65 #define XATTR_NAME_MAX 255 66 #define XATTR_NAME_LEN (XATTR_NAME_MAX + 2) 67 #define XATTR_SIZE_MAX 65536 68 #define XATTR_TEST_KEY "user.testkey" 69 #define XATTR_TEST_VALUE "this is a test value" 70 #define XATTR_TEST_VALUE_SIZE 20 71 72 static void setup(void); 73 static void cleanup(void); 74 75 char filename[BUFSIZ]; 76 char long_key[XATTR_NAME_LEN]; 77 char *long_value; 78 79 struct test_case { 80 char *fname; 81 char *key; 82 char *value; 83 size_t size; 84 int flags; 85 int exp_err; 86 }; 87 struct test_case tc[] = { 88 { /* case 00, invalid flags */ 89 .fname = filename, 90 .key = XATTR_TEST_KEY, 91 .value = XATTR_TEST_VALUE, 92 .size = XATTR_TEST_VALUE_SIZE, 93 .flags = ~0, 94 .exp_err = EINVAL, 95 }, 96 { /* case 01, replace non-existing attribute */ 97 .fname = filename, 98 .key = XATTR_TEST_KEY, 99 .value = XATTR_TEST_VALUE, 100 .size = XATTR_TEST_VALUE_SIZE, 101 .flags = XATTR_REPLACE, 102 .exp_err = ENOATTR, 103 }, 104 { /* case 02, long key name, key will be set in setup() */ 105 .fname = filename, 106 .key = NULL, 107 .value = XATTR_TEST_VALUE, 108 .size = XATTR_TEST_VALUE_SIZE, 109 .flags = XATTR_CREATE, 110 .exp_err = ERANGE, 111 }, 112 { /* case 03, long value, value will be set in setup() */ 113 .fname = filename, 114 .key = XATTR_TEST_KEY, 115 .value = NULL, 116 .size = XATTR_SIZE_MAX + 1, 117 .flags = XATTR_CREATE, 118 .exp_err = E2BIG, 119 }, 120 { /* case 04, zero length value */ 121 .fname = filename, 122 .key = XATTR_TEST_KEY, 123 .value = XATTR_TEST_VALUE, 124 .size = 0, 125 .flags = XATTR_CREATE, 126 .exp_err = 0, 127 }, 128 { /* case 05, create existing attribute */ 129 .fname = filename, 130 .key = XATTR_TEST_KEY, 131 .value = XATTR_TEST_VALUE, 132 .size = XATTR_TEST_VALUE_SIZE, 133 .flags = XATTR_CREATE, 134 .exp_err = EEXIST, 135 }, 136 { /* case 06, replace existing attribute */ 137 .fname = filename, 138 .key = XATTR_TEST_KEY, 139 .value = XATTR_TEST_VALUE, 140 .size = XATTR_TEST_VALUE_SIZE, 141 .flags = XATTR_REPLACE, 142 .exp_err = 0, 143 }, 144 }; 145 146 int TST_TOTAL = sizeof(tc) / sizeof(tc[0]); 147 148 int main(int argc, char *argv[]) 149 { 150 int lc; 151 int i; 152 153 tst_parse_opts(argc, argv, NULL, NULL); 154 155 setup(); 156 157 for (lc = 0; TEST_LOOPING(lc); lc++) { 158 tst_count = 0; 159 160 for (i = 0; i < TST_TOTAL; i++) { 161 TEST(setxattr(tc[i].fname, tc[i].key, tc[i].value, 162 tc[i].size, tc[i].flags)); 163 164 if (TEST_ERRNO == tc[i].exp_err) { 165 tst_resm(TPASS | TTERRNO, "expected behavior"); 166 } else { 167 tst_resm(TFAIL | TTERRNO, "unexpected behavior " 168 "- expected errno %d - Got", 169 tc[i].exp_err); 170 } 171 } 172 } 173 174 cleanup(); 175 tst_exit(); 176 } 177 178 static void setup(void) 179 { 180 int fd; 181 182 tst_require_root(); 183 184 tst_tmpdir(); 185 186 /* Test for xattr support */ 187 fd = creat("testfile", 0644); 188 if (fd == -1) 189 tst_brkm(TBROK | TERRNO, cleanup, "Create testfile failed"); 190 close(fd); 191 if (setxattr("testfile", "user.test", "test", 4, XATTR_CREATE) == -1) 192 if (errno == ENOTSUP) 193 tst_brkm(TCONF, cleanup, "No xattr support in fs or " 194 "mount without user_xattr option"); 195 196 /* Create test file */ 197 snprintf(filename, BUFSIZ, "setxattr01testfile"); 198 fd = creat(filename, 0644); 199 if (fd == -1) 200 tst_brkm(TBROK | TERRNO, cleanup, "Create test file(%s) failed", 201 filename); 202 close(fd); 203 204 /* Prepare test cases */ 205 snprintf(long_key, 6, "%s", "user."); 206 memset(long_key + 5, 'k', XATTR_NAME_LEN - 5); 207 long_key[XATTR_NAME_LEN - 1] = '\0'; 208 tc[2].key = long_key; 209 210 long_value = malloc(XATTR_SIZE_MAX + 2); 211 if (!long_value) 212 tst_brkm(TBROK | TERRNO, cleanup, "malloc failed"); 213 memset(long_value, 'v', XATTR_SIZE_MAX + 2); 214 long_value[XATTR_SIZE_MAX + 1] = '\0'; 215 tc[3].value = long_value; 216 217 TEST_PAUSE; 218 } 219 220 static void cleanup(void) 221 { 222 tst_rmdir(); 223 } 224 #else /* HAVE_ATTR_XATTR_H */ 225 int main(int argc, char *argv[]) 226 { 227 tst_brkm(TCONF, NULL, "<attr/xattr.h> does not exist."); 228 } 229 #endif 230