summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am3
-rw-r--r--src/util/util.h4
-rw-r--r--src/util/util_lock.c83
3 files changed, 89 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 07dcbd21..3306bbac 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -507,7 +507,8 @@ libsss_util_la_SOURCES = \
src/util/murmurhash3.c \
src/util/atomic_io.c \
src/util/sss_selinux.c \
- src/util/domain_info_utils.c
+ src/util/domain_info_utils.c \
+ src/util/util_lock.c
libsss_util_la_LIBADD = \
$(SSSD_LIBS) \
$(UNICODE_LIBS) \
diff --git a/src/util/util.h b/src/util/util.h
index de9e6b89..d9315aef 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -559,6 +559,10 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx,
struct sss_domain_info *copy_subdomain(TALLOC_CTX *mem_ctx,
struct sss_domain_info *subdomain);
+/* from util_lock.c */
+errno_t sss_br_lock_file(int fd, size_t start, size_t len,
+ int retries, useconds_t wait);
+
/* Endianness-compatibility for systems running older versions of glibc */
#ifndef le32toh
diff --git a/src/util/util_lock.c b/src/util/util_lock.c
new file mode 100644
index 00000000..c2d7fac7
--- /dev/null
+++ b/src/util/util_lock.c
@@ -0,0 +1,83 @@
+/*
+ SSSD
+
+ util_lock.c
+
+ Authors:
+ Michal Zidek <mzidek@redhat.com>
+
+ Copyright (C) 2012 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "util/util.h"
+
+errno_t sss_br_lock_file(int fd, size_t start, size_t len,
+ int retries, useconds_t wait)
+{
+ int ret;
+ struct flock lock;
+ int retries_left;
+
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = start;
+ lock.l_len = len;
+ lock.l_pid = 0;
+
+ for (retries_left = retries; retries_left > 0; retries_left--) {
+ ret = fcntl(fd, F_SETLK, &lock);
+ if (ret == -1) {
+ ret = errno;
+ if (ret == EACCES || ret == EAGAIN || ret == EINTR) {
+ DEBUG(SSSDBG_TRACE_FUNC,
+ ("Failed to lock file. Retries left: %d\n",
+ retries_left - 1));
+
+ if ((ret == EACCES || ret == EAGAIN) && (retries_left <= 1)) {
+ /* File is locked by someone else. Return EACCESS
+ * if this is the last try. */
+ return EACCES;
+ }
+
+ if (retries_left - 1 > 0) {
+ ret = usleep(wait);
+ if (ret == -1) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ ("usleep() failed -> ignoring\n"));
+ }
+ }
+ } else {
+ /* Error occurred */
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Unable to lock file.\n"));
+ return ret;
+ }
+ } else if (ret == 0) {
+ /* File successfuly locked */
+ break;
+ }
+ }
+ if (retries_left == 0) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to lock file.\n"));
+ return ret;
+ }
+
+ return EOK;
+}