Patchwork libext2fs: fix ext2fs_llseek on i386

login
register
mail settings
Submitter Theodore Ts'o
Date Jan. 25, 2013, 4:14 a.m.
Message ID <1359087258-13276-1-git-send-email-tytso@mit.edu>
Download mbox | patch
Permalink /patch/215544/
State Accepted
Headers show

Comments

Theodore Ts'o - Jan. 25, 2013, 4:14 a.m.
From: Phillip Susi <psusi@ubuntu.com>

ext2fs_llseek() was using lseek instead of lseek64.  The
only time it would use lseek64 is if passed an offset that
overflowed 32 bits.  This works for SEEK_SET, but not
SEEK_CUR, which can apply a small offset to move the file
pointer past the 32 bit limit.

The code has been changed to instead try lseek64 first, and
fall back to lseek if that fails.  It also was doing a
runtime check of the size of off_t.  This has been moved to
compile time.

This fixes a problem which would cause e2image when built for
x86-32 to bomb out when used with large file systems.

Signed-off-by: Phillip Susi <psusi@ubuntu.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
 configure.in        |  3 +++
 lib/config.h.in     |  3 +++
 lib/ext2fs/llseek.c | 18 ++++++++++--------
 3 files changed, 16 insertions(+), 8 deletions(-)
Phillip Susi - Jan. 25, 2013, 4:34 a.m.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 01/24/2013 11:14 PM, Theodore Ts'o wrote:
> +	fallback: +		if (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8)
> -1))) +			return lseek(fd, (off_t) offset, origin); errno =
> EINVAL;

Shouldn't that be EOVERFLOW?


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with undefined - http://www.enigmail.net/

iQEcBAEBAgAGBQJRAgtjAAoJEJrBOlT6nu75II4H/07hJXsFEGxetEpJGdshSxBc
YTixcONEBDlzppAtLr/aLmHDGr+0269Wjrdj0EhrEqIqlkMG3sRcEkkBoGE7bXbm
3oYLru+YtdVFuDfvZ6PDuConYD/Ud711uLP1Bu2gJN0fGO0l+cg0v1VIirKgaDMO
pB468llpVxMY3Tj9SN5JB7Np0ZS3qxhMpYc3RGsObRamU/BHcIRYw65K8Vsgi4xa
jtf6O8/bQm2AUB+d4IRBuR+KV0/HWFCYtcfSBh/iv/e3aWr2CXA59J5WuGpCfWAM
a72+S9Ek7IOiTi2H59swh2bCSajf01da1JvA26f6yBH7KrY2mvWys1/C/3liUzs=
=/V1N
-----END PGP SIGNATURE-----
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/configure.in b/configure.in
index cf96e43..c3687bb 100644
--- a/configure.in
+++ b/configure.in
@@ -916,14 +916,17 @@  AC_CHECK_SIZEOF(short)
 AC_CHECK_SIZEOF(int)
 AC_CHECK_SIZEOF(long)
 AC_CHECK_SIZEOF(long long)
+AC_CHECK_SIZEOF(off_t)
 SIZEOF_SHORT=$ac_cv_sizeof_short
 SIZEOF_INT=$ac_cv_sizeof_int
 SIZEOF_LONG=$ac_cv_sizeof_long
 SIZEOF_LONG_LONG=$ac_cv_sizeof_long_long
+SIZEOF_OFF_T=$ac_cv_sizeof_off_t
 AC_SUBST(SIZEOF_SHORT)
 AC_SUBST(SIZEOF_INT)
 AC_SUBST(SIZEOF_LONG)
 AC_SUBST(SIZEOF_LONG_LONG)
+AC_SUBST(SIZEOF_OFF_T)
 AC_C_BIGENDIAN
 BUILD_CC="$BUILD_CC" CPP="$CPP" /bin/sh $ac_aux_dir/parse-types.sh
 ASM_TYPES_HEADER=./asm_types.h
diff --git a/lib/config.h.in b/lib/config.h.in
index 90e9743..e14eff4 100644
--- a/lib/config.h.in
+++ b/lib/config.h.in
@@ -543,6 +543,9 @@ 
 /* The size of `long long', as computed by sizeof. */
 #undef SIZEOF_LONG_LONG
 
+/* The size of `off_t', as computed by sizeof. */
+#undef SIZEOF_OFF_T
+
 /* The size of `short', as computed by sizeof. */
 #undef SIZEOF_SHORT
 
diff --git a/lib/ext2fs/llseek.c b/lib/ext2fs/llseek.c
index b0576e4..c3a98a2 100644
--- a/lib/ext2fs/llseek.c
+++ b/lib/ext2fs/llseek.c
@@ -90,17 +90,14 @@  static ext2_loff_t my_llseek (int fd, ext2_loff_t offset, int origin)
 
 ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin)
 {
+#if SIZEOF_OFF_T >= SIZEOF_LONG_LONG
+	return lseek (fd, offset, origin);
+#else
 	ext2_loff_t result;
 	static int do_compat = 0;
 
-	if ((sizeof(off_t) >= sizeof(ext2_loff_t)) ||
-	    (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1))))
-		return lseek(fd, (off_t) offset, origin);
-
-	if (do_compat) {
-		errno = EINVAL;
-		return -1;
-	}
+	if (do_compat)
+		goto fallback;
 
 	result = my_llseek (fd, offset, origin);
 	if (result == -1 && errno == ENOSYS) {
@@ -109,9 +106,14 @@  ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin)
 		 * which does not support the llseek system call
 		 */
 		do_compat++;
+	fallback:
+		if (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))
+			return lseek(fd, (off_t) offset, origin);
 		errno = EINVAL;
+		return -1;
 	}
 	return result;
+#endif
 }
 
 #else /* !linux */