bottleneck testcase based on rubbos
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / srclib / apr / file_io / unix / filestat.c
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_general.h"
20 #include "apr_strings.h"
21 #include "apr_errno.h"
22
23 #ifdef HAVE_UTIME
24 #include <utime.h>
25 #endif
26
27 static apr_filetype_e filetype_from_mode(mode_t mode)
28 {
29     apr_filetype_e type;
30
31     switch (mode & S_IFMT) {
32     case S_IFREG:
33         type = APR_REG;  break;
34     case S_IFDIR:
35         type = APR_DIR;  break;
36     case S_IFLNK:
37         type = APR_LNK;  break;
38     case S_IFCHR:
39         type = APR_CHR;  break;
40     case S_IFBLK:
41         type = APR_BLK;  break;
42 #if defined(S_IFFIFO)
43     case S_IFFIFO:
44         type = APR_PIPE; break;
45 #endif
46 #if !defined(BEOS) && defined(S_IFSOCK)
47     case S_IFSOCK:
48         type = APR_SOCK; break;
49 #endif
50
51     default:
52         /* Work around missing S_IFxxx values above
53          * for Linux et al.
54          */
55 #if !defined(S_IFFIFO) && defined(S_ISFIFO)
56         if (S_ISFIFO(mode)) {
57             type = APR_PIPE;
58         } else
59 #endif
60 #if !defined(BEOS) && !defined(S_IFSOCK) && defined(S_ISSOCK)
61         if (S_ISSOCK(mode)) {
62             type = APR_SOCK;
63         } else
64 #endif
65         type = APR_UNKFILE;
66     }
67     return type;
68 }
69
70 static void fill_out_finfo(apr_finfo_t *finfo, struct stat *info,
71                            apr_int32_t wanted)
72
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;
90      * }
91      */
92 }
93
94 apr_status_t apr_file_info_get_locked(apr_finfo_t *finfo, apr_int32_t wanted,
95                                       apr_file_t *thefile)
96 {
97     struct stat info;
98
99     if (thefile->buffered) {
100         apr_status_t rv = apr_file_flush_locked(thefile);
101         if (rv != APR_SUCCESS)
102             return rv;
103     }
104
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;
110     }
111     else {
112         return errno;
113     }
114 }
115
116 APR_DECLARE(apr_status_t) apr_file_info_get(apr_finfo_t *finfo, 
117                                             apr_int32_t wanted,
118                                             apr_file_t *thefile)
119 {
120     struct stat info;
121
122     if (thefile->buffered) {
123         apr_status_t rv = apr_file_flush(thefile);
124         if (rv != APR_SUCCESS)
125             return rv;
126     }
127
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;
133     }
134     else {
135         return errno;
136     }
137 }
138
139 APR_DECLARE(apr_status_t) apr_file_perms_set(const char *fname, 
140                                              apr_fileperms_t perms)
141 {
142     mode_t mode = apr_unix_perms2mode(perms);
143
144     if (chmod(fname, mode) == -1)
145         return errno;
146     return APR_SUCCESS;
147 }
148
149 APR_DECLARE(apr_status_t) apr_file_attrs_set(const char *fname,
150                                              apr_fileattrs_t attributes,
151                                              apr_fileattrs_t attr_mask,
152                                              apr_pool_t *pool)
153 {
154     apr_status_t status;
155     apr_finfo_t finfo;
156
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)))
160         return APR_SUCCESS;
161
162     status = apr_stat(&finfo, fname, APR_FINFO_PROT, pool);
163     if (!APR_STATUS_IS_SUCCESS(status))
164         return status;
165
166     /* ### TODO: should added bits be umask'd? */
167     if (attr_mask & APR_FILE_ATTR_READONLY)
168     {
169         if (attributes & APR_FILE_ATTR_READONLY)
170         {
171             finfo.protection &= ~APR_UWRITE;
172             finfo.protection &= ~APR_GWRITE;
173             finfo.protection &= ~APR_WWRITE;
174         }
175         else
176         {
177             /* ### umask this! */
178             finfo.protection |= APR_UWRITE;
179             finfo.protection |= APR_GWRITE;
180             finfo.protection |= APR_WWRITE;
181         }
182     }
183
184     if (attr_mask & APR_FILE_ATTR_EXECUTABLE)
185     {
186         if (attributes & APR_FILE_ATTR_EXECUTABLE)
187         {
188             /* ### umask this! */
189             finfo.protection |= APR_UEXECUTE;
190             finfo.protection |= APR_GEXECUTE;
191             finfo.protection |= APR_WEXECUTE;
192         }
193         else
194         {
195             finfo.protection &= ~APR_UEXECUTE;
196             finfo.protection &= ~APR_GEXECUTE;
197             finfo.protection &= ~APR_WEXECUTE;
198         }
199     }
200
201     return apr_file_perms_set(fname, finfo.protection);
202 }
203
204
205 APR_DECLARE(apr_status_t) apr_file_mtime_set(const char *fname,
206                                               apr_time_t mtime,
207                                               apr_pool_t *pool)
208 {
209     apr_status_t status;
210     apr_finfo_t finfo;
211
212     status = apr_stat(&finfo, fname, APR_FINFO_ATIME, pool);
213     if (!APR_STATUS_IS_SUCCESS(status)) {
214         return status;
215     }
216
217 #ifdef HAVE_UTIMES
218     {
219       struct timeval tvp[2];
220     
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);
225       
226       if (utimes(fname, tvp) == -1) {
227         return errno;
228       }
229     }
230 #elif defined(HAVE_UTIME)
231     {
232       struct utimbuf buf;
233       
234       buf.actime = (time_t) (finfo.atime / APR_USEC_PER_SEC);
235       buf.modtime = (time_t) (mtime / APR_USEC_PER_SEC);
236       
237       if (utime(fname, &buf) == -1) {
238         return errno;
239       }
240     }
241 #else
242     return APR_ENOTIMPL;
243 #endif
244
245     return APR_SUCCESS;
246 }
247
248
249 APR_DECLARE(apr_status_t) apr_stat(apr_finfo_t *finfo, 
250                                    const char *fname, 
251                                    apr_int32_t wanted, apr_pool_t *pool)
252 {
253     struct stat info;
254     int srv;
255
256     if (wanted & APR_FINFO_LINK)
257         srv = lstat(fname, &info);
258     else
259         srv = stat(fname, &info);
260
261     if (srv == 0) {
262         finfo->pool = pool;
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;
268     }
269     else {
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.
273         /*
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.
285          */
286         /* WARNING: All errors will be handled as not found
287          */
288 #if !defined(ENOENT) 
289         return APR_ENOENT;
290 #else
291         /* WARNING: All errors but not found will be handled as not directory
292          */
293         if (errno != ENOENT)
294             return APR_ENOENT;
295         else
296             return errno;
297 #endif
298 #else /* All was defined well, report the usual: */
299         return errno;
300 #endif
301     }
302 }
303
304 /* Perhaps this becomes nothing but a macro?
305  */
306 APR_DECLARE(apr_status_t) apr_lstat(apr_finfo_t *finfo, const char *fname,
307                       apr_int32_t wanted, apr_pool_t *pool)
308 {
309     return apr_stat(finfo, fname, wanted | APR_FINFO_LINK, pool);
310 }
311