summaryrefslogtreecommitdiffstats
path: root/file_io/unix/flock.c
diff options
context:
space:
mode:
Diffstat (limited to 'file_io/unix/flock.c')
-rw-r--r--file_io/unix/flock.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/file_io/unix/flock.c b/file_io/unix/flock.c
new file mode 100644
index 0000000..01e8a63
--- /dev/null
+++ b/file_io/unix/flock.c
@@ -0,0 +1,120 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_arch_file_io.h"
+
+#if APR_HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+
+APR_DECLARE(apr_status_t) apr_file_lock(apr_file_t *thefile, int type)
+{
+ int rc;
+
+#if defined(HAVE_FCNTL_H)
+ {
+ struct flock l = { 0 };
+ int fc;
+
+ l.l_whence = SEEK_SET; /* count l_start from start of file */
+ l.l_start = 0; /* lock from start of file */
+ l.l_len = 0; /* lock to end of file */
+ if ((type & APR_FLOCK_TYPEMASK) == APR_FLOCK_SHARED)
+ l.l_type = F_RDLCK;
+ else
+ l.l_type = F_WRLCK;
+
+ fc = (type & APR_FLOCK_NONBLOCK) ? F_SETLK : F_SETLKW;
+
+ /* keep trying if fcntl() gets interrupted (by a signal) */
+ while ((rc = fcntl(thefile->filedes, fc, &l)) < 0 && errno == EINTR)
+ continue;
+
+ if (rc == -1) {
+ /* on some Unix boxes (e.g., Tru64), we get EACCES instead
+ * of EAGAIN; we don't want APR_STATUS_IS_EAGAIN() matching EACCES
+ * since that breaks other things, so fix up the retcode here
+ */
+ if (errno == EACCES) {
+ return EAGAIN;
+ }
+ return errno;
+ }
+ }
+#elif defined(HAVE_SYS_FILE_H)
+ {
+ int ltype;
+
+ if ((type & APR_FLOCK_TYPEMASK) == APR_FLOCK_SHARED)
+ ltype = LOCK_SH;
+ else
+ ltype = LOCK_EX;
+ if ((type & APR_FLOCK_NONBLOCK) != 0)
+ ltype |= LOCK_NB;
+
+ /* keep trying if flock() gets interrupted (by a signal) */
+ while ((rc = flock(thefile->filedes, ltype)) < 0 && errno == EINTR)
+ continue;
+
+ if (rc == -1)
+ return errno;
+ }
+#else
+#error No file locking mechanism is available.
+#endif
+
+ return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_file_unlock(apr_file_t *thefile)
+{
+ int rc;
+
+#if defined(HAVE_FCNTL_H)
+ {
+ struct flock l = { 0 };
+
+ l.l_whence = SEEK_SET; /* count l_start from start of file */
+ l.l_start = 0; /* lock from start of file */
+ l.l_len = 0; /* lock to end of file */
+ l.l_type = F_UNLCK;
+
+ /* keep trying if fcntl() gets interrupted (by a signal) */
+ while ((rc = fcntl(thefile->filedes, F_SETLKW, &l)) < 0
+ && errno == EINTR)
+ continue;
+
+ if (rc == -1)
+ return errno;
+ }
+#elif defined(HAVE_SYS_FILE_H)
+ {
+ /* keep trying if flock() gets interrupted (by a signal) */
+ while ((rc = flock(thefile->filedes, LOCK_UN)) < 0 && errno == EINTR)
+ continue;
+
+ if (rc == -1)
+ return errno;
+ }
+#else
+#error No file locking mechanism is available.
+#endif
+
+ return APR_SUCCESS;
+}