Apache HTTPD
filestat.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 "fsio.h"
19#include "nks/dirio.h"
20#include "apr_file_io.h"
21#include "apr_general.h"
22#include "apr_strings.h"
23#include "apr_errno.h"
24#include "apr_hash.h"
25#include "apr_thread_rwlock.h"
26
27#ifdef HAVE_UTIME_H
28#include <utime.h>
29#endif
30
31#define APR_HAS_PSA
32
34{
36
37 if (S_ISREG(mode))
38 type = APR_REG;
39 else if (S_ISDIR(mode))
40 type = APR_DIR;
41 else if (S_ISCHR(mode))
42 type = APR_CHR;
43 else if (S_ISBLK(mode))
44 type = APR_BLK;
45 else if (S_ISFIFO(mode))
46 type = APR_PIPE;
47 else if (S_ISLNK(mode))
48 type = APR_LNK;
49 else if (S_ISSOCK(mode))
50 type = APR_SOCK;
51 else
53 return type;
54}
55
56static void fill_out_finfo(apr_finfo_t *finfo, struct stat *info,
58{
61
62 finfo->protection = apr_unix_mode2perms(info->st_mode);
63 finfo->filetype = filetype_from_mode(info->st_mode);
64 finfo->user = info->st_uid;
65 finfo->group = info->st_gid;
66 finfo->size = info->st_size;
67 finfo->inode = info->st_ino;
68 finfo->device = info->st_dev;
69 finfo->nlink = info->st_nlink;
70
71 apr_time_ansi_put(&finfo->atime, info->st_atime.tv_sec);
72 apr_time_ansi_put(&finfo->mtime, info->st_mtime.tv_sec);
73 apr_time_ansi_put(&finfo->ctime, info->st_ctime.tv_sec);
74
75#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
76#ifdef DEV_BSIZE
77 finfo->csize = (apr_off_t)info->st_blocks * (apr_off_t)DEV_BSIZE;
78#else
79 finfo->csize = (apr_off_t)info->st_blocks * (apr_off_t)512;
80#endif
81 finfo->valid |= APR_FINFO_CSIZE;
82#endif
83}
84
87{
89
90 if (thefile->buffered) {
92 if (rv != APR_SUCCESS)
93 return rv;
94 }
95
96 if (fstat(thefile->filedes, &info) == 0) {
97 finfo->pool = thefile->pool;
98 finfo->fname = thefile->fname;
99 fill_out_finfo(finfo, &info, wanted);
100 return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
101 }
102 else {
103 return errno;
104 }
105}
106
110{
111 struct stat info;
112
113 if (thefile->buffered) {
114 /* XXX: flush here is not mutex protected */
116 if (rv != APR_SUCCESS)
117 return rv;
118 }
119
120 if (fstat(thefile->filedes, &info) == 0) {
121 finfo->pool = thefile->pool;
122 finfo->fname = thefile->fname;
123 fill_out_finfo(finfo, &info, wanted);
124 return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
125 }
126 else {
127 return errno;
128 }
129}
130
133{
135
136 if (chmod(fname, mode) == -1)
137 return errno;
138 return APR_SUCCESS;
139}
140
145{
147 apr_finfo_t finfo;
148
149 /* Don't do anything if we can't handle the requested attributes */
152 return APR_SUCCESS;
153
155 if (status)
156 return status;
157
158 /* ### TODO: should added bits be umask'd? */
160 {
162 {
163 finfo.protection &= ~APR_UWRITE;
164 finfo.protection &= ~APR_GWRITE;
165 finfo.protection &= ~APR_WWRITE;
166 }
167 else
168 {
169 /* ### umask this! */
170 finfo.protection |= APR_UWRITE;
171 finfo.protection |= APR_GWRITE;
172 finfo.protection |= APR_WWRITE;
173 }
174 }
175
177 {
179 {
180 /* ### umask this! */
181 finfo.protection |= APR_UEXECUTE;
182 finfo.protection |= APR_GEXECUTE;
183 finfo.protection |= APR_WEXECUTE;
184 }
185 else
186 {
187 finfo.protection &= ~APR_UEXECUTE;
188 finfo.protection &= ~APR_GEXECUTE;
189 finfo.protection &= ~APR_WEXECUTE;
190 }
191 }
192
193 return apr_file_perms_set(fname, finfo.protection);
194}
195
196#ifndef APR_HAS_PSA
198{
202 char *key;
205
207 apr_hash_this(hi, (const void**)&key, &keylen, (void**)&pathctx);
208
209 if (pathctx) {
211 }
212 }
213
214 return APR_SUCCESS;
215}
216
217int cstat (NXPathCtx_t ctx, char *path, struct stat *buf, unsigned long requestmap, apr_pool_t *p)
218{
221 apr_thread_rwlock_t *rwlock = NULL;
222
224 char *ptr = NULL, *tr;
225 int len = 0, x;
226 char *ppath;
227 char *pinfo;
228
229 if (ctx == 1) {
230
231 /* If there isn't a global pool then just stat the file
232 and return */
233 if (!gPool) {
234 char poolname[50];
235
237 return getstat(ctx, path, buf, requestmap);
238 }
239
241 apr_pool_tag(gPool, apr_pstrdup(gPool, "cstat_mem_pool"));
242
245
247 apr_pool_userdata_set ((void*)rwlock, "STAT_CACHE_LOCK", apr_pool_cleanup_null, gPool);
248 }
249 else {
250 apr_pool_userdata_get((void**)&statCache, "STAT_CACHE", gPool);
251 apr_pool_userdata_get((void**)&rwlock, "STAT_CACHE_LOCK", gPool);
252 }
253
254 if (!gPool || !statCache || !rwlock) {
255 return getstat(ctx, path, buf, requestmap);
256 }
257
258 for (x = 0,tr = path;*tr != '\0';tr++,x++) {
259 if (*tr == '\\' || *tr == '/') {
260 ptr = tr;
261 len = x;
262 }
263 if (*tr == ':') {
264 ptr = "\\";
265 len = x;
266 }
267 }
268
269 if (ptr) {
271 strlwr(ppath);
272 if (ptr[1] != '\0') {
273 ptr++;
274 }
275 /* If the path ended in a trailing slash then our result path
276 will be a single slash. To avoid stat'ing the root with a
277 slash, we need to make sure we stat the current directory
278 with a dot */
279 if (((*ptr == '/') || (*ptr == '\\')) && (*(ptr+1) == '\0')) {
280 pinfo = apr_pstrdup (p, ".");
281 }
282 else {
283 pinfo = apr_pstrdup (p, ptr);
284 }
285 }
286
287 /* If we have a statCache then try to pull the information
288 from the cache. Otherwise just stat the file and return.*/
289 if (statCache) {
293 if (pathctx) {
295 }
296 else {
297 int err;
298
300 if (!err) {
305 }
306 }
307 }
308 }
309 return getstat(ctx, path, buf, requestmap);
310}
311#endif
312
314 const char *fname,
316{
317 struct stat info;
318 int srv;
319 NXPathCtx_t pathCtx = 0;
320
321 getcwdpath(NULL, &pathCtx, CTX_ACTUAL_CWD);
322#ifdef APR_HAS_PSA
323 srv = getstat(pathCtx, (char*)fname, &info, ST_STAT_BITS|ST_NAME_BIT);
324#else
325 srv = cstat(pathCtx, (char*)fname, &info, ST_STAT_BITS|ST_NAME_BIT, pool);
326#endif
327 errno = srv;
328
329 if (srv == 0) {
330 finfo->pool = pool;
331 finfo->fname = fname;
332 fill_out_finfo(finfo, &info, wanted);
335 if (wanted & APR_FINFO_NAME) {
336 finfo->name = apr_pstrdup(pool, info.st_name);
337 finfo->valid |= APR_FINFO_NAME;
338 }
339 return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
340 }
341 else {
342#if !defined(ENOENT) || !defined(ENOTDIR)
343#error ENOENT || ENOTDIR not defined; please see the
344#error comments at this line in the source for a workaround.
345 /*
346 * If ENOENT || ENOTDIR is not defined in one of the your OS's
347 * include files, APR cannot report a good reason why the stat()
348 * of the file failed; there are cases where it can fail even though
349 * the file exists. This opens holes in Apache, for example, because
350 * it becomes possible for someone to get a directory listing of a
351 * directory even though there is an index (eg. index.html) file in
352 * it. If you do not have a problem with this, delete the above
353 * #error lines and start the compile again. If you need to do this,
354 * please submit a bug report to http://www.apache.org/bug_report.html
355 * letting us know that you needed to do this. Please be sure to
356 * include the operating system you are using.
357 */
358 /* WARNING: All errors will be handled as not found
359 */
360#if !defined(ENOENT)
361 return APR_ENOENT;
362#else
363 /* WARNING: All errors but not found will be handled as not directory
364 */
365 if (errno != ENOENT)
366 return APR_ENOENT;
367 else
368 return errno;
369#endif
370#else /* All was defined well, report the usual: */
371 return errno;
372#endif
373 }
374}
375
379{
381 apr_finfo_t finfo;
382
384 if (status) {
385 return status;
386 }
387
388#ifdef HAVE_UTIMES
389 {
390 struct timeval tvp[2];
391
392 tvp[0].tv_sec = apr_time_sec(finfo.atime);
393 tvp[0].tv_usec = apr_time_usec(finfo.atime);
394 tvp[1].tv_sec = apr_time_sec(mtime);
395 tvp[1].tv_usec = apr_time_usec(mtime);
396
397 if (utimes(fname, tvp) == -1) {
398 return errno;
399 }
400 }
401#elif defined(HAVE_UTIME)
402 {
403 struct utimbuf buf;
404
405 buf.actime = (time_t) (finfo.atime / APR_USEC_PER_SEC);
406 buf.modtime = (time_t) (mtime / APR_USEC_PER_SEC);
407
408 if (utime(fname, &buf) == -1) {
409 return errno;
410 }
411 }
412#else
413 return APR_ENOTIMPL;
414#endif
415
416 return APR_SUCCESS;
417}
const char apr_size_t len
Definition ap_regex.h:187
mode_t
Definition aplibtool.c:31
APR Error Codes.
APR File I/O Handling.
APR Miscellaneous library routines.
APR Hash Tables.
APR Strings library.
APR Reader/Writer Lock Routines.
request_rec int int apr_table_t const char * path
const unsigned char * buf
Definition util_md5.h:50
#define APR_INCOMPLETE
Definition apr_errno.h:452
#define APR_ENOTIMPL
Definition apr_errno.h:476
#define APR_ENOENT
Definition apr_errno.h:662
apr_brigade_flush void * ctx
apr_dbd_transaction_t int mode
Definition apr_dbd.h:261
const void apr_status_t(*) apr_status_t(* APR_DECLARE)(void) apr_pool_pre_cleanup_register(apr_pool_t *p
Definition apr_pools.h:646
apr_size_t size
const char int apr_pool_t * pool
Definition apr_cstr.h:84
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
#define APR_FILE_ATTR_READONLY
#define APR_FILE_ATTR_EXECUTABLE
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
@ APR_NOFILE
apr_file_t * thefile
const char * key
apr_uint32_t apr_fileattrs_t
const char apr_fileperms_t perms
apr_fileattrs_t attributes
void * data
int type
apr_time_t mtime
apr_fileattrs_t apr_fileattrs_t attr_mask
#define APR_UEXECUTE
#define APR_UWRITE
#define APR_GWRITE
#define APR_GEXECUTE
#define APR_WWRITE
#define APR_WEXECUTE
#define APR_FINFO_ATIME
#define APR_FINFO_OWNER
#define APR_FINFO_MIN
#define APR_FINFO_IDENT
const char apr_int32_t wanted
const char * fname
#define APR_FINFO_NAME
#define APR_FINFO_LINK
#define APR_FINFO_NLINK
#define APR_FINFO_PROT
#define APR_FINFO_CSIZE
#define APR_HASH_KEY_STRING
Definition apr_hash.h:47
#define apr_pool_create(newpool, parent)
Definition apr_pools.h:322
apr_int32_t apr_int32_t apr_int32_t err
int int status
#define APR_USEC_PER_SEC
Definition apr_time.h:60
apr_int64_t apr_time_t
Definition apr_time.h:45
#define apr_time_sec(time)
Definition apr_time.h:63
#define apr_time_usec(time)
Definition apr_time.h:66
apr_pool_t * p
Definition md_event.c:32
return NULL
Definition mod_so.c:359
struct stat struct_stat
static void fill_out_finfo(apr_finfo_t *finfo, struct stat *info, apr_int32_t wanted)
Definition filestat.c:56
static apr_filetype_e filetype_from_mode(mode_t mode)
Definition filestat.c:33
apr_status_t apr_file_info_get_locked(apr_finfo_t *finfo, apr_int32_t wanted, apr_file_t *thefile)
Definition filestat.c:85
#define S_ISREG(m)
Definition readfilemap.c:71
void * getGlobalPool()
Definition libprews.c:176
int setGlobalPool(void *data)
Definition libprews.c:162
apr_pool_t * pool
apr_gid_t group
apr_filetype_e filetype
const char * name
apr_dev_t device
apr_off_t size
apr_pool_t * pool
apr_ino_t inode
apr_fileperms_t protection
apr_int32_t nlink
apr_uid_t user
const char * fname
apr_time_t atime
apr_off_t csize
apr_time_t ctime
apr_time_t mtime
apr_int32_t valid
mode_t apr_unix_perms2mode(apr_fileperms_t perms)
Definition fileacc.c:35
apr_fileperms_t apr_unix_mode2perms(mode_t mode)
Definition fileacc.c:71
apr_status_t apr_file_flush_locked(apr_file_t *thefile)
Definition readwrite.c:313
INT info
static size_t keylen(KEY s)
Definition xmlparse.c:7166