Apache HTTPD
dir.c
Go to the documentation of this file.
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 "apr_arch_file_io.h"
18#include "apr_strings.h"
19#include "apr_portable.h"
20#if APR_HAVE_SYS_SYSLIMITS_H
21#include <sys/syslimits.h>
22#endif
23#if APR_HAVE_LIMITS_H
24#include <limits.h>
25#endif
26
27#ifndef NAME_MAX
28#define NAME_MAX 255
29#endif
30
32{
34 if (closedir(dir->dirstruct) == 0) {
35 return APR_SUCCESS;
36 }
37 else {
38 return errno;
39 }
40}
41
42#define PATH_SEPARATOR '/'
43
44/* Remove trailing separators that don't affect the meaning of PATH. */
45static const char *path_canonicalize (const char *path, apr_pool_t *pool)
46{
47 /* At some point this could eliminate redundant components. For
48 * now, it just makes sure there is no trailing slash. */
49 apr_size_t len = strlen (path);
51
52 while ((len > 0) && (path[len - 1] == PATH_SEPARATOR))
53 len--;
54
55 if (len != orig_len)
56 return apr_pstrndup (pool, path, len);
57 else
58 return path;
59}
60
61/* Remove one component off the end of PATH. */
62static char *path_remove_last_component (const char *path, apr_pool_t *pool)
63{
64 const char *newpath = path_canonicalize (path, pool);
65 int i;
66
67 for (i = (strlen(newpath) - 1); i >= 0; i--) {
68 if (path[i] == PATH_SEPARATOR)
69 break;
70 }
71
72 return apr_pstrndup (pool, path, (i < 0) ? 0 : i);
73}
74
77{
79
80 if (!dir) {
81 return errno;
82 }
83
84 (*new) = (apr_dir_t *)apr_palloc(pool, sizeof(apr_dir_t));
85
86 (*new)->pool = pool;
87 (*new)->dirname = apr_pstrdup(pool, dirname);
88 (*new)->dirstruct = dir;
89
90#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) \
91 && !defined(READDIR_IS_THREAD_SAFE)
92 /* On some platforms (e.g., Linux+GNU libc), d_name[] in struct
93 * dirent is declared with enough storage for the name. On other
94 * platforms (e.g., Solaris 8 for Intel), d_name is declared as a
95 * one-byte array. Note: gcc evaluates this at compile time.
96 */
97 (*new)->entry = apr_pcalloc(pool, sizeof(*(*new)->entry) +
98 (sizeof((*new)->entry->d_name) > 1
99 ? 0 : NAME_MAX));
100#else
101 (*new)->entry = NULL;
102#endif
103
104 apr_pool_cleanup_register((*new)->pool, *new, dir_cleanup,
106 return APR_SUCCESS;
107}
108
113
114#ifdef DIRENT_TYPE
116{
117 switch (type) {
118 case DT_REG:
119 return APR_REG;
120 case DT_DIR:
121 return APR_DIR;
122 case DT_LNK:
123 return APR_LNK;
124 case DT_CHR:
125 return APR_CHR;
126 case DT_BLK:
127 return APR_BLK;
128#if defined(DT_FIFO)
129 case DT_FIFO:
130 return APR_PIPE;
131#endif
132#if !defined(BEOS) && defined(DT_SOCK)
133 case DT_SOCK:
134 return APR_SOCK;
135#endif
136 default:
137 return APR_UNKFILE;
138 }
139}
140#endif
141
144{
145 apr_status_t ret = 0;
146#ifdef DIRENT_TYPE
148#endif
149#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) \
150 && !defined(READDIR_IS_THREAD_SAFE)
151#ifdef APR_USE_READDIR64_R
152 struct dirent64 *retent;
153
154 /* If LFS is enabled and readdir64_r is available, readdir64_r is
155 * used in preference to readdir_r. This allows directories to be
156 * read which contain a (64-bit) inode number which doesn't fit
157 * into the 32-bit apr_ino_t, iff the caller doesn't actually care
158 * about the inode number (i.e. wanted & APR_FINFO_INODE == 0).
159 * (such inodes may be seen in some wonky NFS environments)
160 *
161 * Similarly, if the d_off field cannot be reprented in a 32-bit
162 * offset, the libc readdir_r() would barf; using readdir64_r
163 * bypasses that case entirely since APR does not care about
164 * d_off. */
165
167#else
168
169 struct dirent *retent;
170
172#endif
173
174 /* POSIX treats "end of directory" as a non-error case, so ret
175 * will be zero and retent will be set to NULL in that case. */
176 if (!ret && retent == NULL) {
177 ret = APR_ENOENT;
178 }
179
180 /* Solaris is a bit strange, if there are no more entries in the
181 * directory, it returns EINVAL. Since this is against POSIX, we
182 * hack around the problem here. EINVAL is possible from other
183 * readdir implementations, but only if the result buffer is too small.
184 * since we control the size of that buffer, we should never have
185 * that problem.
186 */
187 if (ret == EINVAL) {
188 ret = APR_ENOENT;
189 }
190#else
191 /* We're about to call a non-thread-safe readdir() that may
192 possibly set `errno', and the logic below actually cares about
193 errno after the call. Therefore we need to clear errno first. */
194 errno = 0;
196 if (thedir->entry == NULL) {
197 /* If NULL was returned, this can NEVER be a success. Can it?! */
198 if (errno == APR_SUCCESS) {
199 ret = APR_ENOENT;
200 }
201 else
202 ret = errno;
203 }
204#endif
205
206 /* No valid bit flag to test here - do we want one? */
207 finfo->fname = NULL;
208
209 if (ret) {
210 finfo->valid = 0;
211 return ret;
212 }
213
214#ifdef DIRENT_TYPE
216 if (type != APR_UNKFILE) {
218 }
219#endif
220#ifdef DIRENT_INODE
221 if (thedir->entry->DIRENT_INODE && thedir->entry->DIRENT_INODE != -1) {
222#ifdef APR_USE_READDIR64_R
223 /* If readdir64_r is used, check for the overflow case of trying
224 * to fit a 64-bit integer into a 32-bit integer. */
225 if (sizeof(apr_ino_t) >= sizeof(retent->DIRENT_INODE)
226 || (apr_ino_t)retent->DIRENT_INODE == retent->DIRENT_INODE) {
228 } else {
229 /* Prevent the fallback code below from filling in the
230 * inode if the stat call fails. */
231 retent->DIRENT_INODE = 0;
232 }
233#else
235#endif /* APR_USE_READDIR64_R */
236 }
237#endif /* DIRENT_INODE */
238
240
241 if (wanted)
242 {
243 char fspec[APR_PATH_MAX];
244 char *end;
245
247
248 if (end > fspec && end[-1] != '/' && (end < fspec + APR_PATH_MAX))
249 *end++ = '/';
250
251 apr_cpystrn(end, thedir->entry->d_name,
252 sizeof fspec - (end - fspec));
253
255 /* We passed a stack name that will disappear */
256 finfo->fname = NULL;
257 }
258
259 if (wanted && (ret == APR_SUCCESS || ret == APR_INCOMPLETE)) {
260 wanted &= ~finfo->valid;
261 }
262 else {
263 /* We don't bail because we fail to stat, when we are only -required-
264 * to readdir... but the result will be APR_INCOMPLETE
265 */
266 finfo->pool = thedir->pool;
267 finfo->valid = 0;
268#ifdef DIRENT_TYPE
269 if (type != APR_UNKFILE) {
270 finfo->filetype = type;
271 finfo->valid |= APR_FINFO_TYPE;
272 }
273#endif
274#ifdef DIRENT_INODE
275 if (thedir->entry->DIRENT_INODE && thedir->entry->DIRENT_INODE != -1) {
276 finfo->inode = thedir->entry->DIRENT_INODE;
277 finfo->valid |= APR_FINFO_INODE;
278 }
279#endif
280 }
281
282 finfo->name = apr_pstrdup(thedir->pool, thedir->entry->d_name);
283 finfo->valid |= APR_FINFO_NAME;
284
285 if (wanted)
286 return APR_INCOMPLETE;
287
288 return APR_SUCCESS;
289}
290
296
299{
301
302 if (mkdir(path, mode) == 0) {
303 return APR_SUCCESS;
304 }
305 else {
306 return errno;
307 }
308}
309
312{
314
315 apr_err = apr_dir_make (path, perm, pool); /* Try to make PATH right out */
316
317 if (apr_err == ENOENT) { /* Missing an intermediate dir */
318 char *dir;
319
321 /* If there is no path left, give up. */
322 if (dir[0] == '\0') {
323 return apr_err;
324 }
325
327
328 if (!apr_err)
330 }
331
332 /*
333 * It's OK if PATH exists. Timing issues can lead to the second
334 * apr_dir_make being called on existing dir, therefore this check
335 * has to come last.
336 */
338 return APR_SUCCESS;
339
340 return apr_err;
341}
342
344{
345 if (rmdir(path) == 0) {
346 return APR_SUCCESS;
347 }
348 else {
349 return errno;
350 }
351}
352
354{
355 if (dir == NULL) {
356 return APR_ENODIR;
357 }
358 *thedir = dir->dirstruct;
359 return APR_SUCCESS;
360}
361
364{
365 if ((*dir) == NULL) {
366 (*dir) = (apr_dir_t *)apr_pcalloc(pool, sizeof(apr_dir_t));
367 (*dir)->pool = pool;
368 }
369 (*dir)->dirstruct = thedir;
370 return APR_SUCCESS;
371}
372
373
const char apr_size_t len
Definition ap_regex.h:187
mode_t
Definition aplibtool.c:31
APR Portability Routines.
APR Strings library.
request_rec int int apr_table_t const char * path
#define APR_INCOMPLETE
Definition apr_errno.h:452
#define APR_ENODIR
Definition apr_errno.h:301
#define APR_ENOENT
Definition apr_errno.h:662
#define APR_STATUS_IS_EEXIST(s)
Definition apr_errno.h:1233
apr_dbd_transaction_t int mode
Definition apr_dbd.h:261
apr_size_t size
const char int apr_pool_t * pool
Definition apr_cstr.h:84
const char * dirname
apr_int32_t apr_dir_t * thedir
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
apr_int32_t apr_fileperms_t
apr_filetype_e
@ APR_BLK
@ APR_PIPE
@ APR_LNK
@ APR_UNKFILE
@ APR_REG
@ APR_CHR
@ APR_SOCK
@ APR_DIR
int type
const char apr_int32_t apr_fileperms_t perm
const char apr_int32_t wanted
#define APR_FINFO_INODE
#define APR_FINFO_NAME
#define APR_FINFO_LINK
#define APR_FINFO_TYPE
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
DIR apr_os_dir_t
apr_dir_t * dir
const char char ** end
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
static apr_status_t dir_cleanup(void *thedir)
Definition dir.c:24
struct dirent * entry
apr_pool_t * pool
apr_filetype_e filetype
const char * name
apr_pool_t * pool
apr_ino_t inode
const char * fname
apr_int32_t valid
static char * path_remove_last_component(const char *path, apr_pool_t *pool)
Definition dir.c:62
#define PATH_SEPARATOR
Definition dir.c:42
apr_status_t apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted, apr_dir_t *thedir)
Definition dir.c:142
apr_status_t apr_dir_make(const char *path, apr_fileperms_t perm, apr_pool_t *pool)
Definition dir.c:297
apr_status_t apr_dir_remove(const char *path, apr_pool_t *pool)
Definition dir.c:343
apr_status_t apr_dir_close(apr_dir_t *thedir)
Definition dir.c:109
apr_status_t apr_dir_open(apr_dir_t **new, const char *dirname, apr_pool_t *pool)
Definition dir.c:75
apr_status_t apr_dir_make_recursive(const char *path, apr_fileperms_t perm, apr_pool_t *pool)
Definition dir.c:310
static const char * path_canonicalize(const char *path, apr_pool_t *pool)
Definition dir.c:45
apr_status_t apr_os_dir_get(apr_os_dir_t **thedir, apr_dir_t *dir)
Definition dir.c:353
apr_status_t apr_dir_rewind(apr_dir_t *thedir)
Definition dir.c:291
#define NAME_MAX
Definition dir.c:28
apr_status_t apr_os_dir_put(apr_dir_t **dir, apr_os_dir_t *thedir, apr_pool_t *pool)
Definition dir.c:362
mode_t apr_unix_perms2mode(apr_fileperms_t perms)
Definition fileacc.c:35