ulockmgr: strip ulockmgr support from this source package
authorMiklos Szeredi <mszeredi@suse.cz>
Thu, 25 Jul 2013 15:58:48 +0000 (17:58 +0200)
committerMiklos Szeredi <mszeredi@suse.cz>
Thu, 25 Jul 2013 15:58:48 +0000 (17:58 +0200)
Distribute ulockmgr separately.  It is not needed for the building of
libfuse, only fusexmp_fh.  Check ulockmgr library in ./configure and if not
disable remote-lock suport in fusexmp_fh.

13 files changed:
ChangeLog
configure.ac
doc/Makefile.am
doc/ulockmgr_server.1 [deleted file]
example/Makefile.am
example/fusexmp_fh.c
include/Makefile.am
include/ulockmgr.h [deleted file]
lib/Makefile.am
lib/ulockmgr.c [deleted file]
util/.gitignore
util/Makefile.am
util/ulockmgr_server.c [deleted file]

index 616e02ffd19c75436efba74cede89d07c489e6a7..6b8c257969d9cff2da5e12e01eb00baac793b9ed 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,6 +5,11 @@
        libfuse3.*.  Invoke pkg-config with "fuse3" as the first argument
        to build with version 3 of the library.
 
+       * ulockmgr: strip ulockmgr support from this source package and
+       distribute it separately.  It is not needed for the building of
+       libfuse, only fusexmp_fh.  Check ulockmgr library in ./configure
+       and if not disable remote-lock suport in fusexmp_fh.
+
 2013-07-24  Miklos Szeredi <miklos@szeredi.hu>
 
        * libfuse: remove "-D_FILE_OFFSET_BITS=64" from fuse.pc, add
index d542526028d6559b652b75fed4749e70de0753e8..0e621d43dbfc94134de91ccfd6fa331302c8ea7e 100644 (file)
@@ -63,6 +63,11 @@ AC_SEARCH_LIBS(dlopen, [dl])
 AC_SEARCH_LIBS(clock_gettime, [rt])
 libfuse_libs=$LIBS
 LIBS=
+AC_CHECK_LIB(ulockmgr, ulockmgr_op)
+fusexmp_fh_libs=$LIBS
+AC_SUBST(fusexmp_fh_libs)
+LIBS=
+
 AC_ARG_WITH([libiconv-prefix],
 [  --with-libiconv-prefix=DIR  search for libiconv in DIR/include and DIR/lib], [
     for dir in `echo "$withval" | tr : ' '`; do
index ebc96793bfc1a8529bb94bb1ba49f878d2979454..bc34a9c4923069dbf1e843833e811211c20c0116 100644 (file)
@@ -1,5 +1,5 @@
 ## Process this file with automake to produce Makefile.in
 
-dist_man_MANS = fusermount.1 mount.fuse.8 ulockmgr_server.1
+dist_man_MANS = fusermount.1 mount.fuse.8
 
 EXTRA_DIST = how-fuse-works kernel.txt Doxyfile
diff --git a/doc/ulockmgr_server.1 b/doc/ulockmgr_server.1
deleted file mode 100644 (file)
index 7b8ab9a..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-.TH ULOCKMGR_SERVER 1 2011\-10\-23 2.8.6 "Filesystem in Userspace (FUSE)"
-
-.SH NAME
-\fBulockmgr_server\fR \- Lock Manager Server for FUSE filesystems
-
-.SH SYNOPSIS
-\fBulockmgr_server\fR
-
-.SH DESCRIPTION
-Filesystem in Userspace (FUSE) is a simple interface for userspace programs to export a virtual filesystem to the Linux kernel. It also aims to provide a secure method for non privileged users to create and mount their own filesystem implementations.
-.PP
-\fBulockmgr_server\fR is the Userspace Lock Manager Server for FUSE filesystems.
-
-.SH OPTIONS
-\fBulockmgr_server\fR has no options.
-
-.SH SEE ALSO
-\fIfusermount\fR(1),
-\fImount\fR(8),
-\fImount.fuse\fR(8).
-
-.SH HOMEPAGE
-More information about ulockmgr_server and the FUSE project can be found at <\fIhttp://fuse.sourceforge.net/\fR>.
-
-.SH AUTHOR
-FUSE was written by Miklos Szeredi <\fImiklos@szeredi.hu\fR>.
-.PP
-This manual page was written by Daniel Baumann <\fIdaniel.baumann@progress\-technologies.net\fR>.
index 8b123d2875f5c28a9ef48ef17fa6486ac5a7f2be..0db537b8daa848c7fb130b2f936e9f62a914f6e1 100644 (file)
@@ -6,7 +6,7 @@ noinst_PROGRAMS = fusexmp fusexmp_fh null hello hello_ll fioc fioclient \
                  fsel fselclient cusexmp
 
 LDADD = ../lib/libfuse3.la
-fusexmp_fh_LDADD = ../lib/libfuse3.la ../lib/libulockmgr.la
+fusexmp_fh_LDADD = ../lib/libfuse3.la @fusexmp_fh_libs@
 
 fioclient_CPPFLAGS =
 fioclient_LDFLAGS =
index 3be5071a82bca28625bc7acd1e2028a9a75bec72..ba6789bc6ff32c362d9cd031f01aee64ac515395 100755 (executable)
 #define _GNU_SOURCE
 
 #include <fuse.h>
+
+#ifdef HAVE_LIBULOCKMGR
 #include <ulockmgr.h>
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -500,6 +504,7 @@ static int xmp_removexattr(const char *path, const char *name)
 }
 #endif /* HAVE_SETXATTR */
 
+#ifdef HAVE_LIBULOCKMGR
 static int xmp_lock(const char *path, struct fuse_file_info *fi, int cmd,
                    struct flock *lock)
 {
@@ -508,6 +513,7 @@ static int xmp_lock(const char *path, struct fuse_file_info *fi, int cmd,
        return ulockmgr_op(fi->fh, cmd, lock, &fi->lock_owner,
                           sizeof(fi->lock_owner));
 }
+#endif
 
 static int xmp_flock(const char *path, struct fuse_file_info *fi, int op)
 {
@@ -562,7 +568,9 @@ static struct fuse_operations xmp_oper = {
        .listxattr      = xmp_listxattr,
        .removexattr    = xmp_removexattr,
 #endif
+#ifdef HAVE_LIBULOCKMGR
        .lock           = xmp_lock,
+#endif
        .flock          = xmp_flock,
 };
 
index bfe91e4d9e75b4e4a1bccc76c057bfee217a59d1..ffbfafa95418beaaddc962dcce05891a5ebbf29d 100644 (file)
@@ -9,6 +9,4 @@ fuseinclude_HEADERS = \
        fuse_opt.h              \
        cuse_lowlevel.h
 
-include_HEADERS = ulockmgr.h
-
 noinst_HEADERS = fuse_kernel.h
diff --git a/include/ulockmgr.h b/include/ulockmgr.h
deleted file mode 100644 (file)
index ad55579..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-  libulockmgr: Userspace Lock Manager Library
-  Copyright (C) 2006  Miklos Szeredi <miklos@szeredi.hu>
-
-  This program can be distributed under the terms of the GNU LGPLv2.
-  See the file COPYING.LIB.
-*/
-
-#include <stdint.h>
-#include <fcntl.h>
-#include <sys/types.h>
-
-/**
- * Perform POSIX locking operation
- *
- * @param fd the file descriptor
- * @param cmd the locking command (F_GETFL, F_SETLK or F_SETLKW)
- * @param lock the lock parameters
- * @param owner the lock owner ID cookie
- * @param owner_len length of the lock owner ID cookie
- * @return 0 on success -errno on error
- */
-int ulockmgr_op(int fd, int cmd, struct flock *lock, const void *owner,
-               size_t owner_len);
index eab93820c5c3a46b20c9c6968584cac69fb33d88..2ad0f159b710a0d950ac22807a82facea738af13 100644 (file)
@@ -3,7 +3,7 @@
 AM_CPPFLAGS = -I$(top_srcdir)/include -DFUSERMOUNT_DIR=\"$(bindir)\" \
  -D_REENTRANT -DFUSE_USE_VERSION=30
 
-lib_LTLIBRARIES = libfuse3.la libulockmgr.la
+lib_LTLIBRARIES = libfuse3.la
 
 if BSD
 mount_source = mount_bsd.c
@@ -42,7 +42,4 @@ if NETBSD
 libfuse3_la_LIBADD = -lperfuse -lpuffs
 endif
 
-libulockmgr_la_SOURCES = ulockmgr.c
-libulockmgr_la_LDFLAGS = -pthread -version-number 1:0:1
-
 EXTRA_DIST = fuse_versionscript
diff --git a/lib/ulockmgr.c b/lib/ulockmgr.c
deleted file mode 100644 (file)
index 78f6859..0000000
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
-  libulockmgr: Userspace Lock Manager Library
-  Copyright (C) 2006  Miklos Szeredi <miklos@szeredi.hu>
-
-  This program can be distributed under the terms of the GNU LGPLv2.
-  See the file COPYING.LIB
-*/
-
-/* #define DEBUG 1 */
-
-#include "config.h"
-#include "ulockmgr.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <pthread.h>
-#include <errno.h>
-#include <assert.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-
-struct message {
-       unsigned intr : 1;
-       unsigned nofd : 1;
-       pthread_t thr;
-       int cmd;
-       int fd;
-       struct flock lock;
-       int error;
-};
-
-struct fd_store {
-       struct fd_store *next;
-       int fd;
-       int inuse;
-};
-
-struct owner {
-       struct owner *next;
-       struct owner *prev;
-       struct fd_store *fds;
-       void *id;
-       size_t id_len;
-       int cfd;
-};
-
-static pthread_mutex_t ulockmgr_lock;
-static int ulockmgr_cfd = -1;
-static struct owner owner_list = { .next = &owner_list, .prev = &owner_list };
-
-#define MAX_SEND_FDS 2
-
-static void list_del_owner(struct owner *owner)
-{
-       struct owner *prev = owner->prev;
-       struct owner *next = owner->next;
-       prev->next = next;
-       next->prev = prev;
-}
-
-static void list_add_owner(struct owner *owner, struct owner *next)
-{
-       struct owner *prev = next->prev;
-       owner->next = next;
-       owner->prev = prev;
-       prev->next = owner;
-       next->prev = owner;
-}
-
-/*
- * There's a bug in the linux kernel (< 2.6.22) recv() implementation
- * on AF_UNIX, SOCK_STREAM sockets, that could cause it to return
- * zero, even if data was available.  Retrying the recv will return
- * the data in this case.
- */
-static int do_recv(int sock, void *buf, size_t len, int flags)
-{
-       int res = recv(sock, buf, len, flags);
-       if (res == 0)
-               res = recv(sock, buf, len, flags);
-
-       return res;
-}
-
-static int ulockmgr_send_message(int sock, void *buf, size_t buflen,
-                                int *fdp, int numfds)
-{
-       struct msghdr msg;
-       struct cmsghdr *p_cmsg;
-       struct iovec vec;
-       size_t cmsgbuf[CMSG_SPACE(sizeof(int) * MAX_SEND_FDS) / sizeof(size_t)];
-       int res;
-
-       assert(numfds <= MAX_SEND_FDS);
-       msg.msg_control = cmsgbuf;
-       msg.msg_controllen = sizeof(cmsgbuf);
-       p_cmsg = CMSG_FIRSTHDR(&msg);
-       p_cmsg->cmsg_level = SOL_SOCKET;
-       p_cmsg->cmsg_type = SCM_RIGHTS;
-       p_cmsg->cmsg_len = CMSG_LEN(sizeof(int) * numfds);
-       memcpy(CMSG_DATA(p_cmsg), fdp, sizeof(int) * numfds);
-       msg.msg_controllen = p_cmsg->cmsg_len;
-       msg.msg_name = NULL;
-       msg.msg_namelen = 0;
-       msg.msg_iov = &vec;
-       msg.msg_iovlen = 1;
-       msg.msg_flags = 0;
-       vec.iov_base = buf;
-       vec.iov_len = buflen;
-       res = sendmsg(sock, &msg, MSG_NOSIGNAL);
-       if (res == -1) {
-               perror("libulockmgr: sendmsg");
-               return -1;
-       }
-       if ((size_t) res != buflen) {
-               fprintf(stderr, "libulockmgr: sendmsg short\n");
-               return -1;
-       }
-       return 0;
-}
-
-static int ulockmgr_start_daemon(void)
-{
-       int sv[2];
-       int res;
-       char tmp[64];
-
-       res = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
-       if (res == -1) {
-               perror("libulockmgr: socketpair");
-               return -1;
-       }
-       snprintf(tmp, sizeof(tmp), "exec ulockmgr_server %i", sv[0]);
-       res = system(tmp);
-       close(sv[0]);
-       if (res == -1 || !WIFEXITED(res) || WEXITSTATUS(res) != 0) {
-               close(sv[1]);
-               return -1;
-       }
-       ulockmgr_cfd = sv[1];
-       return 0;
-}
-
-static struct owner *ulockmgr_new_owner(const void *id, size_t id_len)
-{
-       int sv[2];
-       int res;
-       char c = 'm';
-       struct owner *o;
-
-       if (ulockmgr_cfd == -1 && ulockmgr_start_daemon() == -1)
-               return NULL;
-
-       o = calloc(1, sizeof(struct owner) + id_len);
-       if (!o) {
-               fprintf(stderr, "libulockmgr: failed to allocate memory\n");
-               return NULL;
-       }
-       o->id = o + 1;
-       o->id_len = id_len;
-       res = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
-       if (res == -1) {
-               perror("libulockmgr: socketpair");
-               goto out_free;
-       }
-       res = ulockmgr_send_message(ulockmgr_cfd, &c, sizeof(c), &sv[0], 1);
-       close(sv[0]);
-       if (res == -1) {
-               close(ulockmgr_cfd);
-               ulockmgr_cfd = -1;
-               goto out_close;
-       }
-
-       o->cfd = sv[1];
-       memcpy(o->id, id, id_len);
-       list_add_owner(o, &owner_list);
-
-       return o;
-
-out_close:
-       close(sv[1]);
-out_free:
-       free(o);
-       return NULL;
-}
-
-static int ulockmgr_send_request(struct message *msg, const void *id,
-                                size_t id_len)
-{
-       int sv[2];
-       int cfd;
-       struct owner *o;
-       struct fd_store *f = NULL;
-       struct fd_store *newf = NULL;
-       struct fd_store **fp;
-       int fd = msg->fd;
-       int cmd = msg->cmd;
-       int res;
-       int unlockall = (cmd == F_SETLK && msg->lock.l_type == F_UNLCK &&
-                        msg->lock.l_start == 0 && msg->lock.l_len == 0);
-
-       for (o = owner_list.next; o != &owner_list; o = o->next)
-               if (o->id_len == id_len && memcmp(o->id, id, id_len) == 0)
-                       break;
-
-       if (o == &owner_list)
-               o = NULL;
-
-       if (!o && cmd != F_GETLK && msg->lock.l_type != F_UNLCK)
-               o = ulockmgr_new_owner(id, id_len);
-
-       if (!o) {
-               if (cmd == F_GETLK) {
-                       res = fcntl(msg->fd, F_GETLK, &msg->lock);
-                       return (res == -1) ? -errno : 0;
-               } else if (msg->lock.l_type == F_UNLCK)
-                       return 0;
-               else
-                       return -ENOLCK;
-       }
-
-       if (unlockall)
-               msg->nofd = 1;
-       else {
-               for (fp = &o->fds; *fp; fp = &(*fp)->next) {
-                       f = *fp;
-                       if (f->fd == fd) {
-                               msg->nofd = 1;
-                               break;
-                       }
-               }
-       }
-
-       if (!msg->nofd) {
-               newf = f = calloc(1, sizeof(struct fd_store));
-               if (!f) {
-                       fprintf(stderr, "libulockmgr: failed to allocate memory\n");
-                       return -ENOLCK;
-               }
-       }
-
-       res = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
-       if (res == -1) {
-               perror("libulockmgr: socketpair");
-               free(newf);
-               return -ENOLCK;
-       }
-
-       cfd = sv[1];
-       sv[1] = msg->fd;
-       res = ulockmgr_send_message(o->cfd, msg, sizeof(struct message), sv,
-                                   msg->nofd ? 1 : 2);
-       close(sv[0]);
-       if (res == -1) {
-               free(newf);
-               close(cfd);
-               return -EIO;
-       }
-
-       if (newf) {
-               newf->fd = msg->fd;
-               newf->next = o->fds;
-               o->fds = newf;
-       }
-       if (f)
-               f->inuse++;
-
-       res = do_recv(cfd, msg, sizeof(struct message), MSG_WAITALL);
-       if (res == -1) {
-               perror("libulockmgr: recv");
-               msg->error = EIO;
-       } else if (res != sizeof(struct message)) {
-               fprintf(stderr, "libulockmgr: recv short\n");
-               msg->error = EIO;
-       } else if (cmd == F_SETLKW && msg->error == EAGAIN) {
-               pthread_mutex_unlock(&ulockmgr_lock);
-               while (1) {
-                       sigset_t old;
-                       sigset_t unblock;
-                       int errno_save;
-
-                       sigemptyset(&unblock);
-                       sigaddset(&unblock, SIGUSR1);
-                       pthread_sigmask(SIG_UNBLOCK, &unblock, &old);
-                       res = do_recv(cfd, msg, sizeof(struct message),
-                                     MSG_WAITALL);
-                       errno_save = errno;
-                       pthread_sigmask(SIG_SETMASK, &old, NULL);
-                       if (res == sizeof(struct message))
-                               break;
-                       else if (res >= 0) {
-                               fprintf(stderr, "libulockmgr: recv short\n");
-                               msg->error = EIO;
-                               break;
-                       } else if (errno_save != EINTR) {
-                               errno = errno_save;
-                               perror("libulockmgr: recv");
-                               msg->error = EIO;
-                               break;
-                       }
-                       msg->intr = 1;
-                       res = send(o->cfd, msg, sizeof(struct message),
-                                  MSG_NOSIGNAL);
-                       if (res == -1) {
-                               perror("libulockmgr: send");
-                               msg->error = EIO;
-                               break;
-                       }
-                       if (res != sizeof(struct message)) {
-                               fprintf(stderr, "libulockmgr: send short\n");
-                               msg->error = EIO;
-                               break;
-                       }
-               }
-               pthread_mutex_lock(&ulockmgr_lock);
-
-       }
-       if (f)
-               f->inuse--;
-       close(cfd);
-       if (unlockall) {
-               for (fp = &o->fds; *fp;) {
-                       f = *fp;
-                       if (f->fd == fd && !f->inuse) {
-                               *fp = f->next;
-                               free(f);
-                       } else
-                               fp = &f->next;
-               }
-               if (!o->fds) {
-                       list_del_owner(o);
-                       close(o->cfd);
-                       free(o);
-               }
-               /* Force OK on unlock-all, since it _will_ succeed once the
-                  owner is deleted */
-               msg->error = 0;
-       }
-
-       return -msg->error;
-}
-
-#ifdef DEBUG
-static uint32_t owner_hash(const unsigned char *id, size_t id_len)
-{
-       uint32_t h = 0;
-       size_t i;
-       for (i = 0; i < id_len; i++)
-               h = ((h << 8) | (h >> 24)) ^ id[i];
-
-       return h;
-}
-#endif
-
-static int ulockmgr_canonicalize(int fd, struct flock *lock)
-{
-       off_t offset;
-       if (lock->l_whence == SEEK_CUR) {
-               offset = lseek(fd, 0, SEEK_CUR);
-               if (offset == (off_t) -1)
-                       return -errno;
-       } else if (lock->l_whence == SEEK_END) {
-               struct stat stbuf;
-               int res = fstat(fd, &stbuf);
-               if (res == -1)
-                       return -errno;
-
-               offset = stbuf.st_size;
-       } else
-               offset = 0;
-
-       lock->l_whence = SEEK_SET;
-       lock->l_start += offset;
-
-       if (lock->l_start < 0)
-               return -EINVAL;
-
-       if (lock->l_len < 0) {
-               lock->l_start += lock->l_len;
-               if (lock->l_start < 0)
-                       return -EINVAL;
-               lock->l_len = -lock->l_len;
-       }
-       if (lock->l_len && lock->l_start + lock->l_len - 1 < 0)
-               return -EINVAL;
-
-       return 0;
-}
-
-int ulockmgr_op(int fd, int cmd, struct flock *lock, const void *owner,
-               size_t owner_len)
-{
-       int err;
-       struct message msg;
-       sigset_t old;
-       sigset_t block;
-
-       if (cmd != F_GETLK && cmd != F_SETLK && cmd != F_SETLKW)
-               return -EINVAL;
-
-       if (lock->l_type != F_RDLCK && lock->l_type != F_WRLCK &&
-           lock->l_type != F_UNLCK)
-               return -EINVAL;
-
-       if (lock->l_whence != SEEK_SET && lock->l_whence != SEEK_CUR &&
-           lock->l_whence != SEEK_END)
-               return -EINVAL;
-
-#ifdef DEBUG
-       fprintf(stderr, "libulockmgr: %i %i %i %lli %lli own: 0x%08x\n",
-               cmd, lock->l_type, lock->l_whence, lock->l_start, lock->l_len,
-               owner_hash(owner, owner_len));
-#endif
-
-       /* Unlock should never block anyway */
-       if (cmd == F_SETLKW && lock->l_type == F_UNLCK)
-               cmd = F_SETLK;
-
-       memset(&msg, 0, sizeof(struct message));
-       msg.cmd = cmd;
-       msg.fd = fd;
-       msg.lock = *lock;
-       err = ulockmgr_canonicalize(fd, &msg.lock);
-       if (err)
-               return err;
-
-       sigemptyset(&block);
-       sigaddset(&block, SIGUSR1);
-       pthread_sigmask(SIG_BLOCK, &block, &old);
-       pthread_mutex_lock(&ulockmgr_lock);
-       err = ulockmgr_send_request(&msg, owner, owner_len);
-       pthread_mutex_unlock(&ulockmgr_lock);
-       pthread_sigmask(SIG_SETMASK, &old, NULL);
-       if (!err && cmd == F_GETLK) {
-               if (msg.lock.l_type == F_UNLCK)
-                       lock->l_type = F_UNLCK;
-               else
-                       *lock = msg.lock;
-       }
-
-       return err;
-}
index 4a58d8e853103f9a865e905022feedea23c64059..961b59b9222362a1bf7df331ee95bbd01e66c8ce 100644 (file)
@@ -1,5 +1,4 @@
 fusermount
-ulockmgr_server
 fuse_ioslave
 mount.fuse
 mount_util.c
index e77782b09ce6ec337bb9f62842b9ffe8ea9215e2..a489d28e6728e008e55c00c7f826d0bbfe859450 100644 (file)
@@ -1,6 +1,6 @@
 ## Process this file with automake to produce Makefile.in
 
-bin_PROGRAMS = fusermount ulockmgr_server
+bin_PROGRAMS = fusermount
 noinst_PROGRAMS = mount.fuse
 
 # we re-use mount_util.c from the library, but do want to keep ourself
@@ -15,10 +15,6 @@ mount_util.c: $(top_srcdir)/lib/mount_util.c
 
 mount_fuse_SOURCES = mount.fuse.c
 
-ulockmgr_server_SOURCES = ulockmgr_server.c
-ulockmgr_server_CPPFLAGS = -D_REENTRANT 
-ulockmgr_server_LDFLAGS = -pthread
-
 install-exec-hook:
        -chmod u+s $(DESTDIR)$(bindir)/fusermount
        @if test ! -e $(DESTDIR)/dev/fuse; then \
diff --git a/util/ulockmgr_server.c b/util/ulockmgr_server.c
deleted file mode 100644 (file)
index 09972ce..0000000
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
-  ulockmgr_server: Userspace Lock Manager Server
-  Copyright (C) 2006  Miklos Szeredi <miklos@szeredi.hu>
-
-  This program can be distributed under the terms of the GNU GPL.
-  See the file COPYING.
-*/
-
-/* #define DEBUG 1 */
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <pthread.h>
-#include <stdint.h>
-#include <errno.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-
-struct message {
-       unsigned intr : 1;
-       unsigned nofd : 1;
-       pthread_t thr;
-       int cmd;
-       int fd;
-       struct flock lock;
-       int error;
-};
-
-struct fd_store {
-       struct fd_store *next;
-       int fd;
-       int origfd;
-       int inuse;
-};
-
-struct owner {
-       struct fd_store *fds;
-       pthread_mutex_t lock;
-};
-
-struct req_data {
-       struct owner *o;
-       int cfd;
-       struct fd_store *f;
-       struct message msg;
-};
-
-#define MAX_SEND_FDS 2
-
-static int receive_message(int sock, void *buf, size_t buflen, int *fdp,
-                          int *numfds)
-{
-       struct msghdr msg;
-       struct iovec iov;
-       size_t ccmsg[CMSG_SPACE(sizeof(int) * MAX_SEND_FDS) / sizeof(size_t)];
-       struct cmsghdr *cmsg;
-       int res;
-       int i;
-
-       assert(*numfds <= MAX_SEND_FDS);
-       iov.iov_base = buf;
-       iov.iov_len = buflen;
-
-       memset(&msg, 0, sizeof(msg));
-       memset(ccmsg, -1, sizeof(ccmsg));
-       msg.msg_iov = &iov;
-       msg.msg_iovlen = 1;
-       msg.msg_control = ccmsg;
-       msg.msg_controllen = sizeof(ccmsg);
-
-       res = recvmsg(sock, &msg, MSG_WAITALL);
-       if (!res) {
-               /* retry on zero return, see do_recv() in ulockmgr.c */
-               res = recvmsg(sock, &msg, MSG_WAITALL);
-               if (!res)
-                       return 0;
-       }
-       if (res == -1) {
-               perror("ulockmgr_server: recvmsg");
-               return -1;
-       }
-       if ((size_t) res != buflen) {
-               fprintf(stderr, "ulockmgr_server: short message received\n");
-               return -1;
-       }
-
-       cmsg = CMSG_FIRSTHDR(&msg);
-       if (cmsg) {
-               if (!cmsg->cmsg_type == SCM_RIGHTS) {
-                       fprintf(stderr,
-                               "ulockmgr_server: unknown control message %d\n",
-                               cmsg->cmsg_type);
-                       return -1;
-               }
-               memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds);
-               if (msg.msg_flags & MSG_CTRUNC) {
-                       fprintf(stderr,
-                               "ulockmgr_server: control message truncated\n");
-                       for (i = 0; i < *numfds; i++)
-                               close(fdp[i]);
-                       *numfds = 0;
-               }
-       } else {
-               if (msg.msg_flags & MSG_CTRUNC) {
-                       fprintf(stderr,
-                               "ulockmgr_server: control message truncated(*)\n");
-
-                       /* There's a bug in the Linux kernel, that if
-                          not all file descriptors were allocated,
-                          then the cmsg header is not filled in */
-                       cmsg = (struct cmsghdr *) ccmsg;
-                       memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds);
-                       for (i = 0; i < *numfds; i++)
-                               close(fdp[i]);
-               }
-               *numfds = 0;
-       }
-       return res;
-}
-
-static int closefrom(int minfd)
-{
-       DIR *dir = opendir("/proc/self/fd");
-       if (dir) {
-               int dfd = dirfd(dir);
-               struct dirent *ent;
-               while ((ent = readdir(dir))) {
-                       char *end;
-                       int fd = strtol(ent->d_name, &end, 10);
-                       if (ent->d_name[0] && !end[0] && fd >= minfd &&
-                           fd != dfd)
-                               close(fd);
-               }
-               closedir(dir);
-       }
-       return 0;
-}
-
-static void send_reply(int cfd, struct message *msg)
-{
-       int res = send(cfd, msg, sizeof(struct message), MSG_NOSIGNAL);
-       if (res == -1)
-               perror("ulockmgr_server: sending reply");
-#ifdef DEBUG
-       fprintf(stderr, "ulockmgr_server: error: %i\n", msg->error);
-#endif
-}
-
-static void *process_request(void *d_)
-{
-       struct req_data *d = d_;
-       int res;
-
-       assert(d->msg.cmd == F_SETLKW);
-       res = fcntl(d->f->fd, F_SETLK, &d->msg.lock);
-       if (res == -1 && errno == EAGAIN) {
-               d->msg.error = EAGAIN;
-               d->msg.thr = pthread_self();
-               send_reply(d->cfd, &d->msg);
-               res = fcntl(d->f->fd, F_SETLKW, &d->msg.lock);
-       }
-       d->msg.error = (res == -1) ? errno : 0;
-       pthread_mutex_lock(&d->o->lock);
-       d->f->inuse--;
-       pthread_mutex_unlock(&d->o->lock);
-       send_reply(d->cfd, &d->msg);
-       close(d->cfd);
-       free(d);
-
-       return NULL;
-}
-
-static void process_message(struct owner *o, struct message *msg, int cfd,
-                           int fd)
-{
-       struct fd_store *f = NULL;
-       struct fd_store *newf = NULL;
-       struct fd_store **fp;
-       struct req_data *d;
-       pthread_t tid;
-       int res;
-
-#ifdef DEBUG
-       fprintf(stderr, "ulockmgr_server: %i %i %i %lli %lli\n",
-               msg->cmd, msg->lock.l_type, msg->lock.l_whence,
-               msg->lock.l_start, msg->lock.l_len);
-#endif
-
-       if (msg->cmd == F_SETLK  && msg->lock.l_type == F_UNLCK &&
-           msg->lock.l_start == 0 && msg->lock.l_len == 0) {
-               for (fp = &o->fds; *fp;) {
-                       f = *fp;
-                       if (f->origfd == msg->fd && !f->inuse) {
-                               close(f->fd);
-                               *fp = f->next;
-                               free(f);
-                       } else
-                               fp = &f->next;
-               }
-               if (!msg->nofd)
-                       close(fd);
-
-               msg->error = 0;
-               send_reply(cfd, msg);
-               close(cfd);
-               return;
-       }
-
-       if (msg->nofd) {
-               for (fp = &o->fds; *fp; fp = &(*fp)->next) {
-                       f = *fp;
-                       if (f->origfd == msg->fd)
-                               break;
-               }
-               if (!*fp) {
-                       fprintf(stderr, "ulockmgr_server: fd %i not found\n",
-                               msg->fd);
-                       msg->error = EIO;
-                       send_reply(cfd, msg);
-                       close(cfd);
-                       return;
-               }
-       } else {
-               newf = f = malloc(sizeof(struct fd_store));
-               if (!f) {
-                       msg->error = ENOLCK;
-                       send_reply(cfd, msg);
-                       close(cfd);
-                       return;
-               }
-
-               f->fd = fd;
-               f->origfd = msg->fd;
-               f->inuse = 0;
-       }
-
-       if (msg->cmd == F_GETLK || msg->cmd == F_SETLK ||
-           msg->lock.l_type == F_UNLCK) {
-               res = fcntl(f->fd, msg->cmd, &msg->lock);
-               msg->error = (res == -1) ? errno : 0;
-               send_reply(cfd, msg);
-               close(cfd);
-               if (newf) {
-                       newf->next = o->fds;
-                       o->fds = newf;
-               }
-               return;
-       }
-
-       d = malloc(sizeof(struct req_data));
-       if (!d) {
-               msg->error = ENOLCK;
-               send_reply(cfd, msg);
-               close(cfd);
-               free(newf);
-               return;
-       }
-
-       f->inuse++;
-       d->o = o;
-       d->cfd = cfd;
-       d->f = f;
-       d->msg = *msg;
-       res = pthread_create(&tid, NULL, process_request, d);
-       if (res) {
-               msg->error = ENOLCK;
-               send_reply(cfd, msg);
-               close(cfd);
-               free(d);
-               f->inuse--;
-               free(newf);
-               return;
-       }
-
-       if (newf) {
-               newf->next = o->fds;
-               o->fds = newf;
-       }
-       pthread_detach(tid);
-}
-
-static void sigusr1_handler(int sig)
-{
-       (void) sig;
-       /* Nothing to do */
-}
-
-static void process_owner(int cfd)
-{
-       struct owner o;
-       struct sigaction sa;
-
-       memset(&sa, 0, sizeof(struct sigaction));
-       sa.sa_handler = sigusr1_handler;
-       sigemptyset(&sa.sa_mask);
-
-       if (sigaction(SIGUSR1, &sa, NULL) == -1) {
-               perror("ulockmgr_server: cannot set sigusr1 signal handler");
-               exit(1);
-       }
-
-       memset(&o, 0, sizeof(struct owner));
-       pthread_mutex_init(&o.lock, NULL);
-       while (1) {
-               struct message msg;
-               int rfds[2];
-               int res;
-               int numfds = 2;
-
-               res  = receive_message(cfd, &msg, sizeof(msg), rfds, &numfds);
-               if (!res)
-                       break;
-               if (res == -1)
-                       exit(1);
-
-               if (msg.intr) {
-                       if (numfds != 0)
-                               fprintf(stderr,
-                                       "ulockmgr_server: too many fds for intr\n");
-                       pthread_kill(msg.thr, SIGUSR1);
-               } else {
-                       if (numfds != 2)
-                               continue;
-
-                       pthread_mutex_lock(&o.lock);
-                       process_message(&o, &msg, rfds[0], rfds[1]);
-                       pthread_mutex_unlock(&o.lock);
-               }
-       }
-       if (o.fds)
-               fprintf(stderr,
-                       "ulockmgr_server: open file descriptors on exit\n");
-}
-
-int main(int argc, char *argv[])
-{
-       int nullfd;
-       char *end;
-       int cfd;
-       sigset_t empty;
-
-       if (argc != 2 || !argv[1][0])
-               goto out_inval;
-
-       cfd = strtol(argv[1], &end, 10);
-       if (*end)
-               goto out_inval;
-
-       /* demonize current process */
-       switch(fork()) {
-       case -1:
-               perror("ulockmgr_server: fork");
-               exit(1);
-       case 0:
-               break;
-       default:
-               _exit(0);
-       }
-
-       if (setsid() == -1) {
-               perror("ulockmgr_server: setsid");
-               exit(1);
-       }
-
-       (void) chdir("/");
-
-       sigemptyset(&empty);
-       sigprocmask(SIG_SETMASK, &empty, NULL);
-
-       if (dup2(cfd, 4) == -1) {
-               perror("ulockmgr_server: dup2");
-               exit(1);
-       }
-       cfd = 4;
-       nullfd = open("/dev/null", O_RDWR);
-       if (nullfd >= 0) {
-               dup2(nullfd, 0);
-               dup2(nullfd, 1);
-       }
-       close(3);
-       closefrom(5);
-       while (1) {
-               char c;
-               int sock;
-               int pid;
-               int numfds = 1;
-               int res = receive_message(cfd, &c, sizeof(c), &sock, &numfds);
-               if (!res)
-                       break;
-               if (res == -1)
-                       exit(1);
-               assert(numfds == 1);
-
-               pid = fork();
-               if (pid == -1) {
-                       perror("ulockmgr_server: fork");
-                       close(sock);
-                       continue;
-               }
-               if (pid == 0) {
-                       close(cfd);
-                       pid = fork();
-                       if (pid == -1) {
-                               perror("ulockmgr_server: fork");
-                               _exit(1);
-                       }
-                       if (pid == 0)
-                               process_owner(sock);
-                       _exit(0);
-               }
-               waitpid(pid, NULL, 0);
-               close(sock);
-       }
-       return 0;
-
-out_inval:
-       fprintf(stderr, "%s should be started by libulockmgr\n", argv[0]);
-       return 1;
-}