diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index b38a3a5db9ea87665e9132c79965b98c02b1d408..221fa2100e34bc7b391c83431a2935b5d300d4f6 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,12 @@
+2003-01-03  Mark Wielaard  <mark@klomp.org>
+
+	* java/io/FileDescriptor.java (position): New private field.
+	* java/io/natFileDescriptorPosix.cc (write): Up position.
+	(setLength): Use and set position.
+	(seek): Set position.
+	(getFilePointer): Return position.
+	(read): Up position.
+
 2003-01-03  Mark Wielaard  <mark@klomp.org>
 
 	Merge with Classpath:
diff --git a/libjava/java/io/FileDescriptor.java b/libjava/java/io/FileDescriptor.java
index 08f8edfaa0d7cd0b14dd7d67b040efddb0351729..f105c6f8ab0576e849438d2710e999238e328efc 100644
--- a/libjava/java/io/FileDescriptor.java
+++ b/libjava/java/io/FileDescriptor.java
@@ -1,6 +1,6 @@
 // FileDescriptor.java - Open file or device
 
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -101,4 +101,6 @@ public final class FileDescriptor
   // we want to make sure this has the value -1.  This is the most
   // efficient way to accomplish that.
   private int fd = -1;
+
+  private long position = 0;
 }
diff --git a/libjava/java/io/natFileDescriptorPosix.cc b/libjava/java/io/natFileDescriptorPosix.cc
index 80e6bad97ae9ec180a20d45c2bfcceae90a54cff..e8ec9a7e733b9d8f856fec2246c3046f0013830f 100644
--- a/libjava/java/io/natFileDescriptorPosix.cc
+++ b/libjava/java/io/natFileDescriptorPosix.cc
@@ -1,6 +1,6 @@
 // natFileDescriptor.cc - Native part of FileDescriptor class.
 
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -147,6 +147,7 @@ java::io::FileDescriptor::write (jint b)
 	  throw new IOException (JvNewStringLatin1 (strerror (errno)));
 	}
     }
+  position++;
 }
 
 void
@@ -177,6 +178,7 @@ java::io::FileDescriptor::write (jbyteArray b, jint offset, jint len)
       written += r;
       len -= r;
       bytes += r;
+      position += r;
     }
 }
 
@@ -193,7 +195,6 @@ void
 java::io::FileDescriptor::setLength (jlong pos)
 {
   struct stat sb;
-  off_t orig;
 
 #ifdef HAVE_FTRUNCATE
   if (::fstat (fd, &sb))
@@ -202,10 +203,6 @@ java::io::FileDescriptor::setLength (jlong pos)
   if ((jlong) sb.st_size == pos) 
     return;
 
-  orig = ::lseek (fd, (off_t) 0, SEEK_CUR);
-  if (orig == -1)
-    throw new IOException (JvNewStringLatin1 (strerror (errno)));
-
   // If the file is too short, we extend it.  We can't rely on
   // ftruncate() extending the file.  So we lseek() to 1 byte less
   // than we want, and then we write a single byte at the end.
@@ -215,11 +212,15 @@ java::io::FileDescriptor::setLength (jlong pos)
 	throw new IOException (JvNewStringLatin1 (strerror (errno)));
       char out = '\0';
       int r = ::write (fd, &out, 1);
-      if (r <= 0 || ::lseek (fd, orig, SEEK_SET) == -1)
+      if (r <= 0 || ::lseek (fd, position, SEEK_SET) == -1)
 	throw new IOException (JvNewStringLatin1 (strerror (errno)));
     }
-  else if (::ftruncate (fd, (off_t) pos))
-    throw new IOException (JvNewStringLatin1 (strerror (errno)));
+  else
+    {
+      if (::ftruncate (fd, (off_t) pos))
+	throw new IOException (JvNewStringLatin1 (strerror (errno)));
+      position = pos;
+    }
 #else /* HAVE_FTRUNCATE */
   throw new IOException (JvNewStringLatin1 ("FileDescriptor.setLength not implemented"));
 #endif /* HAVE_FTRUNCATE */
@@ -230,19 +231,29 @@ java::io::FileDescriptor::seek (jlong pos, jint whence, jboolean eof_trunc)
 {
   JvAssert (whence == SET || whence == CUR);
 
-  jlong len = length ();
-  jlong here = getFilePointer ();
-
-  if (eof_trunc
-      && ((whence == SET && pos > len) || (whence == CUR && here + pos > len)))
+  if (eof_trunc)
     {
-      whence = SET;
-      pos = len;
+      jlong len = length ();
+      if (whence == SET)
+	{
+	  if (pos > len)
+	    pos = len;
+	}
+      else
+	{
+	  jlong here = getFilePointer ();
+	  if (here + pos > len)
+	    {
+	      pos = len;
+	      whence = SET;
+	    }
+	}
     }
 
   off_t r = ::lseek (fd, (off_t) pos, whence == SET ? SEEK_SET : SEEK_CUR);
   if (r == -1)
     throw new IOException (JvNewStringLatin1 (strerror (errno)));
+  position = r;
   return r;
 }
 
@@ -258,10 +269,7 @@ java::io::FileDescriptor::length (void)
 jlong
 java::io::FileDescriptor::getFilePointer (void)
 {
-  off_t r = ::lseek (fd, 0, SEEK_CUR);
-  if (r == -1)
-    throw new IOException (JvNewStringLatin1 (strerror (errno)));
-  return r;
+  return position;
 }
 
 jint
@@ -282,6 +290,7 @@ java::io::FileDescriptor::read (void)
 	}
       throw new IOException (JvNewStringLatin1 (strerror (errno)));
     }
+  position++;
   return b & 0xFF;
 }
 
@@ -313,6 +322,7 @@ java::io::FileDescriptor::read (jbyteArray buffer, jint offset, jint count)
 	}
       throw new IOException (JvNewStringLatin1 (strerror (errno)));
     }
+  position += r;
   return r;
 }