~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to srclib/apr/file_io/unix/filestat.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
 
2
 * applicable.
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * 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_DECLARE(apr_status_t) apr_file_info_get(apr_finfo_t *finfo, 
 
95
                                            apr_int32_t wanted,
 
96
                                            apr_file_t *thefile)
 
97
{
 
98
    struct_stat info;
 
99
 
 
100
    if (thefile->buffered) {
 
101
        apr_status_t rv = apr_file_flush(thefile);
 
102
        if (rv != APR_SUCCESS)
 
103
            return rv;
 
104
    }
 
105
 
 
106
    if (fstat(thefile->filedes, &info) == 0) {
 
107
        finfo->pool = thefile->pool;
 
108
        finfo->fname = thefile->fname;
 
109
        fill_out_finfo(finfo, &info, wanted);
 
110
        return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
 
111
    }
 
112
    else {
 
113
        return errno;
 
114
    }
 
115
}
 
116
 
 
117
APR_DECLARE(apr_status_t) apr_file_perms_set(const char *fname, 
 
118
                                             apr_fileperms_t perms)
 
119
{
 
120
    mode_t mode = apr_unix_perms2mode(perms);
 
121
 
 
122
    if (chmod(fname, mode) == -1)
 
123
        return errno;
 
124
    return APR_SUCCESS;
 
125
}
 
126
 
 
127
APR_DECLARE(apr_status_t) apr_file_attrs_set(const char *fname,
 
128
                                             apr_fileattrs_t attributes,
 
129
                                             apr_fileattrs_t attr_mask,
 
130
                                             apr_pool_t *pool)
 
131
{
 
132
    apr_status_t status;
 
133
    apr_finfo_t finfo;
 
134
 
 
135
    /* Don't do anything if we can't handle the requested attributes */
 
136
    if (!(attr_mask & (APR_FILE_ATTR_READONLY
 
137
                       | APR_FILE_ATTR_EXECUTABLE)))
 
138
        return APR_SUCCESS;
 
139
 
 
140
    status = apr_stat(&finfo, fname, APR_FINFO_PROT, pool);
 
141
    if (status)
 
142
        return status;
 
143
 
 
144
    /* ### TODO: should added bits be umask'd? */
 
145
    if (attr_mask & APR_FILE_ATTR_READONLY)
 
146
    {
 
147
        if (attributes & APR_FILE_ATTR_READONLY)
 
148
        {
 
149
            finfo.protection &= ~APR_UWRITE;
 
150
            finfo.protection &= ~APR_GWRITE;
 
151
            finfo.protection &= ~APR_WWRITE;
 
152
        }
 
153
        else
 
154
        {
 
155
            /* ### umask this! */
 
156
            finfo.protection |= APR_UWRITE;
 
157
            finfo.protection |= APR_GWRITE;
 
158
            finfo.protection |= APR_WWRITE;
 
159
        }
 
160
    }
 
161
 
 
162
    if (attr_mask & APR_FILE_ATTR_EXECUTABLE)
 
163
    {
 
164
        if (attributes & APR_FILE_ATTR_EXECUTABLE)
 
165
        {
 
166
            /* ### umask this! */
 
167
            finfo.protection |= APR_UEXECUTE;
 
168
            finfo.protection |= APR_GEXECUTE;
 
169
            finfo.protection |= APR_WEXECUTE;
 
170
        }
 
171
        else
 
172
        {
 
173
            finfo.protection &= ~APR_UEXECUTE;
 
174
            finfo.protection &= ~APR_GEXECUTE;
 
175
            finfo.protection &= ~APR_WEXECUTE;
 
176
        }
 
177
    }
 
178
 
 
179
    return apr_file_perms_set(fname, finfo.protection);
 
180
}
 
181
 
 
182
 
 
183
APR_DECLARE(apr_status_t) apr_file_mtime_set(const char *fname,
 
184
                                              apr_time_t mtime,
 
185
                                              apr_pool_t *pool)
 
186
{
 
187
    apr_status_t status;
 
188
    apr_finfo_t finfo;
 
189
 
 
190
    status = apr_stat(&finfo, fname, APR_FINFO_ATIME, pool);
 
191
    if (status) {
 
192
        return status;
 
193
    }
 
194
 
 
195
#ifdef HAVE_UTIMES
 
196
    {
 
197
      struct timeval tvp[2];
 
198
    
 
199
      tvp[0].tv_sec = apr_time_sec(finfo.atime);
 
200
      tvp[0].tv_usec = apr_time_usec(finfo.atime);
 
201
      tvp[1].tv_sec = apr_time_sec(mtime);
 
202
      tvp[1].tv_usec = apr_time_usec(mtime);
 
203
      
 
204
      if (utimes(fname, tvp) == -1) {
 
205
        return errno;
 
206
      }
 
207
    }
 
208
#elif defined(HAVE_UTIME)
 
209
    {
 
210
      struct utimbuf buf;
 
211
      
 
212
      buf.actime = (time_t) (finfo.atime / APR_USEC_PER_SEC);
 
213
      buf.modtime = (time_t) (mtime / APR_USEC_PER_SEC);
 
214
      
 
215
      if (utime(fname, &buf) == -1) {
 
216
        return errno;
 
217
      }
 
218
    }
 
219
#else
 
220
    return APR_ENOTIMPL;
 
221
#endif
 
222
 
 
223
    return APR_SUCCESS;
 
224
}
 
225
 
 
226
 
 
227
APR_DECLARE(apr_status_t) apr_stat(apr_finfo_t *finfo, 
 
228
                                   const char *fname, 
 
229
                                   apr_int32_t wanted, apr_pool_t *pool)
 
230
{
 
231
    struct_stat info;
 
232
    int srv;
 
233
 
 
234
    if (wanted & APR_FINFO_LINK)
 
235
        srv = lstat(fname, &info);
 
236
    else
 
237
        srv = stat(fname, &info);
 
238
 
 
239
    if (srv == 0) {
 
240
        finfo->pool = pool;
 
241
        finfo->fname = fname;
 
242
        fill_out_finfo(finfo, &info, wanted);
 
243
        if (wanted & APR_FINFO_LINK)
 
244
            wanted &= ~APR_FINFO_LINK;
 
245
        return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
 
246
    }
 
247
    else {
 
248
#if !defined(ENOENT) || !defined(ENOTDIR)
 
249
#error ENOENT || ENOTDIR not defined; please see the
 
250
#error comments at this line in the source for a workaround.
 
251
        /*
 
252
         * If ENOENT || ENOTDIR is not defined in one of the your OS's
 
253
         * include files, APR cannot report a good reason why the stat()
 
254
         * of the file failed; there are cases where it can fail even though
 
255
         * the file exists.  This opens holes in Apache, for example, because
 
256
         * it becomes possible for someone to get a directory listing of a 
 
257
         * directory even though there is an index (eg. index.html) file in 
 
258
         * it.  If you do not have a problem with this, delete the above 
 
259
         * #error lines and start the compile again.  If you need to do this,
 
260
         * please submit a bug report to http://www.apache.org/bug_report.html
 
261
         * letting us know that you needed to do this.  Please be sure to 
 
262
         * include the operating system you are using.
 
263
         */
 
264
        /* WARNING: All errors will be handled as not found
 
265
         */
 
266
#if !defined(ENOENT) 
 
267
        return APR_ENOENT;
 
268
#else
 
269
        /* WARNING: All errors but not found will be handled as not directory
 
270
         */
 
271
        if (errno != ENOENT)
 
272
            return APR_ENOENT;
 
273
        else
 
274
            return errno;
 
275
#endif
 
276
#else /* All was defined well, report the usual: */
 
277
        return errno;
 
278
#endif
 
279
    }
 
280
}
 
281
 
 
282