1251875Speter/* Licensed to the Apache Software Foundation (ASF) under one or more
2251875Speter * contributor license agreements.  See the NOTICE file distributed with
3251875Speter * this work for additional information regarding copyright ownership.
4251875Speter * The ASF licenses this file to You under the Apache License, Version 2.0
5251875Speter * (the "License"); you may not use this file except in compliance with
6251875Speter * the License.  You may obtain a copy of the License at
7251875Speter *
8251875Speter *     http://www.apache.org/licenses/LICENSE-2.0
9251875Speter *
10251875Speter * Unless required by applicable law or agreed to in writing, software
11251875Speter * distributed under the License is distributed on an "AS IS" BASIS,
12251875Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13251875Speter * See the License for the specific language governing permissions and
14251875Speter * limitations under the License.
15251875Speter */
16251875Speter
17251875Speter#include "apr_arch_file_io.h"
18251875Speter
19251875Speter#if APR_HAVE_FCNTL_H
20251875Speter#include <fcntl.h>
21251875Speter#endif
22251875Speter#ifdef HAVE_SYS_FILE_H
23251875Speter#include <sys/file.h>
24251875Speter#endif
25251875Speter
26251875SpeterAPR_DECLARE(apr_status_t) apr_file_lock(apr_file_t *thefile, int type)
27251875Speter{
28251875Speter    int rc;
29251875Speter
30251875Speter#if defined(HAVE_FCNTL_H)
31251875Speter    {
32251875Speter        struct flock l = { 0 };
33251875Speter        int fc;
34251875Speter
35251875Speter        l.l_whence = SEEK_SET;  /* lock from current point */
36251875Speter        l.l_start = 0;          /* begin lock at this offset */
37251875Speter        l.l_len = 0;            /* lock to end of file */
38251875Speter        if ((type & APR_FLOCK_TYPEMASK) == APR_FLOCK_SHARED)
39251875Speter            l.l_type = F_RDLCK;
40251875Speter        else
41251875Speter            l.l_type = F_WRLCK;
42251875Speter
43251875Speter        fc = (type & APR_FLOCK_NONBLOCK) ? F_SETLK : F_SETLKW;
44251875Speter
45251875Speter        /* keep trying if fcntl() gets interrupted (by a signal) */
46251875Speter        while ((rc = fcntl(thefile->filedes, fc, &l)) < 0 && errno == EINTR)
47251875Speter            continue;
48251875Speter
49251875Speter        if (rc == -1) {
50251875Speter            /* on some Unix boxes (e.g., Tru64), we get EACCES instead
51251875Speter             * of EAGAIN; we don't want APR_STATUS_IS_EAGAIN() matching EACCES
52251875Speter             * since that breaks other things, so fix up the retcode here
53251875Speter             */
54251875Speter            if (errno == EACCES) {
55251875Speter                return EAGAIN;
56251875Speter            }
57251875Speter            return errno;
58251875Speter        }
59251875Speter    }
60251875Speter#elif defined(HAVE_SYS_FILE_H)
61251875Speter    {
62251875Speter        int ltype;
63251875Speter
64251875Speter        if ((type & APR_FLOCK_TYPEMASK) == APR_FLOCK_SHARED)
65251875Speter            ltype = LOCK_SH;
66251875Speter        else
67251875Speter            ltype = LOCK_EX;
68251875Speter        if ((type & APR_FLOCK_NONBLOCK) != 0)
69251875Speter            ltype |= LOCK_NB;
70251875Speter
71251875Speter        /* keep trying if flock() gets interrupted (by a signal) */
72251875Speter        while ((rc = flock(thefile->filedes, ltype)) < 0 && errno == EINTR)
73251875Speter            continue;
74251875Speter
75251875Speter        if (rc == -1)
76251875Speter            return errno;
77251875Speter    }
78251875Speter#else
79251875Speter#error No file locking mechanism is available.
80251875Speter#endif
81251875Speter
82251875Speter    return APR_SUCCESS;
83251875Speter}
84251875Speter
85251875SpeterAPR_DECLARE(apr_status_t) apr_file_unlock(apr_file_t *thefile)
86251875Speter{
87251875Speter    int rc;
88251875Speter
89251875Speter#if defined(HAVE_FCNTL_H)
90251875Speter    {
91251875Speter        struct flock l = { 0 };
92251875Speter
93251875Speter        l.l_whence = SEEK_SET;  /* lock from current point */
94251875Speter        l.l_start = 0;          /* begin lock at this offset */
95251875Speter        l.l_len = 0;            /* lock to end of file */
96251875Speter        l.l_type = F_UNLCK;
97251875Speter
98251875Speter        /* keep trying if fcntl() gets interrupted (by a signal) */
99251875Speter        while ((rc = fcntl(thefile->filedes, F_SETLKW, &l)) < 0
100251875Speter               && errno == EINTR)
101251875Speter            continue;
102251875Speter
103251875Speter        if (rc == -1)
104251875Speter            return errno;
105251875Speter    }
106251875Speter#elif defined(HAVE_SYS_FILE_H)
107251875Speter    {
108251875Speter        /* keep trying if flock() gets interrupted (by a signal) */
109251875Speter        while ((rc = flock(thefile->filedes, LOCK_UN)) < 0 && errno == EINTR)
110251875Speter            continue;
111251875Speter
112251875Speter        if (rc == -1)
113251875Speter            return errno;
114251875Speter    }
115251875Speter#else
116251875Speter#error No file locking mechanism is available.
117251875Speter#endif
118251875Speter
119251875Speter    return APR_SUCCESS;
120251875Speter}
121