libatalk/cnid/tdb/Makefile
libatalk/compat/Makefile
libatalk/dsi/Makefile
+ libatalk/locking/Makefile
libatalk/nbp/Makefile
libatalk/netddp/Makefile
libatalk/rpc/Makefile
#include <atalk/dsi.h>
#include <atalk/compat.h>
#include <atalk/util.h>
+#include <atalk/locking.h>
#include "globals.h"
#include "switch.h"
if (ad_open(adp, s_path->u_name, ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF, O_RDONLY, O_RDONLY) < 0) {
return AFPERR_DENYCONF;
}
- denyreadset = (getforkmode(adp, ADEID_DFORK, AD_FILELOCK_DENY_RD) != 0 ||
- getforkmode(adp, ADEID_RFORK, AD_FILELOCK_DENY_RD) != 0 );
+ denyreadset = (ad_testlock(adp, ADEID_DFORK, AD_FILELOCK_DENY_RD) != 0 ||
+ ad_testlock(adp, ADEID_RFORK, AD_FILELOCK_DENY_RD) != 0 );
if (denyreadset) {
retvalue = AFPERR_DENYCONF;
return getmetadata(vol, bitmap, &path, dir, buf, buflen, adp );
}
-/* ---------------------------- */
static off_t get_off_t(char **ibuf, int is64)
{
u_int32_t temp;
return ret;
}
-/* ---------------------- */
static int set_off_t(off_t offset, char *rbuf, int is64)
{
u_int32_t temp;
return ret;
}
-/* ------------------------
- */
static int is_neg(int is64, off_t val)
{
if (val < 0 || (sizeof(off_t) == 8 && !is64 && (val & 0x80000000U)))
return 0;
}
-/* -------------------------
- */
-static int setforkmode(struct adouble *adp, int eid, int ofrefnum, int what)
-{
- return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, what, 1, ofrefnum);
-}
-
-/* -------------------------
- */
-int getforkmode(struct adouble *adp, int eid, int what)
-{
- return ad_testlock(adp, eid, what);
-}
-
-/* -------------------------
- */
static int fork_setmode(struct adouble *adp, int eid, int access, int ofrefnum)
{
int ret;
int denywriteset;
if (! (access & (OPENACC_WR | OPENACC_RD | OPENACC_DWR | OPENACC_DRD))) {
- return setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_NONE);
+ return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_NONE, 1, ofrefnum);
}
if ((access & (OPENACC_RD | OPENACC_DRD))) {
- if ((readset = getforkmode(adp, eid, AD_FILELOCK_OPEN_RD)) <0)
+ if ((readset = ad_testlock(adp, eid, AD_FILELOCK_OPEN_RD)) <0)
return readset;
- if ((denyreadset = getforkmode(adp, eid, AD_FILELOCK_DENY_RD)) <0)
+ if ((denyreadset = ad_testlock(adp, eid, AD_FILELOCK_DENY_RD)) <0)
return denyreadset;
if ((access & OPENACC_RD) && denyreadset) {
* true
*/
if ((access & OPENACC_RD)) {
- ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_RD);
+ ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_RD, 1, ofrefnum);
if (ret)
return ret;
}
if ((access & OPENACC_DRD)) {
- ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_RD);
+ ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_DENY_RD, 1, ofrefnum);
if (ret)
return ret;
}
}
/* ------------same for writing -------------- */
if ((access & (OPENACC_WR | OPENACC_DWR))) {
- if ((writeset = getforkmode(adp, eid, AD_FILELOCK_OPEN_WR)) <0)
+ if ((writeset = ad_testlock(adp, eid, AD_FILELOCK_OPEN_WR)) <0)
return writeset;
- if ((denywriteset = getforkmode(adp, eid, AD_FILELOCK_DENY_WR)) <0)
+ if ((denywriteset = ad_testlock(adp, eid, AD_FILELOCK_DENY_WR)) <0)
return denywriteset;
if ((access & OPENACC_WR) && denywriteset) {
return -1;
}
if ((access & OPENACC_WR)) {
- ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_WR);
+ ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_WR, 1, ofrefnum);
if (ret)
return ret;
}
if ((access & OPENACC_DWR)) {
- ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_WR);
+ ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_DENY_WR, 1, ofrefnum);
if (ret)
return ret;
}
/* in fork.c */
extern int flushfork (struct ofork *);
-extern int getforkmode (struct adouble *, int , int );
/* FP functions */
int afp_openfork (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen);
/* Initialize */
cnid_init();
+ if (locktable_init() != 0)
+ afp_exit(EXITERR_SYS);
+#if 0
if (rpc_init("127.0.0.1", 4701) != 0)
afp_exit(EXITERR_SYS);
+#endif
/* watch atp, dsi sockets and ipc parent/child file descriptor. */
if ((ipc = server_ipc_create())) {
extern int ad_close (struct adouble *, int);
/* ad_lock.c */
-extern int ad_fcntl_lock (struct adouble *, const u_int32_t /*eid*/,
- const int /*type*/, const off_t /*offset*/,
- const off_t /*len*/, const int /*user*/);
-extern void ad_fcntl_unlock (struct adouble *, const int /*user*/);
-extern int ad_fcntl_tmplock (struct adouble *, const u_int32_t /*eid*/,
- const int /*type*/, const off_t /*offset*/,
- const off_t /*len*/, const int /*user*/);
-extern int ad_testlock (struct adouble * /*adp*/, int /*eid*/, off_t /*off*/);
-
-extern u_int16_t ad_openforks (struct adouble * /*adp*/, u_int16_t);
-extern int ad_excl_lock (struct adouble * /*adp*/, const u_int32_t /*eid*/);
-
-#if 0
-#define ad_lock ad_fcntl_lock
-#define ad_tmplock ad_fcntl_tmplock
-#define ad_unlock ad_fcntl_unlock
-#endif
-
-#define ad_lock rpc_lock
-#define ad_tmplock rpc_tmplock
-#define ad_unlock rpc_unlock
+extern int ad_testlock (struct adouble *adp, int eid, off_t off);
+extern uint16_t ad_openforks(struct adouble *adp, uint16_t);
+extern int ad_excl_lock (struct adouble *adp, uint32_t eid);
+extern int ad_lock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int user);
+extern void ad_unlock(struct adouble *, int user);
+extern int ad_tmplock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int user);
/* ad_open.c */
extern const char *oflags2logstr(int oflags);
/*
- * Copyright (c) 2010 Frank Lahm
+ * Copyright (c) 2011 Frank Lahm
* All Rights Reserved. See COPYRIGHT.
*/
#include <sys/types.h>
#include <inttypes.h>
-#include <atalk/lockrpc.gen.h>
-
-#include "event2/event.h"
-#include "event2/http.h"
-#include "event2/rpc.h"
-
-struct adouble;
-
-extern int rpc_init(const char *addr, unsigned short port);
-extern int rpc_lock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int user);
-extern void rpc_unlock(struct adouble *, int user);
-extern int rpc_tmplock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int user);
-
+extern int locktable_init(void);
#endif /* ATALK_LOCKING_H */
--- /dev/null
+/*
+ * Copyright (c) 2011 Frank Lahm
+ * All Rights Reserved. See COPYRIGHT.
+ */
+
+#ifndef ATALK_RPC_H
+#define ATALK_RPC_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <inttypes.h>
+
+#include <atalk/lockrpc.gen.h>
+
+#include "event2/event.h"
+#include "event2/http.h"
+#include "event2/rpc.h"
+
+struct adouble;
+extern int rpc_init(const char *addr, unsigned short port);
+extern int rpc_lock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int user);
+extern void rpc_unlock(struct adouble *, int user);
+extern int rpc_tmplock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int user);
+
+#endif /* ATALK_RPC_H */
# Makefile.am for libatalk/
# rpc should be first because it generates RPC headers included elsewhere
-SUBDIRS = rpc acl adouble bstring compat cnid dsi tdb util unicode vfs
+SUBDIRS = rpc acl adouble bstring compat cnid dsi locking tdb util unicode vfs
lib_LTLIBRARIES = libatalk.la
bstring/libbstring.la \
compat/libcompat.la \
dsi/libdsi.la \
+ locking/liblocking.la \
rpc/librpc.la \
tdb/libtdb.la \
unicode/libunicode.la \
bstring/libbstring.la \
compat/libcompat.la \
dsi/libdsi.la \
+ locking/liblocking.la \
rpc/librpc.la \
tdb/libtdb.la \
unicode/libunicode.la \
}
/* ------------------ */
-int ad_fcntl_lock(struct adouble *ad, const u_int32_t eid, const int locktype,
- const off_t off, const off_t len, const int fork)
+static int ad_fcntl_lock(struct adouble *ad, const u_int32_t eid, const int locktype,
+ const off_t off, const off_t len, const int fork)
{
#if 0
struct flock lock;
return 0;
}
+
+/* -------------------------
+*/
+static int ad_fcntl_tmplock(struct adouble *ad, const u_int32_t eid, const int locktype,
+ const off_t off, const off_t len, const int fork)
+{
+ struct flock lock;
+ struct ad_fd *adf;
+ int err;
+ int type;
+
+ lock.l_start = off;
+ type = locktype;
+ if (eid == ADEID_DFORK) {
+ adf = &ad->ad_data_fork;
+ } else {
+ /* FIXME META */
+ adf = &ad->ad_resource_fork;
+ if (adf->adf_fd == -1) {
+ /* there's no resource fork. return success */
+ return 0;
+ }
+ /* if ADLOCK_FILELOCK we want a lock from offset 0
+ * it's used when deleting a file:
+ * in open we put read locks on meta datas
+ * in delete a write locks on the whole file
+ * so if the file is open by somebody else it fails
+ */
+ if (!(type & ADLOCK_FILELOCK))
+ lock.l_start += ad_getentryoff(ad, eid);
+ }
+
+ if (!(adf->adf_flags & O_RDWR) && (type & ADLOCK_WR)) {
+ type = (type & ~ADLOCK_WR) | ADLOCK_RD;
+ }
+
+ lock.l_type = XLATE_FCNTL_LOCK(type & ADLOCK_MASK);
+ lock.l_whence = SEEK_SET;
+ lock.l_len = len;
+
+ /* see if it's locked by another fork. */
+ if (fork && adf_findxlock(adf, fork, ADLOCK_WR |
+ ((type & ADLOCK_WR) ? ADLOCK_RD : 0),
+ lock.l_start, lock.l_len) > -1) {
+ errno = EACCES;
+ return -1;
+ }
+
+ /* okay, we might have ranges byte-locked. we need to make sure that
+ * we restore the appropriate ranges once we're done. so, we check
+ * for overlap on an unlock and relock.
+ * XXX: in the future, all the byte locks will be sorted and contiguous.
+ * we just want to upgrade all the locks and then downgrade them
+ * here. */
+ if (!adf->adf_excl) {
+ err = set_lock(adf->adf_fd, F_SETLK, &lock);
+ }
+ else {
+ err = 0;
+ }
+ if (!err && (lock.l_type == F_UNLCK))
+ adf_relockrange(adf, adf->adf_fd, lock.l_start, len);
+
+ return err;
+}
+
+/* --------------------- */
+static void ad_fcntl_unlock(struct adouble *ad, const int fork)
+{
+ if (ad_data_fileno(ad) != -1) {
+ adf_unlock(&ad->ad_data_fork, fork);
+ }
+ if (ad_reso_fileno(ad) != -1) {
+ adf_unlock(&ad->ad_resource_fork, fork);
+ }
+
+ if (ad->ad_flags != AD_VERSION_EA) {
+ return;
+ }
+ if (ad_meta_fileno(ad) != -1) {
+ adf_unlock(&ad->ad_metadata_fork, fork);
+ }
+}
+
+/******************************************************************************
+ * Public functions
+ ******************************************************************************/
+
/* --------------- */
int ad_testlock(struct adouble *ad, int eid, const off_t off)
{
- there's no locks held by another process (clients)
- or we already know the answer and don't need to test.
*/
-u_int16_t ad_openforks(struct adouble *ad, u_int16_t attrbits)
+uint16_t ad_openforks(struct adouble *ad, u_int16_t attrbits)
{
return 0;
#if 0
#endif
}
-/* -------------------------
-*/
-int ad_fcntl_tmplock(struct adouble *ad, const u_int32_t eid, const int locktype,
- const off_t off, const off_t len, const int fork)
-{
- return 0;
-#if 0
- struct flock lock;
- struct ad_fd *adf;
- int err;
- int type;
-
- lock.l_start = off;
- type = locktype;
- if (eid == ADEID_DFORK) {
- adf = &ad->ad_data_fork;
- } else {
- /* FIXME META */
- adf = &ad->ad_resource_fork;
- if (adf->adf_fd == -1) {
- /* there's no resource fork. return success */
- return 0;
- }
- /* if ADLOCK_FILELOCK we want a lock from offset 0
- * it's used when deleting a file:
- * in open we put read locks on meta datas
- * in delete a write locks on the whole file
- * so if the file is open by somebody else it fails
- */
- if (!(type & ADLOCK_FILELOCK))
- lock.l_start += ad_getentryoff(ad, eid);
- }
-
- if (!(adf->adf_flags & O_RDWR) && (type & ADLOCK_WR)) {
- type = (type & ~ADLOCK_WR) | ADLOCK_RD;
- }
-
- lock.l_type = XLATE_FCNTL_LOCK(type & ADLOCK_MASK);
- lock.l_whence = SEEK_SET;
- lock.l_len = len;
-
- /* see if it's locked by another fork. */
- if (fork && adf_findxlock(adf, fork, ADLOCK_WR |
- ((type & ADLOCK_WR) ? ADLOCK_RD : 0),
- lock.l_start, lock.l_len) > -1) {
- errno = EACCES;
- return -1;
- }
-
- /* okay, we might have ranges byte-locked. we need to make sure that
- * we restore the appropriate ranges once we're done. so, we check
- * for overlap on an unlock and relock.
- * XXX: in the future, all the byte locks will be sorted and contiguous.
- * we just want to upgrade all the locks and then downgrade them
- * here. */
- if (!adf->adf_excl) {
- err = set_lock(adf->adf_fd, F_SETLK, &lock);
- }
- else {
- err = 0;
- }
- if (!err && (lock.l_type == F_UNLCK))
- adf_relockrange(adf, adf->adf_fd, lock.l_start, len);
-
- return err;
-#endif
-}
-
/* -------------------------
the fork is opened in Read Write, Deny Read, Deny Write mode
lock the whole file once
#endif
}
-/* --------------------- */
-void ad_fcntl_unlock(struct adouble *ad, const int fork)
+int ad_lock(struct adouble *ad, uint32_t eid, int type, off_t off, off_t len, int user)
{
- return;
-#if 0
- if (ad_data_fileno(ad) != -1) {
- adf_unlock(&ad->ad_data_fork, fork);
- }
- if (ad_reso_fileno(ad) != -1) {
- adf_unlock(&ad->ad_resource_fork, fork);
- }
+ return 0;
+}
- if (ad->ad_flags != AD_VERSION_EA) {
+void ad_unlock(struct adouble *ad, int user)
+{
return;
- }
- if (ad_meta_fileno(ad) != -1) {
- adf_unlock(&ad->ad_metadata_fork, fork);
- }
-#endif
+}
+
+int ad_tmplock(struct adouble *ad, uint32_t eid, int type, off_t off, off_t len, int user)
+{
+ return 0;
}
#include <atalk/ea.h>
#include <atalk/bstrlib.h>
#include <atalk/bstradd.h>
+#include <atalk/compat.h>
#include "ad_lock.h"
--- /dev/null
+Makefile
+Makefile.in
+*.lo
+*.la
+.deps
+.libs
+
--- /dev/null
+# Makefile.am for libatalk/locking/
+
+noinst_LTLIBRARIES = liblocking.la
+
+liblocking_la_SOURCES = locking.c
--- /dev/null
+/*
+ * Copyright (c) 2011 Frank Lahm
+ * All Rights Reserved. See COPYRIGHT.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <atalk/logger.h>
+#include <atalk/errchk.h>
+#include <atalk/locking.h>
+#include <atalk/cnid.h>
+#define AFP_LOCKTABLE_SIZE (8*1024*1024)
+
+/*
+ * Struct for building the the main database of file locks.
+ * vid + cnid build the primary key for database access.
+ */
+struct afp_lock {
+ /* Keys */
+ uint32_t vid;
+ cnid_t cnid;
+
+ /* Refcounting access and deny modes */
+ uint16_t amode_r;
+ uint16_t amode_w;
+ uint16_t dmode_r;
+ uint16_t dmode_w;
+};
+
+/*
+ * Structure for building a table which provides the way to find locks by pid
+ */
+struct pid_lock {
+ /* Key */
+ pid_t pid;
+
+ /* Key for afp_lock */
+ uint32_t vid;
+ cnid_t cnid;
+};
+
+/***************************************************************************
+ * Public functios
+ ***************************************************************************/
+
+int locktable_init(void)
+{
+ EC_INIT;
+
+
+EC_CLEANUP:
+ EC_EXIT;
+}
+
/*
- * Copyright (c) 2010 Frank Lahm
+ * Copyright (c) 2011 Frank Lahm
* All Rights Reserved. See COPYRIGHT.
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
+#include <pthread.h>
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
#include "event2/event-config.h"
#include <atalk/adouble.h>
#include <atalk/bstrlib.h>
#include <atalk/bstradd.h>
+#include <atalk/lockrpc.gen.h>
EVRPC_HEADER(lock_msg, lock_req, lock_rep)
EVRPC_GENERATE(lock_msg, lock_req, lock_rep)
event_base_loopexit(ev_base, NULL);
}
-static void rpc_dummy(const char *name)
+static int rpc_dummy(const char *name)
{
struct lock *lock = NULL;
struct lock_req *lock_req = NULL;
int rpc_init(const char *addr, unsigned short port)
{
EC_INIT;
+
struct evhttp_connection *evcon;
EC_NULL_LOG(ev_base = event_init());
# Makefile.am for libatalk/util/
+pkgconfdir = @PKGCONFDIR@
+
noinst_LTLIBRARIES = libutil.la
libutil_la_SOURCES = \
server_lock.c \
socket.c \
strdicasecmp.c \
- volinfo.c \
+ volinfo.c \
unix.c
+
+libutil_la_CFLAGS = -D_PATH_AFPDCONF=\"$(pkgconfdir)/afpd.conf\"
\ No newline at end of file
/*
- * $Id: server_ipc.c,v 1.4 2010-01-21 14:14:49 didg Exp $
- *
* All rights reserved. See COPYRIGHT.
- *
- *
- * ipc between parent and children.
*/
#ifdef HAVE_CONFIG_H
#endif
#include <sys/types.h>
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <errno.h>
#include <atalk/server_child.h>
#include <atalk/server_ipc.h>
LOG (log_debug, logtype_afpd, "ipc_write: command: %u, pid: %u, msglen: %u", command, pid, len);
return write(pipe_fd[1], block, len+IPC_HEADERLEN );
}
-
#include <atalk/logger.h>
#include <atalk/volinfo.h>
#include <atalk/volume.h>
+#include <atalk/compat.h>
#ifdef CNID_DB
#include <atalk/cnid.h>
#endif /* CNID_DB*/