--- /dev/null
+--- python-1.5.2/Modules/fcntlmodule.c.orig Wed Jan 6 13:44:23 1999
++++ python-1.5.2/Modules/fcntlmodule.c Sun Apr 1 07:42:54 2001
+@@ -233,30 +233,12 @@
+ {
+ int fd, code, ret, whence = 0;
+ PyObject *lenobj = NULL, *startobj = NULL;
++ struct flock l;
+
+ if (!PyArg_ParseTuple(args, "ii|OOi", &fd, &code,
+ &lenobj, &startobj, &whence))
+ return NULL;
+
+-#ifndef LOCK_SH
+-#define LOCK_SH 1 /* shared lock */
+-#define LOCK_EX 2 /* exclusive lock */
+-#define LOCK_NB 4 /* don't block when locking */
+-#define LOCK_UN 8 /* unlock */
+-#endif
+- {
+- struct flock l;
+- if (code == LOCK_UN)
+- l.l_type = F_UNLCK;
+- else if (code & LOCK_SH)
+- l.l_type = F_RDLCK;
+- else if (code & LOCK_EX)
+- l.l_type = F_WRLCK;
+- else {
+- PyErr_SetString(PyExc_ValueError,
+- "unrecognized flock argument");
+- return NULL;
+- }
+ l.l_start = l.l_len = 0;
+ if (startobj != NULL) {
+ #if !defined(HAVE_LARGEFILE_SUPPORT)
+@@ -281,10 +263,45 @@
+ return NULL;
+ }
+ l.l_whence = whence;
++ switch (code)
++ {
++ case F_TEST:
++ /* Test the lock: return 0 if FD is unlocked or locked by this process;
++ return -1, set errno to EACCES, if another process holds the lock. */
++ if (fcntl (fd, F_GETLK, &l) < 0) {
++ PyErr_SetFromErrno(PyExc_IOError);
++ return NULL;
++ }
++ if (l.l_type == F_UNLCK || l.l_pid == getpid ()) {
++ Py_INCREF(Py_None);
++ return Py_None;
++ }
++ errno = EACCES;
++ PyErr_SetFromErrno(PyExc_IOError);
++ return NULL;
++
++ case F_ULOCK:
++ l.l_type = F_UNLCK;
++ code = F_SETLK;
++ break;
++ case F_LOCK:
++ l.l_type = F_WRLCK;
++ code = F_SETLKW;
++ break;
++ case F_TLOCK:
++ l.l_type = F_WRLCK;
++ code = F_SETLK;
++ break;
++
++ default:
++ PyErr_SetString(PyExc_ValueError,
++ "unrecognized flock argument");
++ return NULL;
++ }
+ Py_BEGIN_ALLOW_THREADS
+- ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l);
++ ret = fcntl(fd, code, &l);
+ Py_END_ALLOW_THREADS
+- }
++
+ if (ret < 0) {
+ PyErr_SetFromErrno(PyExc_IOError);
+ return NULL;