Fix a sign extension bug in stdio.

This also lets us test the EOVERFLOW behavior, which pointed out that the
fgetpos/fsetpos return on failure has always been wrong...

Bug: http://b/24807045
Change-Id: I35273eb07c8c9155af858adb27569983397580b6
diff --git a/libc/stdio/stdio.cpp b/libc/stdio/stdio.cpp
index 2139621..16cbd55 100644
--- a/libc/stdio/stdio.cpp
+++ b/libc/stdio/stdio.cpp
@@ -426,7 +426,12 @@
   if (_EXT(fp)->_seek64 != nullptr) {
     return (*_EXT(fp)->_seek64)(fp->_cookie, offset, whence);
   } else if (fp->_seek != nullptr) {
-    return (*fp->_seek)(fp->_cookie, offset, whence);
+    off64_t result = (*fp->_seek)(fp->_cookie, offset, whence);
+#if !defined(__LP64__)
+    // Avoid sign extension if off64_t is larger than off_t.
+    if (result != -1) result &= 0xffffffff;
+#endif
+    return result;
   } else {
     errno = ESPIPE;
     return -1;
@@ -531,12 +536,12 @@
 
 int fgetpos(FILE* fp, fpos_t* pos) {
   *pos = ftello(fp);
-  return (*pos == -1);
+  return (*pos == -1) ? -1 : 0;
 }
 
 int fgetpos64(FILE* fp, fpos64_t* pos) {
   *pos = ftello64(fp);
-  return (*pos == -1);
+  return (*pos == -1) ? -1 : 0;
 }
 
 static FILE* __funopen(const void* cookie,
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 7f412c1..b6f6526 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -1116,14 +1116,19 @@
   FILE* fp = funopen(nullptr, read_fn, nullptr, seek_fn, nullptr);
   ASSERT_TRUE(fp != nullptr);
   fpos_t pos;
-  ASSERT_EQ(0, fgetpos(fp, &pos));
-  ASSERT_EQ(0xfedcba12LL, pos);
+#if defined(__LP64__)
+  EXPECT_EQ(0, fgetpos(fp, &pos)) << strerror(errno);
+  EXPECT_EQ(0xfedcba12LL, pos);
+#else
+  EXPECT_EQ(-1, fgetpos(fp, &pos)) << strerror(errno);
+  EXPECT_EQ(EOVERFLOW, errno);
+#endif
 
   FILE* fp64 = funopen64(nullptr, read_fn, nullptr, seek64_fn, nullptr);
   ASSERT_TRUE(fp64 != nullptr);
   fpos64_t pos64;
-  ASSERT_EQ(0, fgetpos64(fp64, &pos64));
-  ASSERT_EQ(0xfedcba12345678, pos64);
+  EXPECT_EQ(0, fgetpos64(fp64, &pos64)) << strerror(errno);
+  EXPECT_EQ(0xfedcba12345678, pos64);
 #else
   GTEST_LOG_(INFO) << "glibc uses fopencookie instead.\n";
 #endif