0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek/*
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek SSSD
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek util_lock.c
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek Authors:
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek Michal Zidek <mzidek@redhat.com>
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek Copyright (C) 2012 Red Hat
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek This program is free software; you can redistribute it and/or modify
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek it under the terms of the GNU General Public License as published by
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek the Free Software Foundation; either version 3 of the License, or
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek (at your option) any later version.
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek This program is distributed in the hope that it will be useful,
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek but WITHOUT ANY WARRANTY; without even the implied warranty of
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek GNU General Public License for more details.
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek You should have received a copy of the GNU General Public License
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek along with this program. If not, see <http://www.gnu.org/licenses/>.
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek*/
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek#include <unistd.h>
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek#include <fcntl.h>
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek#include <errno.h>
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek#include "util/util.h"
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidekerrno_t sss_br_lock_file(int fd, size_t start, size_t len,
e9086c9178b06ff396b958dcc2a1e5baa0693f5cMichal Zidek int num_tries, useconds_t wait)
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek{
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek int ret;
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek struct flock lock;
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek int retries_left;
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek
e9086c9178b06ff396b958dcc2a1e5baa0693f5cMichal Zidek if (num_tries <= 0) {
e9086c9178b06ff396b958dcc2a1e5baa0693f5cMichal Zidek return EINVAL;
e9086c9178b06ff396b958dcc2a1e5baa0693f5cMichal Zidek }
e9086c9178b06ff396b958dcc2a1e5baa0693f5cMichal Zidek
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek lock.l_type = F_WRLCK;
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek lock.l_whence = SEEK_SET;
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek lock.l_start = start;
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek lock.l_len = len;
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek lock.l_pid = 0;
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek
e9086c9178b06ff396b958dcc2a1e5baa0693f5cMichal Zidek for (retries_left = num_tries; retries_left > 0; retries_left--) {
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek ret = fcntl(fd, F_SETLK, &lock);
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek if (ret == -1) {
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek ret = errno;
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek if (ret == EACCES || ret == EAGAIN || ret == EINTR) {
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek DEBUG(SSSDBG_TRACE_FUNC,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "Failed to lock file. Retries left: %d\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov retries_left - 1);
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek if ((ret == EACCES || ret == EAGAIN) && (retries_left <= 1)) {
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek /* File is locked by someone else. Return EACCESS
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek * if this is the last try. */
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek return EACCES;
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek }
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek if (retries_left - 1 > 0) {
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek ret = usleep(wait);
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek if (ret == -1) {
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek DEBUG(SSSDBG_MINOR_FAILURE,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "usleep() failed -> ignoring\n");
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek }
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek }
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek } else {
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek /* Error occurred */
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek DEBUG(SSSDBG_CRIT_FAILURE,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "Unable to lock file.\n");
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek return ret;
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek }
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek } else if (ret == 0) {
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek /* File successfuly locked */
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek break;
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek }
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek }
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek if (retries_left == 0) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Unable to lock file.\n");
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek return ret;
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek }
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek return EOK;
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek}