commit-classpath
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Fwd: FYI: Fix RandomAccessFile.setLenght (truncation file, updates


From: Mark Wielaard
Subject: Re: [Fwd: FYI: Fix RandomAccessFile.setLenght (truncation file, updates file position).]
Date: Sat, 01 May 2004 02:19:27 +0200

Hi Michael,

On Fri, 2004-04-30 at 07:57, Michael Koch wrote:
> Areyou sure the bug isnt in FileChannelImpl.truncate(long) ? have you 
> checked this ?

Good catch. Indeed the bug is in FileChannelImpl.truncate().
I have created a bunch of Mauve tests for it.
Unfortunately it has more then one bug.
It also has a bug were it allowed truncate() to actually expand the File
which isn't allowed. Attached are some patches for this including a new
implementation of RandomAccessFile.setLength() to only use truncate for
making the file smaller and using seek for expanding the file.

2004-04-30  Mark Wielaard  <address@hidden>

        * gnu/java/nio/channels/FileChannelImpl.java (truncate): Only truncate
        when size is smaller.
        * native/jni/java-nio/gnu_java_nio_channels_FileChannelImpl.c
        (implTruncate): Always save current position. Only reposition file
        pointer to where we started if not beyond new lenght. Reposition file
        pointer to file length if it points beyond the end of file.
        * java/io/RandomAccessFile.java (setLength): Use truncate for
        shrinking the file and seek plus write for expanding the file.

This makes all Mauve tests pass (including the new ones). And no
regressions. I think this is the best we can do for this release. In the
future we might want an extra native/VM method for expanding and/or
truncating explicitly.

What do you think. OK for this release?
We can also go with what we have now, then FileChannel.truncate() will
be broken (two ways), but RandomAccessFile.setLength() will be correct.

Cheers,

Mark
Index: gnu/java/nio/channels/FileChannelImpl.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/gnu/java/nio/channels/FileChannelImpl.java,v
retrieving revision 1.5
diff -u -r1.5 FileChannelImpl.java
--- gnu/java/nio/channels/FileChannelImpl.java  23 Apr 2004 05:51:19 -0000      
1.5
+++ gnu/java/nio/channels/FileChannelImpl.java  1 May 2004 00:03:41 -0000
@@ -413,7 +413,9 @@
     if ((mode & WRITE) == 0)
        throw new NonWritableChannelException ();
 
-    implTruncate (size);
+    if (size < size ())
+      implTruncate (size);
+
     return this;
   }
 }
Index: java/io/RandomAccessFile.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/io/RandomAccessFile.java,v
retrieving revision 1.39
diff -u -r1.39 RandomAccessFile.java
--- java/io/RandomAccessFile.java       29 Apr 2004 21:21:11 -0000      1.39
+++ java/io/RandomAccessFile.java       1 May 2004 00:03:41 -0000
@@ -210,11 +210,17 @@
    */
   public void setLength (long newLen) throws IOException
   {
-    ch.truncate (newLen);
-
-    long position = getFilePointer();
-    if (position > newLen)
-      seek(newLen);
+    // FileChannel.truncate() can only shrink a file.
+    // To expand it we need to seek forward and write at least one byte.
+    if (newLen < length())
+      ch.truncate (newLen);
+    else
+      {
+       long pos = getFilePointer();
+       seek(newLen - 1);
+       write(0);
+       seek(pos);
+      }
   }
 
   /**
Index: native/jni/java-nio/gnu_java_nio_channels_FileChannelImpl.c
===================================================================
RCS file: 
/cvsroot/classpath/classpath/native/jni/java-nio/gnu_java_nio_channels_FileChannelImpl.c,v
retrieving revision 1.9
diff -u -r1.9 gnu_java_nio_channels_FileChannelImpl.c
--- native/jni/java-nio/gnu_java_nio_channels_FileChannelImpl.c 30 Apr 2004 
11:05:17 -0000      1.9
+++ native/jni/java-nio/gnu_java_nio_channels_FileChannelImpl.c 1 May 2004 
00:03:42 -0000
@@ -394,20 +394,20 @@
       return;
     }
 
+  /* Save off current position */
+  TARGET_NATIVE_FILE_TELL(native_fd, save_offset, result);
+  if (result != TARGET_NATIVE_OK)
+    {
+      JCL_ThrowException(env, IO_EXCEPTION,
+                         TARGET_NATIVE_LAST_ERROR_STRING());
+      return;
+    }
+
   if (TARGET_NATIVE_MATH_INT_INT64_LT(file_size,len))
     {
       /* File is too short -- seek to one byte short of where we want,
        * then write a byte */
 
-      /* Save off current position */
-      TARGET_NATIVE_FILE_TELL(native_fd, save_offset, result);
-      if (result != TARGET_NATIVE_OK)
-        {
-          JCL_ThrowException(env, IO_EXCEPTION,
-                             TARGET_NATIVE_LAST_ERROR_STRING());
-          return;
-        }
-
       /* move to position n-1 */
       TARGET_NATIVE_FILE_SEEK_BEGIN(native_fd, 
TARGET_NATIVE_MATH_INT_INT64_SUB(len,1), new_offset, result);
       if (result != TARGET_NATIVE_OK)
@@ -429,14 +429,18 @@
           return;
         }
 
-      /* Reposition file pointer to where we started */
-      TARGET_NATIVE_FILE_SEEK_BEGIN(native_fd, save_offset, new_offset, 
result);
-      if (result != TARGET_NATIVE_OK)
-        {
-          JCL_ThrowException(env, IO_EXCEPTION,
-                             TARGET_NATIVE_LAST_ERROR_STRING());
-          return;
-        }
+      /* Reposition file pointer to where we started if not beyond new len. */
+      if (TARGET_NATIVE_MATH_INT_INT64_LT(save_offset, len))
+       {
+         TARGET_NATIVE_FILE_SEEK_BEGIN(native_fd, save_offset,
+                                       new_offset, result);
+         if (result != TARGET_NATIVE_OK)
+           {
+             JCL_ThrowException(env, IO_EXCEPTION,
+                                TARGET_NATIVE_LAST_ERROR_STRING());
+             return;
+           }
+       }
     }
     else if (TARGET_NATIVE_MATH_INT_INT64_GT(file_size,len))
     {
@@ -458,6 +462,18 @@
       JCL_ThrowException(env, IO_EXCEPTION,
                          "Unable to shorten file length");
 #endif /* HAVE_FTRUNCATE */
+
+      /* Reposition file pointer when it now is beyond the end of file. */
+      if (TARGET_NATIVE_MATH_INT_INT64_GT(save_offset, len))
+       {
+         TARGET_NATIVE_FILE_SEEK_BEGIN(native_fd, len, new_offset, result);
+         if (result != TARGET_NATIVE_OK)
+           {
+             JCL_ThrowException(env, IO_EXCEPTION,
+                                TARGET_NATIVE_LAST_ERROR_STRING());
+             return;
+           }
+       }
     }
 }
 

Attachment: signature.asc
Description: This is a digitally signed message part


reply via email to

[Prev in Thread] Current Thread [Next in Thread]