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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "apr_arch_file_io.h"
18 #include "apr_file_io.h"
19 #include "apr_general.h"
20 #include "apr_strings.h"
21 #include "apr_errno.h"
27 static apr_filetype_e filetype_from_mode(mode_t mode)
31 switch (mode & S_IFMT) {
33 type = APR_REG; break;
35 type = APR_DIR; break;
37 type = APR_LNK; break;
39 type = APR_CHR; break;
41 type = APR_BLK; break;
44 type = APR_PIPE; break;
46 #if !defined(BEOS) && defined(S_IFSOCK)
48 type = APR_SOCK; break;
52 /* Work around missing S_IFxxx values above
55 #if !defined(S_IFFIFO) && defined(S_ISFIFO)
60 #if !defined(BEOS) && !defined(S_IFSOCK) && defined(S_ISSOCK)
70 static void fill_out_finfo(apr_finfo_t *finfo, struct stat *info,
73 finfo->valid = APR_FINFO_MIN | APR_FINFO_IDENT | APR_FINFO_NLINK
74 | APR_FINFO_OWNER | APR_FINFO_PROT;
75 finfo->protection = apr_unix_mode2perms(info->st_mode);
76 finfo->filetype = filetype_from_mode(info->st_mode);
77 finfo->user = info->st_uid;
78 finfo->group = info->st_gid;
79 finfo->size = info->st_size;
80 finfo->inode = info->st_ino;
81 finfo->device = info->st_dev;
82 finfo->nlink = info->st_nlink;
83 apr_time_ansi_put(&finfo->atime, info->st_atime);
84 apr_time_ansi_put(&finfo->mtime, info->st_mtime);
85 apr_time_ansi_put(&finfo->ctime, info->st_ctime);
86 /* ### needs to be revisited
87 * if (wanted & APR_FINFO_CSIZE) {
88 * finfo->csize = info->st_blocks * 512;
89 * finfo->valid |= APR_FINFO_CSIZE;
94 apr_status_t apr_file_info_get_locked(apr_finfo_t *finfo, apr_int32_t wanted,
99 if (thefile->buffered) {
100 apr_status_t rv = apr_file_flush_locked(thefile);
101 if (rv != APR_SUCCESS)
105 if (fstat(thefile->filedes, &info) == 0) {
106 finfo->pool = thefile->pool;
107 finfo->fname = thefile->fname;
108 fill_out_finfo(finfo, &info, wanted);
109 return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
116 APR_DECLARE(apr_status_t) apr_file_info_get(apr_finfo_t *finfo,
122 if (thefile->buffered) {
123 apr_status_t rv = apr_file_flush(thefile);
124 if (rv != APR_SUCCESS)
128 if (fstat(thefile->filedes, &info) == 0) {
129 finfo->pool = thefile->pool;
130 finfo->fname = thefile->fname;
131 fill_out_finfo(finfo, &info, wanted);
132 return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
139 APR_DECLARE(apr_status_t) apr_file_perms_set(const char *fname,
140 apr_fileperms_t perms)
142 mode_t mode = apr_unix_perms2mode(perms);
144 if (chmod(fname, mode) == -1)
149 APR_DECLARE(apr_status_t) apr_file_attrs_set(const char *fname,
150 apr_fileattrs_t attributes,
151 apr_fileattrs_t attr_mask,
157 /* Don't do anything if we can't handle the requested attributes */
158 if (!(attr_mask & (APR_FILE_ATTR_READONLY
159 | APR_FILE_ATTR_EXECUTABLE)))
162 status = apr_stat(&finfo, fname, APR_FINFO_PROT, pool);
163 if (!APR_STATUS_IS_SUCCESS(status))
166 /* ### TODO: should added bits be umask'd? */
167 if (attr_mask & APR_FILE_ATTR_READONLY)
169 if (attributes & APR_FILE_ATTR_READONLY)
171 finfo.protection &= ~APR_UWRITE;
172 finfo.protection &= ~APR_GWRITE;
173 finfo.protection &= ~APR_WWRITE;
177 /* ### umask this! */
178 finfo.protection |= APR_UWRITE;
179 finfo.protection |= APR_GWRITE;
180 finfo.protection |= APR_WWRITE;
184 if (attr_mask & APR_FILE_ATTR_EXECUTABLE)
186 if (attributes & APR_FILE_ATTR_EXECUTABLE)
188 /* ### umask this! */
189 finfo.protection |= APR_UEXECUTE;
190 finfo.protection |= APR_GEXECUTE;
191 finfo.protection |= APR_WEXECUTE;
195 finfo.protection &= ~APR_UEXECUTE;
196 finfo.protection &= ~APR_GEXECUTE;
197 finfo.protection &= ~APR_WEXECUTE;
201 return apr_file_perms_set(fname, finfo.protection);
205 APR_DECLARE(apr_status_t) apr_file_mtime_set(const char *fname,
212 status = apr_stat(&finfo, fname, APR_FINFO_ATIME, pool);
213 if (!APR_STATUS_IS_SUCCESS(status)) {
219 struct timeval tvp[2];
221 tvp[0].tv_sec = apr_time_sec(finfo.atime);
222 tvp[0].tv_usec = apr_time_usec(finfo.atime);
223 tvp[1].tv_sec = apr_time_sec(mtime);
224 tvp[1].tv_usec = apr_time_usec(mtime);
226 if (utimes(fname, tvp) == -1) {
230 #elif defined(HAVE_UTIME)
234 buf.actime = (time_t) (finfo.atime / APR_USEC_PER_SEC);
235 buf.modtime = (time_t) (mtime / APR_USEC_PER_SEC);
237 if (utime(fname, &buf) == -1) {
249 APR_DECLARE(apr_status_t) apr_stat(apr_finfo_t *finfo,
251 apr_int32_t wanted, apr_pool_t *pool)
256 if (wanted & APR_FINFO_LINK)
257 srv = lstat(fname, &info);
259 srv = stat(fname, &info);
263 finfo->fname = fname;
264 fill_out_finfo(finfo, &info, wanted);
265 if (wanted & APR_FINFO_LINK)
266 wanted &= ~APR_FINFO_LINK;
267 return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
270 #if !defined(ENOENT) || !defined(ENOTDIR)
271 #error ENOENT || ENOTDIR not defined; please see the
272 #error comments at this line in the source for a workaround.
274 * If ENOENT || ENOTDIR is not defined in one of the your OS's
275 * include files, APR cannot report a good reason why the stat()
276 * of the file failed; there are cases where it can fail even though
277 * the file exists. This opens holes in Apache, for example, because
278 * it becomes possible for someone to get a directory listing of a
279 * directory even though there is an index (eg. index.html) file in
280 * it. If you do not have a problem with this, delete the above
281 * #error lines and start the compile again. If you need to do this,
282 * please submit a bug report to http://www.apache.org/bug_report.html
283 * letting us know that you needed to do this. Please be sure to
284 * include the operating system you are using.
286 /* WARNING: All errors will be handled as not found
291 /* WARNING: All errors but not found will be handled as not directory
298 #else /* All was defined well, report the usual: */
304 /* Perhaps this becomes nothing but a macro?
306 APR_DECLARE(apr_status_t) apr_lstat(apr_finfo_t *finfo, const char *fname,
307 apr_int32_t wanted, apr_pool_t *pool)
309 return apr_stat(finfo, fname, wanted | APR_FINFO_LINK, pool);