Implement POSIX lockf.

This has been requested a few times over the years. This is basically
a very late rebase of https://android-review.googlesource.com/45470
which was abandoned years ago. One addition is that this version has
_FILE_OFFSET_BITS=64 support.

POSIX puts this in <unistd.h>. glibc also has it in <fcntl.h>.

Bug: http://b/13077650
Change-Id: I5862b1dc326e326c01ad92438ecc1578d19ba739
diff --git a/libc/Android.mk b/libc/Android.mk
index 0923939..bcb4afc 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -159,6 +159,7 @@
     bionic/libgen.cpp \
     bionic/link.cpp \
     bionic/locale.cpp \
+    bionic/lockf.cpp \
     bionic/lstat.cpp \
     bionic/malloc_info.cpp \
     bionic/mbrtoc16.cpp \
diff --git a/libc/bionic/lockf.cpp b/libc/bionic/lockf.cpp
new file mode 100644
index 0000000..1510b3d
--- /dev/null
+++ b/libc/bionic/lockf.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <unistd.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+
+int lockf64(int fd, int cmd, off64_t length) {
+  // Translate POSIX lockf into fcntl.
+  struct flock fl;
+  memset(&fl, 0, sizeof(fl));
+  fl.l_whence = SEEK_CUR;
+  fl.l_start = 0;
+  fl.l_len = length;
+
+  if (cmd == F_ULOCK) {
+    fl.l_type = F_UNLCK;
+    cmd = F_SETLK64;
+    return fcntl(fd, F_SETLK64, &fl);
+  }
+
+  if (cmd == F_LOCK) {
+    fl.l_type = F_WRLCK;
+    return fcntl(fd, F_SETLKW64, &fl);
+  }
+
+  if (cmd == F_TLOCK) {
+    fl.l_type = F_WRLCK;
+    return fcntl(fd, F_SETLK64, &fl);
+  }
+
+  if (cmd == F_TEST) {
+    fl.l_type = F_RDLCK;
+    if (fcntl(fd, F_GETLK64, &fl) == -1) return -1;
+    if (fl.l_type == F_UNLCK || fl.l_pid == getpid()) return 0;
+    errno = EACCES;
+    return -1;
+  }
+
+  errno = EINVAL;
+  return -1;
+}
+
+int lockf(int fd, int cmd, off_t length) {
+  return lockf64(fd, cmd, length);
+}
diff --git a/libc/include/machine/wchar_limits.h b/libc/include/bits/lockf.h
similarity index 77%
copy from libc/include/machine/wchar_limits.h
copy to libc/include/bits/lockf.h
index 94cbd7e..d814807 100644
--- a/libc/include/machine/wchar_limits.h
+++ b/libc/include/bits/lockf.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,17 +26,25 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _MACHINE_WCHAR_LIMITS_H_
-#define _MACHINE_WCHAR_LIMITS_H_
+#ifndef _BITS_LOCKF_H_
+#define _BITS_LOCKF_H_
 
-/* Both GCC and clang define __WCHAR_MAX__. */
-#define WCHAR_MAX __WCHAR_MAX__
+#include <sys/cdefs.h>
 
-/* As of 3.4, clang still doesn't define __WCHAR_MIN__. */
-#if defined(__WCHAR_UNSIGNED__)
-#  define WCHAR_MIN L'\0'
+#define F_ULOCK 0
+#define F_LOCK 1
+#define F_TLOCK 2
+#define F_TEST 3
+
+__BEGIN_DECLS
+
+#if defined(__USE_FILE_OFFSET64)
+int lockf(int, int, off_t) __RENAME(lockf64);
 #else
-#  define WCHAR_MIN (-(WCHAR_MAX) - 1)
+int lockf(int, int, off_t);
 #endif
+int lockf64(int, int, off64_t);
 
-#endif /* _MACHINE_WCHAR_LIMITS_H_ */
+__END_DECLS
+
+#endif
diff --git a/libc/include/machine/posix_limits.h b/libc/include/bits/posix_limits.h
similarity index 98%
rename from libc/include/machine/posix_limits.h
rename to libc/include/bits/posix_limits.h
index 787af5c..31016a8 100644
--- a/libc/include/machine/posix_limits.h
+++ b/libc/include/bits/posix_limits.h
@@ -26,8 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _POSIX_LIMITS_H_
-#define _POSIX_LIMITS_H_
+#ifndef _BITS_POSIX_LIMITS_H_
+#define _BITS_POSIX_LIMITS_H_
 
 
 /* Any constant values here other than -1 or 200809L are explicitly specified by POSIX.1-2008. */
@@ -154,4 +154,4 @@
 #define _XOPEN_SHM                  -1
 #define _XOPEN_UNIX                 1
 
-#endif /* _POSIX_LIMITS_H_ */
+#endif
diff --git a/libc/include/machine/pthread_types.h b/libc/include/bits/pthread_types.h
similarity index 93%
rename from libc/include/machine/pthread_types.h
rename to libc/include/bits/pthread_types.h
index 900541c..6ac1c68 100644
--- a/libc/include/machine/pthread_types.h
+++ b/libc/include/bits/pthread_types.h
@@ -26,8 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _MACHINE_PTHREAD_TYPES_H_
-#define _MACHINE_PTHREAD_TYPES_H_
+#ifndef _BITS_PTHREAD_TYPES_H_
+#define _BITS_PTHREAD_TYPES_H_
 
 #include <sys/types.h>
 
@@ -45,4 +45,4 @@
 #endif
 } pthread_attr_t;
 
-#endif /* _MACHINE_PTHREAD_TYPES_H_ */
+#endif
diff --git a/libc/include/machine/timespec.h b/libc/include/bits/timespec.h
similarity index 94%
rename from libc/include/machine/timespec.h
rename to libc/include/bits/timespec.h
index 11779ae..046d898 100644
--- a/libc/include/machine/timespec.h
+++ b/libc/include/bits/timespec.h
@@ -26,8 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _MACHINE_TIMESPEC_H_
-#define _MACHINE_TIMESPEC_H_
+#ifndef _BITS_TIMESPEC_H_
+#define _BITS_TIMESPEC_H_
 
 #include <sys/types.h>
 
@@ -43,4 +43,4 @@
 };
 #endif
 
-#endif /* _MACHINE_TIMESPEC_H_ */
+#endif
diff --git a/libc/include/machine/wchar_limits.h b/libc/include/bits/wchar_limits.h
similarity index 93%
rename from libc/include/machine/wchar_limits.h
rename to libc/include/bits/wchar_limits.h
index 94cbd7e..f779c1a 100644
--- a/libc/include/machine/wchar_limits.h
+++ b/libc/include/bits/wchar_limits.h
@@ -26,8 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _MACHINE_WCHAR_LIMITS_H_
-#define _MACHINE_WCHAR_LIMITS_H_
+#ifndef _BITS_WCHAR_LIMITS_H_
+#define _BITS_WCHAR_LIMITS_H_
 
 /* Both GCC and clang define __WCHAR_MAX__. */
 #define WCHAR_MAX __WCHAR_MAX__
@@ -39,4 +39,4 @@
 #  define WCHAR_MIN (-(WCHAR_MAX) - 1)
 #endif
 
-#endif /* _MACHINE_WCHAR_LIMITS_H_ */
+#endif
diff --git a/libc/include/fcntl.h b/libc/include/fcntl.h
index 0f016d7..6e2ad51 100644
--- a/libc/include/fcntl.h
+++ b/libc/include/fcntl.h
@@ -36,6 +36,10 @@
 #include <linux/stat.h>
 #include <linux/uio.h>
 
+#if defined(__USE_GNU) || defined(__USE_BSD)
+#include <bits/lockf.h>
+#endif
+
 __BEGIN_DECLS
 
 #ifdef __LP64__
diff --git a/libc/include/limits.h b/libc/include/limits.h
index 67c7719..342217b 100644
--- a/libc/include/limits.h
+++ b/libc/include/limits.h
@@ -84,7 +84,7 @@
 #define SEM_VALUE_MAX 0x3fffffff
 
 /* POSIX says these belong in <unistd.h> but BSD has some in <limits.h>. */
-#include <machine/posix_limits.h>
+#include <bits/posix_limits.h>
 
 #define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
 #endif /* !_LIMITS_H_ */
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index 21d34fb..50f2024 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -30,7 +30,7 @@
 #define _PTHREAD_H_
 
 #include <limits.h>
-#include <machine/pthread_types.h>
+#include <bits/pthread_types.h>
 #include <sched.h>
 #include <sys/cdefs.h>
 #include <sys/types.h>
diff --git a/libc/include/sched.h b/libc/include/sched.h
index 930dd7c..0b9235b 100644
--- a/libc/include/sched.h
+++ b/libc/include/sched.h
@@ -28,8 +28,8 @@
 #ifndef _SCHED_H_
 #define _SCHED_H_
 
+#include <bits/timespec.h>
 #include <linux/sched.h>
-#include <machine/timespec.h>
 #include <sys/cdefs.h>
 
 __BEGIN_DECLS
diff --git a/libc/include/signal.h b/libc/include/signal.h
index 7a171b4..85c46c0 100644
--- a/libc/include/signal.h
+++ b/libc/include/signal.h
@@ -30,9 +30,9 @@
 #define _SIGNAL_H_
 
 #include <asm/sigcontext.h>
+#include <bits/pthread_types.h>
+#include <bits/timespec.h>
 #include <limits.h>
-#include <machine/pthread_types.h>
-#include <machine/timespec.h>
 #include <sys/cdefs.h>
 #include <sys/types.h>
 
diff --git a/libc/include/stdint.h b/libc/include/stdint.h
index a6f8505..a66e21e 100644
--- a/libc/include/stdint.h
+++ b/libc/include/stdint.h
@@ -29,8 +29,8 @@
 #ifndef _STDINT_H
 #define _STDINT_H
 
+#include <bits/wchar_limits.h>
 #include <stddef.h>
-#include <machine/wchar_limits.h>
 
 typedef __signed char __int8_t;
 typedef unsigned char __uint8_t;
diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h
index 65aa190..257ded0 100644
--- a/libc/include/sys/stat.h
+++ b/libc/include/sys/stat.h
@@ -29,8 +29,8 @@
 #ifndef _SYS_STAT_H_
 #define _SYS_STAT_H_
 
+#include <bits/timespec.h>
 #include <linux/stat.h>
-#include <machine/timespec.h>
 #include <sys/cdefs.h>
 #include <sys/types.h>
 
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index 23b47a3..5045267 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -35,7 +35,8 @@
 #include <sys/select.h>
 #include <sys/sysconf.h>
 
-#include <machine/posix_limits.h>
+#include <bits/lockf.h>
+#include <bits/posix_limits.h>
 
 __BEGIN_DECLS
 
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index ea6aca0..0a94cee 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -36,7 +36,7 @@
 #include <time.h>
 #include <xlocale.h>
 
-#include <machine/wchar_limits.h>
+#include <bits/wchar_limits.h>
 
 __BEGIN_DECLS
 
diff --git a/libc/libc.arm.brillo.map b/libc/libc.arm.brillo.map
index 95f7cba..4de7b2b 100644
--- a/libc/libc.arm.brillo.map
+++ b/libc/libc.arm.brillo.map
@@ -1235,6 +1235,8 @@
     getifaddrs;
     if_freenameindex;
     if_nameindex;
+    lockf;
+    lockf64;
     preadv;
     preadv64;
     prlimit; # arm mips x86
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index 90b1db3..1f26a60 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1235,6 +1235,8 @@
     getifaddrs;
     if_freenameindex;
     if_nameindex;
+    lockf;
+    lockf64;
     preadv;
     preadv64;
     prlimit; # arm mips x86
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index e5933ae..fbeaa0d 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1159,6 +1159,8 @@
     getifaddrs;
     if_freenameindex;
     if_nameindex;
+    lockf;
+    lockf64;
     preadv;
     preadv64;
     pthread_barrierattr_destroy;
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 928f10d..e5cae49 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1262,6 +1262,8 @@
     getifaddrs;
     if_freenameindex;
     if_nameindex;
+    lockf;
+    lockf64;
     preadv;
     preadv64;
     prlimit; # arm mips x86
diff --git a/libc/libc.mips.brillo.map b/libc/libc.mips.brillo.map
index 691a22a..98ae6f8 100644
--- a/libc/libc.mips.brillo.map
+++ b/libc/libc.mips.brillo.map
@@ -1220,6 +1220,8 @@
     getifaddrs;
     if_freenameindex;
     if_nameindex;
+    lockf;
+    lockf64;
     preadv;
     preadv64;
     prlimit; # arm mips x86
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index 04c76d4..79bca0b 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1220,6 +1220,8 @@
     getifaddrs;
     if_freenameindex;
     if_nameindex;
+    lockf;
+    lockf64;
     preadv;
     preadv64;
     prlimit; # arm mips x86
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index e5933ae..fbeaa0d 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1159,6 +1159,8 @@
     getifaddrs;
     if_freenameindex;
     if_nameindex;
+    lockf;
+    lockf64;
     preadv;
     preadv64;
     pthread_barrierattr_destroy;
diff --git a/libc/libc.x86.brillo.map b/libc/libc.x86.brillo.map
index fbd7085..8792e6a 100644
--- a/libc/libc.x86.brillo.map
+++ b/libc/libc.x86.brillo.map
@@ -1219,6 +1219,8 @@
     getifaddrs;
     if_freenameindex;
     if_nameindex;
+    lockf;
+    lockf64;
     preadv;
     preadv64;
     prlimit; # arm mips x86
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index bcabf71..4835a4e 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1219,6 +1219,8 @@
     getifaddrs;
     if_freenameindex;
     if_nameindex;
+    lockf;
+    lockf64;
     preadv;
     preadv64;
     prlimit; # arm mips x86
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index e5933ae..fbeaa0d 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1159,6 +1159,8 @@
     getifaddrs;
     if_freenameindex;
     if_nameindex;
+    lockf;
+    lockf64;
     preadv;
     preadv64;
     pthread_barrierattr_destroy;