Index: tdb-1.3.0/common/lock.c
===================================================================
--- tdb-1.3.0.orig/common/lock.c
+++ tdb-1.3.0/common/lock.c
@@ -47,10 +47,28 @@ static int fcntl_lock(struct tdb_context
 	}
 #endif
 
+#ifndef HAVE_FCNTL_LOCK_PARTIAL
+	/* Some platforms (like GNU/Hurd) only support whole file locking */
+	if (rw) {
+		if (tdb->nwr++)
+			/* Alread WR-locked */
+			return 0;
+	} else {
+		if (tdb->nrd++ || tdb->nwr)
+			/* Alread RD or WR-locked */
+			return 0;
+	}
+#endif
+
 	fl.l_type = rw;
 	fl.l_whence = SEEK_SET;
+#ifdef HAVE_FCNTL_LOCK_PARTIAL
 	fl.l_start = off;
 	fl.l_len = len;
+#else
+	fl.l_start = 0;
+	fl.l_len = 0;
+#endif
 	fl.l_pid = 0;
 
 	cmd = waitflag ? F_SETLKW : F_SETLK;
@@ -128,10 +146,37 @@ static int fcntl_unlock(struct tdb_conte
 	}
 #endif
 
+#ifndef HAVE_FCNTL_LOCK_PARTIAL
+	/* Some platforms (like GNU/Hurd) only support whole file locking */
+	if (rw)
+		if (--tdb->nwr)
+			/* Still WR-locked */
+			return 0;
+		else if (tdb->nrd)
+			/* Still RD-locked, downgrade to RD */
+			fl.l_type = F_RDLCK;
+		else
+			/* Not locked any more */
+			fl.l_type = F_UNLCK;
+	else
+		if (--tdb->nrd || tdb->nwr)
+			/* Still RD or WR-locked */
+			return 0;
+		else
+			/* Not locked any more */
+			fl.l_type = F_UNLCK;
+#else
 	fl.l_type = F_UNLCK;
+#endif
+
 	fl.l_whence = SEEK_SET;
+#ifdef HAVE_FCNTL_LOCK_PARTIAL
 	fl.l_start = off;
 	fl.l_len = len;
+#else
+	fl.l_start = 0;
+	fl.l_len = 0;
+#endif
 	fl.l_pid = 0;
 
 	return fcntl(tdb->fd, F_SETLKW, &fl);
Index: tdb-1.3.0/lib/replace/wscript
===================================================================
--- tdb-1.3.0.orig/lib/replace/wscript
+++ tdb-1.3.0/lib/replace/wscript
@@ -134,6 +134,23 @@ struct foo bar = { .y = 'X', .x = 1 };
                     addmain=False,
                     msg='Checking for O_DIRECT flag to open(2)')
 
+    if conf.CHECK_HEADERS('fcntl.h'):
+        conf.CHECK_CODE('''
+                        #include <fcntl.h>
+                        int main (void) { int fd = open("/dev/null", O_RDWR); 
+                                          struct flock fl;
+                                          fl.l_type = F_WRLCK;
+                                          fl.l_whence = SEEK_SET;
+                                          fl.l_start = fl.l_len = 100;
+                                          fl.l_pid = 0;
+                                          return fcntl(fd, F_SETLK, &fl); }
+                        ''', 
+                        define='HAVE_FCNTL_LOCK_PARTIAL',
+                        addmain=False,
+                        execute=True,
+                        msg='Checking for partial locking support using fcntl(2)')
+                                             
+                    
     conf.CHECK_TYPES('"long long" intptr_t uintptr_t ptrdiff_t comparison_fn_t')
     conf.CHECK_TYPE('_Bool', define='HAVE__Bool')
     conf.CHECK_TYPE('bool', define='HAVE_BOOL')
Index: tdb-1.3.0/test/run-die-during-transaction.c
===================================================================
--- tdb-1.3.0.orig/test/run-die-during-transaction.c
+++ tdb-1.3.0/test/run-die-during-transaction.c
@@ -218,6 +218,9 @@ int main(int argc, char *argv[])
 	struct agent *agent;
 	int i;
 
+#ifndef HAVE_FCNTL_LOCK_PARTIAL
+	skip(1, "No partial locking support");
+#else
 	plan_tests(12);
 	unlock_callback = maybe_die;
 
@@ -227,6 +230,6 @@ int main(int argc, char *argv[])
 		diag("Testing %s after death", operation_name(ops[i]));
 		ok1(test_death(ops[i], agent));
 	}
-
+#endif
 	return exit_status();
 }
Index: tdb-1.3.0/test/run-no-lock-during-traverse.c
===================================================================
--- tdb-1.3.0.orig/test/run-no-lock-during-traverse.c
+++ tdb-1.3.0/test/run-no-lock-during-traverse.c
@@ -77,6 +77,9 @@ int main(int argc, char *argv[])
 	struct tdb_context *tdb;
 	int errors = 0;
 
+#ifndef HAVE_FCNTL_LOCK_PARTIAL
+	skip(1, "No partial locking support");
+#else
 	plan_tests(41);
 	tdb = tdb_open_ex("run-no-lock-during-traverse.tdb",
 			  1024, TDB_CLEAR_IF_FIRST, O_CREAT|O_TRUNC|O_RDWR,
@@ -109,6 +112,7 @@ int main(int argc, char *argv[])
 	ok1(tdb_unlockall(tdb) == 0);
 
 	ok1(tdb_close(tdb) == 0);
+#endif
 
 	return exit_status();
 }
Index: tdb-1.3.0/test/run-nested-traverse.c
===================================================================
--- tdb-1.3.0.orig/test/run-nested-traverse.c
+++ tdb-1.3.0/test/run-nested-traverse.c
@@ -61,6 +61,9 @@ int main(int argc, char *argv[])
 	struct tdb_context *tdb;
 	TDB_DATA key, data;
 
+#ifndef HAVE_FCNTL_LOCK_PARTIAL
+	skip(1, "No partial locking support");
+#else
 	plan_tests(17);
 	agent = prepare_external_agent();
 
@@ -83,6 +86,7 @@ int main(int argc, char *argv[])
 	tdb_traverse(tdb, traverse1, NULL);
 	tdb_traverse_read(tdb, traverse1, NULL);
 	tdb_close(tdb);
+#endif
 
 	return exit_status();
 }
Index: tdb-1.3.0/test/run-open-during-transaction.c
===================================================================
--- tdb-1.3.0.orig/test/run-open-during-transaction.c
+++ tdb-1.3.0/test/run-open-during-transaction.c
@@ -148,6 +148,9 @@ int main(int argc, char *argv[])
 	struct tdb_context *tdb;
 	TDB_DATA key, data;
 
+#ifndef HAVE_FCNTL_LOCK_PARTIAL
+	skip(1, "No partial locking support");
+#else
 	plan_tests(20);
 	agent = prepare_external_agent();
 
@@ -177,6 +180,7 @@ int main(int argc, char *argv[])
 		opened = false;
 		tdb_close(tdb);
 	}
+#endif
 
 	return exit_status();
 }
Index: tdb-1.3.0/test/run-marklock-deadlock.c
===================================================================
--- tdb-1.3.0.orig/test/run-marklock-deadlock.c
+++ tdb-1.3.0/test/run-marklock-deadlock.c
@@ -255,6 +255,9 @@ int main(int argc, char *argv[])
 	int ret;
 	bool mutex_support;
 
+#ifndef HAVE_FCNTL_LOCK_PARTIAL
+	skip(1, "No partial locking support");
+#else
 	mutex_support = tdb_runtime_check_for_robust_mutexes();
 
 	ret = do_tests("marklock-deadlock-fcntl.tdb",
@@ -273,6 +276,7 @@ int main(int argc, char *argv[])
 		       TDB_MUTEX_LOCKING |
 		       TDB_INCOMPATIBLE_HASH);
 	ok(ret == 0, "marklock-deadlock-mutex.tdb tests should succeed");
+#endif
 
 	return exit_status();
 }
Index: tdb-1.3.0/common/tdb_private.h
===================================================================
--- tdb-1.3.0.orig/common/tdb_private.h
+++ tdb-1.3.0/common/tdb_private.h
@@ -201,6 +201,10 @@ struct tdb_context {
 	char *name; /* the name of the database */
 	void *map_ptr; /* where it is currently mapped */
 	int fd; /* open file descriptor for the database */
+#ifndef HAVE_FCNTL_LOCK_PARTIAL
+	int nrd; /* number of RD locks */
+	int nwr; /* number of WR locks */
+#endif
 	tdb_len_t map_size; /* how much space has been mapped */
 	int read_only; /* opened read-only */
 	int traverse_read; /* read-only traversal */
Index: tdb-1.3.0/common/open.c
===================================================================
--- tdb-1.3.0.orig/common/open.c
+++ tdb-1.3.0/common/open.c
@@ -328,6 +328,10 @@ _PUBLIC_ struct tdb_context *tdb_open_ex
 #ifdef TDB_TRACE
 	tdb->tracefd = -1;
 #endif
+#ifndef HAVE_FCNTL_LOCK_PARTIAL
+	tdb->nrd = 0;
+	tdb->nwr = 0;
+#endif
 	tdb->name = NULL;
 	tdb->map_ptr = NULL;
 	tdb->flags = tdb_flags;
--- tdb-1.3.0.orig/test/run-traverse-in-transaction.c	2014-11-25 23:47:30.000000000 +0000
+++ tdb-1.3.0/test/run-traverse-in-transaction.c	2014-11-25 23:47:45.000000000 +0000
@@ -46,6 +46,9 @@
 	struct tdb_context *tdb;
 	TDB_DATA key, data;
 
+#ifndef HAVE_FCNTL_LOCK_PARTIAL
+	skip(1, "No partial locking support");
+#else
 	plan_tests(13);
 	agent = prepare_external_agent();
 
@@ -82,6 +85,7 @@
 	    == SUCCESS);
 
 	tdb_close(tdb);
+#endif
 
 	return exit_status();
 }
