diff --git a/MODULES.html.sh b/MODULES.html.sh
index 058125d..ccce428 100755
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -396,6 +396,7 @@ fgets
fgetwc
fgetws
fileno
+flock
flockfile
floor
floorf
@@ -2105,6 +2106,7 @@ func_all_modules ()
func_module errno
func_module fchdir
func_module fcntl
+ func_module flock
func_module fopen
func_module fprintf-posix
func_module freopen
diff --git a/doc/glibc-functions/flock.texi b/doc/glibc-functions/flock.texi
index 29a2eb8..23878cf 100644
--- a/doc/glibc-functions/flock.texi
+++ b/doc/glibc-functions/flock.texi
@@ -2,15 +2,18 @@
@subsection @code{flock}
@findex flock
-Gnulib module: ---
+Gnulib module: flock
Portability problems fixed by Gnulib:
@itemize
address@hidden
+This function is missing on some platforms:
+mingw
@end itemize
Portability problems not fixed by Gnulib:
@itemize
@item
This function is missing on some platforms:
-AIX 5.1, HP-UX 11, Solaris 10, mingw, BeOS.
+AIX 5.1, HP-UX 11, Solaris 10, BeOS.
@end itemize
diff --git a/lib/flock.c b/lib/flock.c
new file mode 100644
index 0000000..142fcc4
--- /dev/null
+++ b/lib/flock.c
@@ -0,0 +1,232 @@
+/* Emulate flock on platforms that lack it, primarily Windows and MinGW.
+
+ This is derived from sqlite3 sources.
+ http://www.sqlite.org/cvstrac/rlog?f=sqlite/src/os_win.c
+ http://www.sqlite.org/copyright.html
+
+ Written by Richard W.M. Jones
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see . */
+
+#include
+#include
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+/* _get_osfhandle */
+#include
+
+/* LockFile and LockFileEx */
+#define WIN32_LEAN_AND_MEAN
+#include
+
+#include
+
+/* Is this platform NT? NT has LockFileEx which can do reader/writer
+ * locks, everything before that only has LockFile which can just lock
+ * files. This is not implemented for WinCE (which lacks both).
+ *
+ * os_type is:
+ * 0 = not determined yet
+ * 1 = 95/98/ME
+ * 2 = NT
+ */
+static int os_type = 0;
+
+static int
+is_NT ()
+{
+ if (os_type==0)
+ {
+ OSVERSIONINFO sInfo;
+
+ sInfo.dwOSVersionInfoSize = sizeof(sInfo);
+ GetVersionEx(&sInfo);
+ os_type = sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ? 2 : 1;
+ }
+ return os_type == 2;
+}
+
+/* Determine the current size of a file. Because the other braindead
+ * APIs we'll call need lower/upper 32 bit pairs, keep the file size
+ * like that too. Use GetFileSize since it's available on all
+ * versions of Windows (GetFileSizeEx is less braindead but only
+ * available on NT).
+ */
+static int
+file_size (HANDLE h, DWORD *lower, DWORD *upper)
+{
+ *lower = GetFileSize (h, upper);
+ return 1;
+}
+
+/* LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems. */
+#ifndef LOCKFILE_FAIL_IMMEDIATELY
+# define LOCKFILE_FAIL_IMMEDIATELY 1
+#endif
+
+/* Acquire a reader lock. */
+static int
+do_lock_read (HANDLE h, int non_blocking)
+{
+ int res;
+ DWORD size_lower, size_upper;
+
+ res = file_size (h, &size_lower, &size_upper);
+ if (!res) return 0;
+
+ if (is_NT())
+ {
+ OVERLAPPED ovlp;
+ int flags = 0;
+
+ /* NT is relatively sane. Request a non-exclusive lock on
+ * the whole file.
+ */
+ ovlp.Offset = 0;
+ ovlp.OffsetHigh = 0;
+ ovlp.hEvent = 0;
+ if (non_blocking) flags |= LOCKFILE_FAIL_IMMEDIATELY;
+ res = LockFileEx (h, flags, 0, size_lower, size_upper, &ovlp);
+ }
+ else
+ {
+ int lk;
+
+ /* Pre-NT systems have only LockFile, which only locks
+ * exclusively. Use the same strategy as sqlite: acquire a lock
+ * on a single byte somewhere in the file. Two readers will
+ * usually be able to continue in parallel (unless they are
+ * unlucky and request the same byte -- of course the size of
+ * the file matters here). A writer will try to lock the whole
+ * file, so always get exclusive access.
+ */
+ /* XXX rand() isn't thread-safe. */
+ /* XXX sqlite original code saves 'lk' (the offset of the byte
+ * we are locking). We have nowhere convenient to stash this,
+ * but it shouldn't matter - we unlock the whole file below.
+ */
+ lk = rand () % size_lower;
+ res = LockFile (h, lk, 0, 1, 0);
+ }
+
+ return res;
+}
+
+/* Get an exclusive lock on a file. */
+static int
+do_lock_exclusive (HANDLE h, int non_blocking)
+{
+ int res;
+ DWORD size_lower, size_upper;
+
+ res = file_size (h, &size_lower, &size_upper);
+ if (!res) return 0;
+
+ if (is_NT())
+ {
+ OVERLAPPED ovlp;
+ int flags = LOCKFILE_EXCLUSIVE_LOCK;
+
+ ovlp.Offset = 0;
+ ovlp.OffsetHigh = 0;
+ ovlp.hEvent = 0;
+ if (non_blocking) flags |= LOCKFILE_FAIL_IMMEDIATELY;
+ res = LockFileEx (h, flags, 0, size_lower, size_upper, &ovlp);
+ }
+ else
+ {
+ /* See discussion in do_lock_read function above. */
+ res = LockFile (h, 0, 0, size_lower, size_upper);
+ }
+
+ return res;
+}
+
+/* Unlock reader or exclusive lock. */
+static int
+do_unlock (HANDLE h)
+{
+ int res;
+ DWORD size_lower, size_upper;
+
+ res = file_size (h, &size_lower, &size_upper);
+ if (!res) return 0;
+
+ res = UnlockFile(h, 0, 0, size_lower, size_upper);
+ return res;
+}
+
+int
+flock (int fd, int operation)
+{
+ HANDLE h = (HANDLE) _get_osfhandle (fd);
+ DWORD res;
+ int non_blocking = operation & LOCK_NB;
+
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (operation & LOCK_SH)
+ res = do_lock_read (h, non_blocking);
+ else if (operation & LOCK_EX)
+ res = do_lock_exclusive (h, non_blocking);
+ else if (operation & LOCK_UN)
+ res = do_unlock (h);
+ else {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Map Windows errors into Unix errnos. As usual MSDN fails to
+ * document the permissible error codes.
+ */
+ if (!res) {
+ DWORD err = GetLastError ();
+ switch (err)
+ {
+ /* This means someone else is holding a lock. */
+ case ERROR_LOCK_VIOLATION:
+ /* EWOULDBLOCK is not available on MinGW. */
+ errno = EAGAIN;
+ break;
+
+ /* Out of memory. */
+ case ERROR_NOT_ENOUGH_MEMORY:
+ errno = ENOMEM;
+ break;
+
+ /* Unlikely to be other errors, but at least don't lose the
+ * error code.
+ */
+ default:
+ errno = err;
+ }
+
+ return -1;
+ }
+
+ return 0;
+}
+
+#else /* !Windows */
+
+#error "This platform lacks flock function, and Gnulib doesn't provide a replacement. This is a bug in Gnulib."
+
+#endif /* !Windows */
diff --git a/lib/sys_file.in.h b/lib/sys_file.in.h
new file mode 100644
index 0000000..c1d2315
--- /dev/null
+++ b/lib/sys_file.in.h
@@ -0,0 +1,58 @@
+/* Provide a more complete sys/file.h.
+
+ Copyright (C) 2007-2008 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Richard W.M. Jones. */
+#ifndef _GL_SYS_FILE_H
+
address@hidden@
+
+/* The include_next requires a split double-inclusion guard. */
+# if @HAVE_SYS_FILE_H@
+# @INCLUDE_NEXT@ @NEXT_SYS_FILE_H@
+# endif
+
+#ifndef _GL_SYS_FILE_H
+#define _GL_SYS_FILE_H
+
+
+#if @GNULIB_FLOCK@
+/* Apply or remove advisory locks on an open file.
+ Return 0 if successful, otherwise -1 and errno set. */
+# if address@hidden@
+extern int flock (int fd, int operation);
+
+/* Operations for the 'flock' call (same as Linux kernel constants). */
+#define LOCK_SH 1 /* Shared lock. */
+#define LOCK_EX 2 /* Exclusive lock. */
+#define LOCK_UN 8 /* Unlock. */
+
+/* Can be OR'd in to one of the above. */
+#define LOCK_NB 4 /* Don't block when locking. */
+
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef flock
+# define flock(fd,op) \
+ (GL_LINK_WARNING ("flock is unportable - " \
+ "use gnulib module flock for portability"), \
+ flock ((fd), (op)))
+#endif
+
+
+#endif /* _GL_SYS_FILE_H */
+#endif /* _GL_SYS_FILE_H */
diff --git a/m4/flock.m4 b/m4/flock.m4
new file mode 100644
index 0000000..54ef7cf
--- /dev/null
+++ b/m4/flock.m4
@@ -0,0 +1,19 @@
+# flock.m4 serial 1
+dnl Copyright (C) 2008 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_FLOCK],
+[
+ AC_REQUIRE([gl_HEADER_SYS_FILE_H_DEFAULTS])
+ AC_CHECK_FUNCS_ONCE([flock])
+ if test $ac_cv_func_flock = no; then
+ HAVE_FLOCK=0
+ AC_LIBOBJ([flock])
+ gl_PREREQ_FLOCK
+ fi
+])
+
+# Prerequisites of lib/flock.c.
+AC_DEFUN([gl_PREREQ_FLOCK], [:])
diff --git a/m4/sys_file_h.m4 b/m4/sys_file_h.m4
new file mode 100644
index 0000000..436c6fe
--- /dev/null
+++ b/m4/sys_file_h.m4
@@ -0,0 +1,41 @@
+# Configure a replacement for .
+
+# Copyright (C) 2008 Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# Written by Richard W.M. Jones.
+
+AC_DEFUN([gl_HEADER_SYS_FILE_H],
+[
+ AC_REQUIRE([gl_HEADER_SYS_FILE_H_DEFAULTS])
+
+ dnl Only flock is defined in a working . If that
+ dnl function is already there, we don't want to do any substitution.
+ AC_CHECK_FUNCS_ONCE([flock])
+
+ gl_CHECK_NEXT_HEADERS([sys/file.h])
+ SYS_FILE_H='sys/file.h'
+ AC_SUBST([SYS_FILE_H])
+
+ AC_CHECK_HEADERS_ONCE([sys/file.h])
+ if test $ac_cv_header_sys_file_h = yes; then
+ HAVE_SYS_FILE_H=1
+ else
+ HAVE_SYS_FILE_H=0
+ fi
+ AC_SUBST([HAVE_SYS_FILE_H])
+])
+
+AC_DEFUN([gl_HEADER_SYS_FILE_MODULE_INDICATOR],
+[
+ AC_REQUIRE([gl_HEADER_SYS_FILE_H_DEFAULTS])
+ GNULIB_[]m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./-],[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])=1
+])
+
+AC_DEFUN([gl_HEADER_SYS_FILE_H_DEFAULTS],
+[
+ GNULIB_FLOCK=0; AC_SUBST([GNULIB_FLOCK])
+ HAVE_FLOCK=1; AC_SUBST([HAVE_FLOCK])
+])
diff --git a/modules/flock b/modules/flock
new file mode 100644
index 0000000..9134d51
--- /dev/null
+++ b/modules/flock
@@ -0,0 +1,24 @@
+Description:
+flock(2) function: advisory file locks.
+
+Files:
+lib/flock.c
+m4/flock.m4
+
+Depends-on:
+sys_file
+
+configure.ac:
+gl_FUNC_FLOCK
+gl_HEADER_SYS_FILE_MODULE_INDICATOR([flock])
+
+Makefile.am:
+
+Include:
+
+
+License:
+LGPLv2+
+
+Maintainer:
+Richard W.M. Jones, Jim Meyering
diff --git a/modules/sys_file b/modules/sys_file
new file mode 100644
index 0000000..2c1f8f8
--- /dev/null
+++ b/modules/sys_file
@@ -0,0 +1,44 @@
+Description:
+ for systems with an incomplete header.
+
+Files:
+lib/sys_file.in.h
+m4/sys_file_h.m4
+
+Depends-on:
+include_next
+link-warning
+
+configure.ac:
+gl_HEADER_SYS_FILE_H
+AC_PROG_MKDIR_P
+
+Makefile.am:
+BUILT_SOURCES += $(SYS_FILE_H)
+
+# We need the following in order to create when the system
+# has one that is incomplete.
+sys/file.h: sys_file.in.h
+ @MKDIR_P@ sys
+ rm -f address@hidden $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's/@''HAVE_SYS_FILE_H''@/$(HAVE_SYS_FILE_H)/g' \
+ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+ -e 's|@''NEXT_SYS_FILE_H''@|$(NEXT_SYS_FILE_H)|g' \
+ -e 's/@''HAVE_FLOCK''@/$(HAVE_FLOCK)/g' \
+ -e 's/@''GNULIB_FLOCK''@/$(GNULIB_FLOCK)/g' \
+ < $(srcdir)/sys_file.in.h; \
+ } > address@hidden
+ mv address@hidden $@
+MOSTLYCLEANFILES += sys/file.h sys/file.h-t
+MOSTLYCLEANDIRS += sys
+
+Include:
+#include
+
+License:
+LGPLv2+
+
+Maintainer:
+all