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_file_io.h" 19#include "apr_lib.h" 20#include "apr_strings.h" 21#include "apr_portable.h" 22#include <string.h> 23 24static apr_status_t dir_cleanup(void *thedir) 25{ 26 apr_dir_t *dir = thedir; 27 return apr_dir_close(dir); 28} 29 30 31 32APR_DECLARE(apr_status_t) apr_dir_open(apr_dir_t **new, const char *dirname, apr_pool_t *pool) 33{ 34 apr_dir_t *thedir = (apr_dir_t *)apr_palloc(pool, sizeof(apr_dir_t)); 35 36 if (thedir == NULL) 37 return APR_ENOMEM; 38 39 thedir->pool = pool; 40 thedir->dirname = apr_pstrdup(pool, dirname); 41 42 if (thedir->dirname == NULL) 43 return APR_ENOMEM; 44 45 thedir->handle = 0; 46 thedir->validentry = FALSE; 47 *new = thedir; 48 apr_pool_cleanup_register(pool, thedir, dir_cleanup, apr_pool_cleanup_null); 49 return APR_SUCCESS; 50} 51 52 53 54APR_DECLARE(apr_status_t) apr_dir_close(apr_dir_t *thedir) 55{ 56 int rv = 0; 57 58 if (thedir->handle) { 59 rv = DosFindClose(thedir->handle); 60 61 if (rv == 0) { 62 thedir->handle = 0; 63 } 64 } 65 66 return APR_FROM_OS_ERROR(rv); 67} 68 69 70 71APR_DECLARE(apr_status_t) apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted, 72 apr_dir_t *thedir) 73{ 74 int rv; 75 ULONG entries = 1; 76 77 if (thedir->handle == 0) { 78 thedir->handle = HDIR_CREATE; 79 rv = DosFindFirst(apr_pstrcat(thedir->pool, thedir->dirname, "/*", NULL), &thedir->handle, 80 FILE_ARCHIVED|FILE_DIRECTORY|FILE_SYSTEM|FILE_HIDDEN|FILE_READONLY, 81 &thedir->entry, sizeof(thedir->entry), &entries, FIL_STANDARD); 82 } else { 83 rv = DosFindNext(thedir->handle, &thedir->entry, sizeof(thedir->entry), &entries); 84 } 85 86 finfo->pool = thedir->pool; 87 finfo->fname = NULL; 88 finfo->valid = 0; 89 90 if (rv == 0 && entries == 1) { 91 thedir->validentry = TRUE; 92 93 /* We passed a name off the stack that has popped */ 94 finfo->fname = NULL; 95 finfo->size = thedir->entry.cbFile; 96 finfo->csize = thedir->entry.cbFileAlloc; 97 98 /* Only directories & regular files show up in directory listings */ 99 finfo->filetype = (thedir->entry.attrFile & FILE_DIRECTORY) ? APR_DIR : APR_REG; 100 101 apr_os2_time_to_apr_time(&finfo->mtime, thedir->entry.fdateLastWrite, 102 thedir->entry.ftimeLastWrite); 103 apr_os2_time_to_apr_time(&finfo->atime, thedir->entry.fdateLastAccess, 104 thedir->entry.ftimeLastAccess); 105 apr_os2_time_to_apr_time(&finfo->ctime, thedir->entry.fdateCreation, 106 thedir->entry.ftimeCreation); 107 108 finfo->name = thedir->entry.achName; 109 finfo->valid = APR_FINFO_NAME | APR_FINFO_MTIME | APR_FINFO_ATIME | 110 APR_FINFO_CTIME | APR_FINFO_TYPE | APR_FINFO_SIZE | 111 APR_FINFO_CSIZE; 112 113 return APR_SUCCESS; 114 } 115 116 thedir->validentry = FALSE; 117 118 if (rv) 119 return APR_FROM_OS_ERROR(rv); 120 121 return APR_ENOENT; 122} 123 124 125 126APR_DECLARE(apr_status_t) apr_dir_rewind(apr_dir_t *thedir) 127{ 128 return apr_dir_close(thedir); 129} 130 131 132 133APR_DECLARE(apr_status_t) apr_dir_make(const char *path, apr_fileperms_t perm, apr_pool_t *pool) 134{ 135 return APR_FROM_OS_ERROR(DosCreateDir(path, NULL)); 136} 137 138 139 140APR_DECLARE(apr_status_t) apr_dir_remove(const char *path, apr_pool_t *pool) 141{ 142 return APR_FROM_OS_ERROR(DosDeleteDir(path)); 143} 144 145 146 147APR_DECLARE(apr_status_t) apr_os_dir_get(apr_os_dir_t **thedir, apr_dir_t *dir) 148{ 149 if (dir == NULL) { 150 return APR_ENODIR; 151 } 152 *thedir = &dir->handle; 153 return APR_SUCCESS; 154} 155 156 157 158APR_DECLARE(apr_status_t) apr_os_dir_put(apr_dir_t **dir, apr_os_dir_t *thedir, 159 apr_pool_t *pool) 160{ 161 if ((*dir) == NULL) { 162 (*dir) = (apr_dir_t *)apr_pcalloc(pool, sizeof(apr_dir_t)); 163 (*dir)->pool = pool; 164 } 165 (*dir)->handle = *thedir; 166 return APR_SUCCESS; 167} 168