Apache HTTPD
open.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 "apr_strings.h"
19#include "apr_portable.h"
20#include "apr_thread_mutex.h"
21#include "apr_arch_inherit.h"
22
23#ifdef NETWARE
24#include "nks/dirio.h"
25#include "apr_hash.h"
26#include "fsio.h"
27#endif
28
30{
32 int fd = file->filedes;
33
34 /* Set file descriptor to -1 before close(), so that there is no
35 * chance of returning an already closed FD from apr_os_file_get().
36 */
37 file->filedes = -1;
38
39 if (close(fd) == 0) {
40 /* Only the parent process should delete the file! */
43 }
44#if APR_HAS_THREADS
45 if (file->thlock) {
46 rv = apr_thread_mutex_destroy(file->thlock);
47 }
48#endif
49 }
50 else {
51 /* Restore, close() was not successful. */
52 file->filedes = fd;
53
54 /* Are there any error conditions other than EINTR or EBADF? */
55 rv = errno;
56 }
57#ifndef WAITIO_USES_POLL
58 if (file->pollset != NULL) {
60 /* If the file close failed, return its error value,
61 * not apr_pollset_destroy()'s.
62 */
63 if (rv == APR_SUCCESS) {
64 rv = pollset_rv;
65 }
66 }
67#endif /* !WAITIO_USES_POLL */
68 return rv;
69}
70
72{
75
76 if (file->buffered) {
78 }
79
80 rv = file_cleanup(file, 0);
81
82 return rv != APR_SUCCESS ? rv : flush_rv;
83}
84
89
91 const char *fname,
95{
97 int oflags = 0;
98#if APR_HAS_THREADS
100 apr_status_t rv;
101#endif
102
103 if ((flag & APR_FOPEN_READ) && (flag & APR_FOPEN_WRITE)) {
104 oflags = O_RDWR;
105 }
106 else if (flag & APR_FOPEN_READ) {
108 }
109 else if (flag & APR_FOPEN_WRITE) {
111 }
112 else {
113 return APR_EACCES;
114 }
115
116 if (flag & APR_FOPEN_CREATE) {
117 oflags |= O_CREAT;
118 if (flag & APR_FOPEN_EXCL) {
119 oflags |= O_EXCL;
120 }
121 }
122 if ((flag & APR_FOPEN_EXCL) && !(flag & APR_FOPEN_CREATE)) {
123 return APR_EACCES;
124 }
125
126 if (flag & APR_FOPEN_APPEND) {
127 oflags |= O_APPEND;
128 }
129 if (flag & APR_FOPEN_TRUNCATE) {
130 oflags |= O_TRUNC;
131 }
132#ifdef O_BINARY
133 if (flag & APR_FOPEN_BINARY) {
134 oflags |= O_BINARY;
135 }
136#endif
137
138 if (flag & APR_FOPEN_NONBLOCK) {
139#ifdef O_NONBLOCK
141#else
142 return APR_ENOTIMPL;
143#endif
144 }
145
146#ifdef O_CLOEXEC
147 /* Introduced in Linux 2.6.23. Silently ignored on earlier Linux kernels.
148 */
149 if (!(flag & APR_FOPEN_NOCLEANUP)) {
150 oflags |= O_CLOEXEC;
151}
152#endif
153
154#if APR_HAS_LARGE_FILES && defined(_LARGEFILE64_SOURCE)
156#elif defined(O_LARGEFILE)
159 }
160#endif
161
162#if APR_HAS_THREADS
166 if (rv) {
167 return rv;
168 }
169 }
170#endif
171
172 if (perm == APR_OS_DEFAULT) {
173 fd = open(fname, oflags, 0666);
174 }
175 else {
177 }
178 if (fd < 0) {
179 return errno;
180 }
181 if (!(flag & APR_FOPEN_NOCLEANUP)) {
182#ifdef O_CLOEXEC
183 static int has_o_cloexec = 0;
184 if (!has_o_cloexec)
185#endif
186 {
187 int flags;
188
189 if ((flags = fcntl(fd, F_GETFD)) == -1) {
190 close(fd);
191 return errno;
192 }
193 if ((flags & FD_CLOEXEC) == 0) {
194 flags |= FD_CLOEXEC;
195 if (fcntl(fd, F_SETFD, flags) == -1) {
196 close(fd);
197 return errno;
198 }
199 }
200#ifdef O_CLOEXEC
201 else {
202 has_o_cloexec = 1;
203 }
204#endif
205 }
206 }
207
208 (*new) = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t));
209 (*new)->pool = pool;
210 (*new)->flags = flag;
211 (*new)->filedes = fd;
212
213 (*new)->fname = apr_pstrdup(pool, fname);
214
215 (*new)->blocking = BLK_ON;
216 (*new)->buffered = (flag & APR_FOPEN_BUFFERED) > 0;
217
218 if ((*new)->buffered) {
219 (*new)->buffer = apr_palloc(pool, APR_FILE_DEFAULT_BUFSIZE);
220 (*new)->bufsize = APR_FILE_DEFAULT_BUFSIZE;
221#if APR_HAS_THREADS
222 if ((*new)->flags & APR_FOPEN_XTHREAD) {
223 (*new)->thlock = thlock;
224 }
225#endif
226 }
227 else {
228 (*new)->buffer = NULL;
229 }
230
231 (*new)->is_pipe = 0;
232 (*new)->timeout = -1;
233 (*new)->ungetchar = -1;
234 (*new)->eof_hit = 0;
235 (*new)->filePtr = 0;
236 (*new)->bufpos = 0;
237 (*new)->dataRead = 0;
238 (*new)->direction = 0;
239#ifndef WAITIO_USES_POLL
240 /* Start out with no pollset. apr_wait_for_io_or_timeout() will
241 * initialize the pollset if needed.
242 */
243 (*new)->pollset = NULL;
244#endif
245 if (!(flag & APR_FOPEN_NOCLEANUP)) {
246 apr_pool_cleanup_register((*new)->pool, (void *)(*new),
249 }
250 return APR_SUCCESS;
251}
252
254{
256}
257
259{
260 if (unlink(path) == 0) {
261 return APR_SUCCESS;
262 }
263 else {
264 return errno;
265 }
266}
267
269 const char *to_path,
270 apr_pool_t *p)
271{
272 if (rename(from_path, to_path) != 0) {
273 return errno;
274 }
275 return APR_SUCCESS;
276}
277
280{
281 *thefile = file->filedes;
282 return APR_SUCCESS;
283}
284
288{
289 int *dafile = thefile;
290
291 (*file) = apr_pcalloc(pool, sizeof(apr_file_t));
292 (*file)->pool = pool;
293 (*file)->eof_hit = 0;
294 (*file)->blocking = BLK_UNKNOWN; /* in case it is a pipe */
295 (*file)->timeout = -1;
296 (*file)->ungetchar = -1; /* no char avail */
297 (*file)->filedes = *dafile;
298 (*file)->flags = flags | APR_FOPEN_NOCLEANUP;
299 (*file)->buffered = (flags & APR_FOPEN_BUFFERED) > 0;
300
301#ifndef WAITIO_USES_POLL
302 /* Start out with no pollset. apr_wait_for_io_or_timeout() will
303 * initialize the pollset if needed.
304 */
305 (*file)->pollset = NULL;
306#endif
307
308 if ((*file)->buffered) {
309 (*file)->buffer = apr_palloc(pool, APR_FILE_DEFAULT_BUFSIZE);
310 (*file)->bufsize = APR_FILE_DEFAULT_BUFSIZE;
311#if APR_HAS_THREADS
312 if ((*file)->flags & APR_FOPEN_XTHREAD) {
313 apr_status_t rv;
314 rv = apr_thread_mutex_create(&((*file)->thlock),
316 if (rv) {
317 return rv;
318 }
319 }
320#endif
321 }
322 return APR_SUCCESS;
323}
324
326{
327 if (fptr->eof_hit == 1) {
328 return APR_EOF;
329 }
330 return APR_SUCCESS;
331}
332
336{
337 int fd = STDERR_FILENO;
338
340}
341
345{
346 int fd = STDOUT_FILENO;
347
349}
350
354{
355 int fd = STDIN_FILENO;
356
358}
359
362{
364}
365
368{
370}
371
374{
376}
377
379
380/* We need to do this by hand instead of using APR_IMPLEMENT_INHERIT_UNSET
381 * because the macro sets both cleanups to the same function, which is not
382 * suitable on Unix (see PR 41119). */
384{
386 return APR_EINVAL;
387 }
388 if (thefile->flags & APR_INHERIT) {
389 int flags;
390
391 if ((flags = fcntl(thefile->filedes, F_GETFD)) == -1)
392 return errno;
393
394 flags |= FD_CLOEXEC;
395 if (fcntl(thefile->filedes, F_SETFD, flags) == -1)
396 return errno;
397
400 (void *)thefile,
403 }
404 return APR_SUCCESS;
405}
406
408
410 const char *to_path)
411{
412 if (link(from_path, to_path) == -1) {
413 return errno;
414 }
415
416 return APR_SUCCESS;
417}
APR Hash Tables.
APR Portability Routines.
APR Strings library.
APR Thread Mutex Routines.
request_rec int int apr_table_t const char * path
#define APR_EOF
Definition apr_errno.h:461
#define APR_EACCES
Definition apr_errno.h:641
#define APR_ENOTIMPL
Definition apr_errno.h:476
#define APR_EINVAL
Definition apr_errno.h:711
apr_file_t * fd
const char apr_ssize_t int flags
Definition apr_encode.h:168
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
apr_int32_t apr_fileperms_t
apr_file_t * thefile
const char apr_int32_t flag
const char apr_file_t * file
const char * to_path
const char apr_int32_t apr_fileperms_t perm
#define APR_FOPEN_TRUNCATE
Definition apr_file_io.h:58
#define APR_FOPEN_NONBLOCK
Definition apr_file_io.h:88
#define APR_FOPEN_NOCLEANUP
Definition apr_file_io.h:74
#define APR_FOPEN_XTHREAD
Definition apr_file_io.h:67
#define APR_FOPEN_APPEND
Definition apr_file_io.h:57
#define APR_FOPEN_DELONCLOSE
Definition apr_file_io.h:66
#define APR_FOPEN_EXCL
Definition apr_file_io.h:63
#define APR_FOPEN_BUFFERED
Definition apr_file_io.h:65
#define APR_FOPEN_WRITE
Definition apr_file_io.h:55
#define APR_FOPEN_BINARY
Definition apr_file_io.h:60
#define APR_FOPEN_LARGEFILE
Definition apr_file_io.h:82
#define APR_FOPEN_READ
Definition apr_file_io.h:54
#define APR_FOPEN_CREATE
Definition apr_file_io.h:56
#define APR_OS_DEFAULT
const char * fname
#define APR_POOL_IMPLEMENT_ACCESSOR(type)
Definition apr_pools.h:91
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
int apr_os_file_t
apr_pool_t * p
Definition md_event.c:32
return NULL
Definition mod_so.c:359
#define APR_FILE_DEFAULT_BUFSIZE
#define APR_INHERIT
#define APR_IMPLEMENT_INHERIT_SET(name, flag, pool, cleanup)
#define O_BINARY
Definition readfilemap.c:78
apr_int32_t flags
apr_pollset_t * pollset
apr_pool_t * pool
mode_t apr_unix_perms2mode(apr_fileperms_t perms)
Definition fileacc.c:35
apr_status_t apr_unix_child_file_cleanup(void *thefile)
Definition open.c:85
apr_status_t apr_unix_file_cleanup(void *thefile)
Definition open.c:71
static apr_status_t file_cleanup(apr_file_t *file, int is_child)
Definition open.c:29