Index: test/Makefile.in =================================================================== --- test/Makefile.in (revision 606453) +++ test/Makefile.in (working copy) @@ -28,7 +28,7 @@ testhash.lo testargs.lo testnames.lo testuser.lo testpath.lo \ testenv.lo testprocmutex.lo testfnmatch.lo testatomic.lo testflock.lo \ testsock.lo testglobalmutex.lo teststrnatcmp.lo testfilecopy.lo \ - testtemp.lo testlfs.lo testcond.lo + testtemp.lo testlfs.lo testcond.lo testxattr.lo OTHER_PROGRAMS = \ sendfile@EXEEXT@ \ Index: test/testxattr.c =================================================================== --- test/testxattr.c (revision 0) +++ test/testxattr.c (revision 0) @@ -0,0 +1,499 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_file_io.h" +#include "apr_file_xattr.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "testutil.h" + +#if APR_HAS_XATTR + +#define DIRNAME "data" +#define FNAME DIRNAME "/file_xattrfile.txt" +#define DNAME DIRNAME "/dir_xattrdir" + +#define TESTKEY1 "testkey1" +#define TESTVAL1 "testval1" +#define TESTKEY2 "testkey2" +#define TESTVAL2 "testval2" + +/* test solaris subfilename escaping */ +#define TESTKEYSPECIAL1 "/testkey2" +#define TESTKEYSPECIAL2 "%testkey2" + +static void test_xattr_file_set(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_xattr_t *xattr; + apr_file_t *filetest = NULL; + + rv = apr_file_open(&filetest, FNAME, + APR_WRITE | APR_CREATE | APR_DELONCLOSE, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_open_path(&xattr, FNAME, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_set(xattr, TESTKEY1, TESTVAL1, strlen(TESTVAL1), 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + apr_xattr_destroy(xattr); + apr_file_close(filetest); +} + +static void test_xattr_file_set_create(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_xattr_t *xattr; + apr_file_t *filetest = NULL; + + rv = apr_file_open(&filetest, FNAME, + APR_WRITE | APR_CREATE | APR_DELONCLOSE, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_open_path(&xattr, FNAME, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_set(xattr, TESTKEY1, TESTVAL1, strlen(TESTVAL1), + APR_XATTR_CREATE); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_set(xattr, TESTKEY1, TESTVAL1, strlen(TESTVAL1), + APR_XATTR_CREATE); + ABTS_TRUE(tc, APR_STATUS_IS_EEXIST(rv)); + + apr_xattr_destroy(xattr); + apr_file_close(filetest); +} + +static void test_xattr_file_set_replace(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_xattr_t *xattr; + apr_file_t *filetest = NULL; + + rv = apr_file_open(&filetest, FNAME, + APR_WRITE | APR_CREATE | APR_DELONCLOSE, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_open_path(&xattr, FNAME, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_set(xattr, TESTKEY1, TESTVAL1, strlen(TESTVAL1), + APR_XATTR_REPLACE); + ABTS_TRUE(tc, APR_STATUS_IS_ENOATTR(rv)); + + rv = apr_xattr_set(xattr, TESTKEY1, TESTVAL1, strlen(TESTVAL1), + APR_XATTR_CREATE); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_set(xattr, TESTKEY1, TESTVAL1, strlen(TESTVAL1), + APR_XATTR_REPLACE); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + apr_xattr_destroy(xattr); + apr_file_close(filetest); +} + +static void test_xattr_file_get(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_xattr_t *xattr; + apr_file_t *filetest = NULL; + apr_size_t size; + char *val = NULL; + + rv = apr_file_open(&filetest, FNAME, + APR_WRITE | APR_CREATE | APR_DELONCLOSE, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_open_path(&xattr, FNAME, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_set(xattr, TESTKEY1, TESTVAL1, strlen(TESTVAL1), 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_get(xattr, TESTKEY1, (void**)&val, &size, 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, strlen(TESTVAL1), size); + ABTS_PTR_NOTNULL(tc, val); + ABTS_TRUE(tc, strncmp(TESTVAL1, val, strlen(TESTVAL1)) == 0); + + apr_xattr_destroy(xattr); + apr_file_close(filetest); +} + +static void test_xattr_file_get_enoattr(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_xattr_t *xattr; + apr_file_t *filetest = NULL; + apr_size_t size; + char *val = NULL; + + rv = apr_file_open(&filetest, FNAME, + APR_WRITE | APR_CREATE | APR_DELONCLOSE, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_open_path(&xattr, FNAME, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_get(xattr, TESTKEY1, (void**)&val, &size, 0); + ABTS_TRUE(tc, APR_STATUS_IS_ENOATTR(rv)); + + apr_xattr_destroy(xattr); + apr_file_close(filetest); +} + +static void test_xattr_file_exists(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_xattr_t *xattr; + apr_file_t *filetest = NULL; + apr_size_t size; + int exists; + + rv = apr_file_open(&filetest, FNAME, + APR_WRITE | APR_CREATE | APR_DELONCLOSE, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_open_path(&xattr, FNAME, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_exists(xattr, TESTKEY1, &exists, 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_TRUE(tc, !exists); + + rv = apr_xattr_set(xattr, TESTKEY1, TESTVAL1, strlen(TESTVAL1), 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_exists(xattr, TESTKEY1, &exists, 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_TRUE(tc, exists); + + apr_xattr_destroy(xattr); + apr_file_close(filetest); +} + +static void test_xattr_file_list(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_xattr_t *xattr; + apr_file_t *filetest = NULL; + apr_array_header_t *list = NULL; + int cmp1, cmp2; + + rv = apr_file_open(&filetest, FNAME, + APR_WRITE | APR_CREATE | APR_DELONCLOSE, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_open_path(&xattr, FNAME, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_set(xattr, TESTKEY1, TESTVAL1, strlen(TESTVAL1), 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_xattr_set(xattr, TESTKEY2, TESTVAL2, strlen(TESTVAL2), 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_list(xattr, &list, 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, list); + ABTS_INT_EQUAL(tc, 2, list->nelts); + cmp1 = (strcmp(APR_ARRAY_IDX(list, 0, char*), TESTKEY1) == 0) && + (strcmp(APR_ARRAY_IDX(list, 1, char*), TESTKEY2) == 0); + cmp2 = (strcmp(APR_ARRAY_IDX(list, 0, char*), TESTKEY2) == 0) && + (strcmp(APR_ARRAY_IDX(list, 1, char*), TESTKEY1) == 0); + ABTS_TRUE(tc, cmp1 || cmp2 ); + + apr_xattr_destroy(xattr); + apr_file_close(filetest); +} + +static void test_xattr_file_remove(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_xattr_t *xattr; + apr_file_t *filetest = NULL; + apr_size_t size; + char *val = NULL; + + rv = apr_file_open(&filetest, FNAME, + APR_WRITE | APR_CREATE | APR_DELONCLOSE, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_open_path(&xattr, FNAME, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_set(xattr, TESTKEY1, TESTVAL1, strlen(TESTVAL1), 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_remove(xattr, TESTKEY1, 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_get(xattr, TESTKEY1, (void**)&val, &size, 0); + ABTS_INT_NEQUAL(tc, APR_SUCCESS, rv); + + apr_xattr_destroy(xattr); + apr_file_close(filetest); +} + +static void test_xattr_file_remove_enoattr(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_xattr_t *xattr; + apr_file_t *filetest = NULL; + apr_size_t size; + char *val = NULL; + + rv = apr_file_open(&filetest, FNAME, + APR_WRITE | APR_CREATE | APR_DELONCLOSE, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_open_path(&xattr, FNAME, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_remove(xattr, TESTKEY1, 0); + ABTS_TRUE(tc, APR_STATUS_IS_ENOATTR(rv)); + + apr_xattr_destroy(xattr); + apr_file_close(filetest); +} + +static void test_xattr_dir_set(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_xattr_t *xattr; + + rv = apr_dir_make(DNAME, APR_OS_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_open_path(&xattr, DNAME, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_set(xattr, TESTKEY1, TESTVAL1, strlen(TESTVAL1), 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + apr_xattr_destroy(xattr); + apr_dir_remove(DNAME, p); +} + +static void test_xattr_dir_get(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_xattr_t *xattr; + apr_size_t size; + char *val = NULL; + + rv = apr_dir_make(DNAME, APR_OS_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_open_path(&xattr, DNAME, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_set(xattr, TESTKEY1, TESTVAL1, strlen(TESTVAL1), 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_get(xattr, TESTKEY1, (void**)&val, &size, 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, strlen(TESTVAL1), size); + ABTS_PTR_NOTNULL(tc, val); + ABTS_TRUE(tc, strncmp(TESTVAL1, val, strlen(TESTVAL1)) == 0); + + apr_xattr_destroy(xattr); + apr_dir_remove(DNAME, p); +} + +static void test_xattr_dir_exists(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_xattr_t *xattr; + apr_file_t *filetest = NULL; + apr_size_t size; + int exists; + + rv = apr_dir_make(DNAME, APR_OS_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_open_path(&xattr, DNAME, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_exists(xattr, TESTKEY1, &exists, 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_TRUE(tc, !exists); + + rv = apr_xattr_set(xattr, TESTKEY1, TESTVAL1, strlen(TESTVAL1), 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_exists(xattr, TESTKEY1, &exists, 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_TRUE(tc, exists); + + apr_xattr_destroy(xattr); + apr_dir_remove(DNAME, p); +} + +static void test_xattr_dir_list(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_xattr_t *xattr; + apr_array_header_t *list = NULL; + int cmp1, cmp2; + + rv = apr_dir_make(DNAME, APR_OS_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_open_path(&xattr, DNAME, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_set(xattr, TESTKEY1, TESTVAL1, strlen(TESTVAL1), 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_xattr_set(xattr, TESTKEY2, TESTVAL2, strlen(TESTVAL2), 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_list(xattr, &list, 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, list); + ABTS_INT_EQUAL(tc, 2, list->nelts); + cmp1 = (strcmp(APR_ARRAY_IDX(list, 0, char*), TESTKEY1) == 0) && + (strcmp(APR_ARRAY_IDX(list, 1, char*), TESTKEY2) == 0); + cmp2 = (strcmp(APR_ARRAY_IDX(list, 0, char*), TESTKEY2) == 0) && + (strcmp(APR_ARRAY_IDX(list, 1, char*), TESTKEY1) == 0); + ABTS_TRUE(tc, cmp1 || cmp2 ); + + apr_xattr_destroy(xattr); + apr_dir_remove(DNAME, p); +} + +static void test_xattr_dir_remove(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_xattr_t *xattr; + apr_size_t size; + char *val = NULL; + + rv = apr_dir_make(DNAME, APR_OS_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_open_path(&xattr, DNAME, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_set(xattr, TESTKEY1, TESTVAL1, strlen(TESTVAL1), 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_remove(xattr, TESTKEY1, 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_get(xattr, TESTKEY1, (void**)&val, &size, 0); + ABTS_INT_NEQUAL(tc, APR_SUCCESS, rv); + + apr_xattr_destroy(xattr); + apr_dir_remove(DNAME, p); +} + +static void test_xattr_open_path_enoent(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_xattr_t *xattr; + + rv = apr_xattr_open_path(&xattr, FNAME, p); + ABTS_TRUE(tc, APR_STATUS_IS_ENOENT(rv)); +} + +static void test_xattr_file_special_chars(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_xattr_t *xattr; + apr_file_t *filetest = NULL; + apr_size_t size; + const char *name = (const char*)data; + char *val = NULL; + apr_array_header_t *list = NULL; + int cmp1, cmp2; + + rv = apr_file_open(&filetest, FNAME, + APR_WRITE | APR_CREATE | APR_DELONCLOSE, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_open_path(&xattr, FNAME, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_set(xattr, name, TESTVAL1, strlen(TESTVAL1), 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_xattr_get(xattr, name, (void**)&val, &size, 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, strlen(TESTVAL1), size); + ABTS_PTR_NOTNULL(tc, val); + ABTS_TRUE(tc, strncmp(TESTVAL1, val, strlen(TESTVAL1)) == 0); + + rv = apr_xattr_list(xattr, &list, 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, list); + ABTS_INT_EQUAL(tc, 1, list->nelts); + ABTS_TRUE(tc, strcmp(name, APR_ARRAY_IDX(list, 0, char*)) == 0); + + apr_xattr_destroy(xattr); + apr_file_close(filetest); +} + +#else + +static void test_xattr_not_impl(abts_case *tc, void *data) +{ + ABTS_NOT_IMPL(tc, "xattr not implemented on this platform"); +} + +#endif /* APR_HAS_XATTR */ + +abts_suite *testxattr(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + +#if !APR_HAS_XATTR + abts_run_test(suite, test_xattr_not_impl, NULL); +#else + abts_run_test(suite, test_xattr_file_set, NULL); + abts_run_test(suite, test_xattr_file_set_create, NULL); + abts_run_test(suite, test_xattr_file_set_replace, NULL); + abts_run_test(suite, test_xattr_file_get, NULL); + abts_run_test(suite, test_xattr_file_get_enoattr, NULL); + abts_run_test(suite, test_xattr_file_exists, NULL); + abts_run_test(suite, test_xattr_file_list, NULL); + abts_run_test(suite, test_xattr_file_remove, NULL); + abts_run_test(suite, test_xattr_file_remove_enoattr, NULL); + abts_run_test(suite, test_xattr_dir_set, NULL); + abts_run_test(suite, test_xattr_dir_get, NULL); + abts_run_test(suite, test_xattr_dir_exists, NULL); + abts_run_test(suite, test_xattr_dir_list, NULL); + abts_run_test(suite, test_xattr_dir_remove, NULL); + abts_run_test(suite, test_xattr_open_path_enoent, NULL); + abts_run_test(suite, test_xattr_file_special_chars, TESTKEYSPECIAL1); + abts_run_test(suite, test_xattr_file_special_chars, TESTKEYSPECIAL2); +#endif + + return suite; +} Index: test/abts_tests.h =================================================================== --- test/abts_tests.h (revision 606453) +++ test/abts_tests.h (working copy) @@ -66,7 +66,8 @@ {testtime}, {testud}, {testuser}, - {testvsn} + {testvsn}, + {testxattr} }; #endif /* APR_TEST_INCLUDES */ Index: test/testutil.h =================================================================== --- test/testutil.h (revision 606453) +++ test/testutil.h (working copy) @@ -102,5 +102,6 @@ abts_suite *testud(abts_suite *suite); abts_suite *testuser(abts_suite *suite); abts_suite *testvsn(abts_suite *suite); +abts_suite *testxattr(abts_suite *suite); #endif /* APR_TEST_INCLUDES */