1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdio.h> 18#include <stdlib.h> 19#include <string.h> 20#include "apr_file_io.h" 21#include "apr_file_info.h" 22#include "apr_errno.h" 23#include "apr_general.h" 24#include "apr_lib.h" 25#include "testutil.h" 26 27static void test_mkdir(abts_case *tc, void *data) 28{ 29 apr_status_t rv; 30 apr_finfo_t finfo; 31 32 rv = apr_dir_make("data/testdir", APR_UREAD | APR_UWRITE | APR_UEXECUTE, p); 33 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 34 35 rv = apr_stat(&finfo, "data/testdir", APR_FINFO_TYPE, p); 36 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 37 ABTS_INT_EQUAL(tc, APR_DIR, finfo.filetype); 38} 39 40static void test_mkdir_recurs(abts_case *tc, void *data) 41{ 42 apr_status_t rv; 43 apr_finfo_t finfo; 44 45 rv = apr_dir_make_recursive("data/one/two/three", 46 APR_UREAD | APR_UWRITE | APR_UEXECUTE, p); 47 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 48 49 rv = apr_stat(&finfo, "data/one", APR_FINFO_TYPE, p); 50 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 51 ABTS_INT_EQUAL(tc, APR_DIR, finfo.filetype); 52 53 rv = apr_stat(&finfo, "data/one/two", APR_FINFO_TYPE, p); 54 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 55 ABTS_INT_EQUAL(tc, APR_DIR, finfo.filetype); 56 57 rv = apr_stat(&finfo, "data/one/two/three", APR_FINFO_TYPE, p); 58 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 59 ABTS_INT_EQUAL(tc, APR_DIR, finfo.filetype); 60} 61 62static void test_remove(abts_case *tc, void *data) 63{ 64 apr_status_t rv; 65 apr_finfo_t finfo; 66 67 rv = apr_dir_remove("data/testdir", p); 68 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 69 70 rv = apr_stat(&finfo, "data/testdir", APR_FINFO_TYPE, p); 71 ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv)); 72} 73 74static void test_removeall_fail(abts_case *tc, void *data) 75{ 76 apr_status_t rv; 77 78 rv = apr_dir_remove("data/one", p); 79 ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOTEMPTY(rv)); 80} 81 82static void test_removeall(abts_case *tc, void *data) 83{ 84 apr_status_t rv; 85 86 rv = apr_dir_remove("data/one/two/three", p); 87 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 88 89 rv = apr_dir_remove("data/one/two", p); 90 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 91 92 rv = apr_dir_remove("data/one", p); 93 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 94} 95 96static void test_remove_notthere(abts_case *tc, void *data) 97{ 98 apr_status_t rv; 99 100 rv = apr_dir_remove("data/notthere", p); 101 ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv)); 102} 103 104static void test_mkdir_twice(abts_case *tc, void *data) 105{ 106 apr_status_t rv; 107 108 rv = apr_dir_make("data/testdir", APR_UREAD | APR_UWRITE | APR_UEXECUTE, p); 109 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 110 111 rv = apr_dir_make("data/testdir", APR_UREAD | APR_UWRITE | APR_UEXECUTE, p); 112 ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EEXIST(rv)); 113 114 rv = apr_dir_remove("data/testdir", p); 115 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 116} 117 118static void test_opendir(abts_case *tc, void *data) 119{ 120 apr_status_t rv; 121 apr_dir_t *dir; 122 123 rv = apr_dir_open(&dir, "data", p); 124 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 125 apr_dir_close(dir); 126} 127 128static void test_opendir_notthere(abts_case *tc, void *data) 129{ 130 apr_status_t rv; 131 apr_dir_t *dir; 132 133 rv = apr_dir_open(&dir, "notthere", p); 134 ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv)); 135} 136 137static void test_closedir(abts_case *tc, void *data) 138{ 139 apr_status_t rv; 140 apr_dir_t *dir; 141 142 rv = apr_dir_open(&dir, "data", p); 143 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 144 rv = apr_dir_close(dir); 145 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 146} 147 148static void test_rewind(abts_case *tc, void *data) 149{ 150 apr_dir_t *dir; 151 apr_finfo_t first, second; 152 153 APR_ASSERT_SUCCESS(tc, "apr_dir_open failed", apr_dir_open(&dir, "data", p)); 154 155 APR_ASSERT_SUCCESS(tc, "apr_dir_read failed", 156 apr_dir_read(&first, APR_FINFO_DIRENT, dir)); 157 158 APR_ASSERT_SUCCESS(tc, "apr_dir_rewind failed", apr_dir_rewind(dir)); 159 160 APR_ASSERT_SUCCESS(tc, "second apr_dir_read failed", 161 apr_dir_read(&second, APR_FINFO_DIRENT, dir)); 162 163 APR_ASSERT_SUCCESS(tc, "apr_dir_close failed", apr_dir_close(dir)); 164 165 ABTS_STR_EQUAL(tc, first.name, second.name); 166} 167 168/* Test for a (fixed) bug in apr_dir_read(). This bug only happened 169 in threadless cases. */ 170static void test_uncleared_errno(abts_case *tc, void *data) 171{ 172 apr_file_t *thefile = NULL; 173 apr_finfo_t finfo; 174 apr_int32_t finfo_flags = APR_FINFO_TYPE | APR_FINFO_NAME; 175 apr_dir_t *this_dir; 176 apr_status_t rv; 177 178 rv = apr_dir_make("dir1", APR_OS_DEFAULT, p); 179 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 180 rv = apr_dir_make("dir2", APR_OS_DEFAULT, p); 181 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 182 rv = apr_file_open(&thefile, "dir1/file1", 183 APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_CREATE, APR_OS_DEFAULT, p); 184 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 185 rv = apr_file_close(thefile); 186 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 187 188 /* Try to remove dir1. This should fail because it's not empty. 189 However, on a platform with threads disabled (such as FreeBSD), 190 `errno' will be set as a result. */ 191 rv = apr_dir_remove("dir1", p); 192 ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOTEMPTY(rv)); 193 194 /* Read `.' and `..' out of dir2. */ 195 rv = apr_dir_open(&this_dir, "dir2", p); 196 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 197 rv = apr_dir_read(&finfo, finfo_flags, this_dir); 198 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 199 rv = apr_dir_read(&finfo, finfo_flags, this_dir); 200 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 201 202 /* Now, when we attempt to do a third read of empty dir2, and the 203 underlying system readdir() returns NULL, the old value of 204 errno shouldn't cause a false alarm. We should get an ENOENT 205 back from apr_dir_read, and *not* the old errno. */ 206 rv = apr_dir_read(&finfo, finfo_flags, this_dir); 207 ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv)); 208 209 rv = apr_dir_close(this_dir); 210 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 211 212 /* Cleanup */ 213 rv = apr_file_remove("dir1/file1", p); 214 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 215 rv = apr_dir_remove("dir1", p); 216 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 217 rv = apr_dir_remove("dir2", p); 218 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 219 220} 221 222static void test_rmkdir_nocwd(abts_case *tc, void *data) 223{ 224 char *cwd, *path; 225 226 APR_ASSERT_SUCCESS(tc, "make temp dir", 227 apr_dir_make("dir3", APR_OS_DEFAULT, p)); 228 229 APR_ASSERT_SUCCESS(tc, "obtain cwd", apr_filepath_get(&cwd, 0, p)); 230 231 APR_ASSERT_SUCCESS(tc, "determine path to temp dir", 232 apr_filepath_merge(&path, cwd, "dir3", 0, p)); 233 234 APR_ASSERT_SUCCESS(tc, "change to temp dir", apr_filepath_set(path, p)); 235 236 APR_ASSERT_SUCCESS(tc, "restore cwd", apr_filepath_set(cwd, p)); 237 238 APR_ASSERT_SUCCESS(tc, "remove cwd", apr_dir_remove(path, p)); 239} 240 241 242abts_suite *testdir(abts_suite *suite) 243{ 244 suite = ADD_SUITE(suite) 245 246 abts_run_test(suite, test_mkdir, NULL); 247 abts_run_test(suite, test_mkdir_recurs, NULL); 248 abts_run_test(suite, test_remove, NULL); 249 abts_run_test(suite, test_removeall_fail, NULL); 250 abts_run_test(suite, test_removeall, NULL); 251 abts_run_test(suite, test_remove_notthere, NULL); 252 abts_run_test(suite, test_mkdir_twice, NULL); 253 abts_run_test(suite, test_rmkdir_nocwd, NULL); 254 255 abts_run_test(suite, test_rewind, NULL); 256 257 abts_run_test(suite, test_opendir, NULL); 258 abts_run_test(suite, test_opendir_notthere, NULL); 259 abts_run_test(suite, test_closedir, NULL); 260 abts_run_test(suite, test_uncleared_errno, NULL); 261 262 return suite; 263} 264 265