>From e35e886c7641e3b6ac2d42422093af2aad57bfbf Mon Sep 17 00:00:00 2001
From: Michal Zidek <mzidek@redhat.com>
Date: Wed, 31 Oct 2012 11:05:31 +0100
Subject: [PATCH 1/2] util: Added new file util_lock.c

---
 Makefile.am          |  3 +-
 src/util/util.h      |  4 +++
 src/util/util_lock.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 90 insertions(+), 1 deletion(-)
 create mode 100644 src/util/util_lock.c

diff --git a/Makefile.am b/Makefile.am
index 07dcbd2..3306bba 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 df57a3d..1b979e1 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -557,6 +557,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 0000000..aa0d73c
--- /dev/null
+++ b/src/util/util_lock.c
@@ -0,0 +1,84 @@
+/*
+    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;
+}
+
-- 
1.7.11.2

