1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) 2018 Linaro Limited. All rights reserved. 4 * Author: Rafael David Tinoco <rafael.tinoco@linaro.org> 5 */ 6 7/* 8 * Basic tests for fgetxattr(2) and make sure fgetxattr(2) handles error 9 * conditions correctly. 10 * 11 * There are 3 test cases: 12 * 1. Get an non-existing attribute: 13 * - fgetxattr(2) should return -1 and set errno to ENODATA 14 * 2. Buffer size is smaller than attribute value size: 15 * - fgetxattr(2) should return -1 and set errno to ERANGE 16 * 3. Get attribute, fgetxattr(2) should succeed: 17 * - verify the attribute got by fgetxattr(2) is same as the value we set 18 */ 19 20#include "config.h" 21#include <sys/types.h> 22#include <sys/stat.h> 23#include <sys/wait.h> 24#include <errno.h> 25#include <fcntl.h> 26#include <unistd.h> 27#include <signal.h> 28#include <stdio.h> 29#include <stdlib.h> 30#include <string.h> 31#ifdef HAVE_SYS_XATTR_H 32# include <sys/xattr.h> 33#endif 34#include "tst_test.h" 35 36#ifdef HAVE_SYS_XATTR_H 37#define XATTR_SIZE_MAX 65536 38#define XATTR_TEST_KEY "user.testkey" 39#define XATTR_TEST_VALUE "this is a test value" 40#define XATTR_TEST_VALUE_SIZE 20 41#define XATTR_TEST_INVALID_KEY "user.nosuchkey" 42#define MNTPOINT "mntpoint" 43#define FNAME MNTPOINT"/fgetxattr01testfile" 44 45static int fd = -1; 46 47struct test_case { 48 char *key; 49 char *value; 50 size_t size; 51 int exp_ret; 52 int exp_err; 53}; 54struct test_case tc[] = { 55 { /* case 00, get non-existing attribute */ 56 .key = XATTR_TEST_INVALID_KEY, 57 .value = NULL, 58 .size = XATTR_SIZE_MAX, 59 .exp_ret = -1, 60 .exp_err = ENODATA, 61 }, 62 { /* case 01, small value buffer */ 63 .key = XATTR_TEST_KEY, 64 .value = NULL, 65 .size = 1, 66 .exp_ret = -1, 67 .exp_err = ERANGE, 68 }, 69 { /* case 02, get existing attribute */ 70 .key = XATTR_TEST_KEY, 71 .value = NULL, 72 .size = XATTR_TEST_VALUE_SIZE, 73 .exp_ret = XATTR_TEST_VALUE_SIZE, 74 .exp_err = 0, 75 }, 76}; 77 78static void verify_fgetxattr(unsigned int i) 79{ 80 TEST(fgetxattr(fd, tc[i].key, tc[i].value, tc[i].size)); 81 82 if (TST_RET == -1 && TST_ERR == EOPNOTSUPP) 83 tst_brk(TCONF, "fgetxattr(2) not supported"); 84 85 if (TST_RET >= 0) { 86 87 if (tc[i].exp_ret == TST_RET) 88 tst_res(TPASS, "fgetxattr(2) passed"); 89 else 90 tst_res(TFAIL, "fgetxattr(2) passed unexpectedly"); 91 92 if (strncmp(tc[i].value, XATTR_TEST_VALUE, 93 XATTR_TEST_VALUE_SIZE)) { 94 tst_res(TFAIL, "wrong value, expect \"%s\" got \"%s\"", 95 XATTR_TEST_VALUE, tc[i].value); 96 } 97 98 tst_res(TPASS, "got the right value"); 99 } 100 101 if (tc[i].exp_err == TST_ERR) { 102 tst_res(TPASS | TTERRNO, "fgetxattr(2) passed"); 103 return; 104 } 105 106 tst_res(TFAIL | TTERRNO, "fgetxattr(2) failed"); 107} 108 109static void setup(void) 110{ 111 size_t i = 0; 112 113 SAFE_TOUCH(FNAME, 0644, NULL); 114 fd = SAFE_OPEN(FNAME, O_RDONLY); 115 116 for (i = 0; i < ARRAY_SIZE(tc); i++) { 117 tc[i].value = SAFE_MALLOC(tc[i].size); 118 memset(tc[i].value, 0, tc[i].size); 119 } 120 121 SAFE_FSETXATTR(fd, XATTR_TEST_KEY, XATTR_TEST_VALUE, 122 XATTR_TEST_VALUE_SIZE, XATTR_CREATE); 123} 124 125static void cleanup(void) 126{ 127 size_t i = 0; 128 129 for (i = 0; i < ARRAY_SIZE(tc); i++) 130 free(tc[i].value); 131 132 if (fd > 0) 133 SAFE_CLOSE(fd); 134} 135 136static struct tst_test test = { 137 .setup = setup, 138 .test = verify_fgetxattr, 139 .cleanup = cleanup, 140 .tcnt = ARRAY_SIZE(tc), 141 .mntpoint = MNTPOINT, 142 .mount_device = 1, 143 .all_filesystems = 1, 144 .needs_root = 1, 145}; 146 147#else /* HAVE_SYS_XATTR_H */ 148TST_TEST_TCONF("<sys/xattr.h> does not exist"); 149#endif 150