[Rpcemu] Patch for > 2G files in HostFS

Sprow webpages at sprow.co.uk
Sun Oct 23 00:04:03 PDT 2011


Hi,
Further to my earlier email, I've since spotted a use of ftruncate() which
I'd not found because I was only searching for functions from <stdio.h>. It
has a similar restriction of not accepting top bit set truncate points,
which manifests itself as files being rounded up to the nearest FileSwitch
buffer size:
  *CREATE test 90000005
  F=OPENUP"test"
  IFF=0 THENPRINT"No handle":END
  PTR#F=&8FFFFFFF
  PRINT~PTR#F,~EXT#F
  REM Now cross a FileSwitch buffer boundary
  BPUT#F,99
  BPUT#F,100
  CLOSE#F
  PRINT"Reopening"
  F=OPENIN"test"
  PRINT~PTR#F,~EXT#F
  CLOSE#F
  END
the second print out says 90000400 because HostFS uses a 1k buffer.

I also upgraded to 0.8.8 - many more MIPS! - so the following patch is based
on that. Annoyingly Windows doesn't have an ftruncate64() like other systems
so this is implemented locally based on the documented behaviour but using
native Windows functions.

--- 0.8.8/src/org_hostfs.c	Sun Sep 19 20:25:38 2010
+++ 0.8.8/src/hostfs.c	Sun Oct 23 07:56:02 2011
@@ -52,6 +52,33 @@
 # define mkdir(name, mode) _mkdir(name)
 #endif
 
+/* Windows doesn't have an ftruncate64() implementation, so map
+   this to the equivalent Kernel call */
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+#include <windows.h>
+int ftruncate64(int fd, off64_t length)
+{
+  HANDLE  h;
+  int64_t present;
+  
+  h = (HANDLE)_get_osfhandle(fd);
+  if (h == (HANDLE)-1) {
+    errno = EBADF;
+    return -1;
+  }
+  
+  present = _lseeki64(fd, (int64_t)length, SEEK_SET);
+  if (present != (int64_t)length) {
+    errno = EINVAL;
+    return -1;
+  }
+  
+  /* If the call fails blame it on the system */
+  errno = ENOSYS;
+  return SetEndOfFile(h) ? 0 : -1;
+}
+#endif
+
 typedef int bool;
 
 #define true  ((bool) 1)
@@ -817,8 +844,8 @@
   }
 
   /* Find the extent of the file */
-  fseek(open_file[idx], 0L, SEEK_END);
-  state->Reg[3] = ftell(open_file[idx]);
+  fseeko64(open_file[idx], 0LL, SEEK_END);
+  state->Reg[3] = (ARMword)ftello64(open_file[idx]);
   rewind(open_file[idx]); /* Return to start */
 
   state->Reg[1] = idx; /* Our filing system's handle */
@@ -845,7 +872,7 @@
 
   hostfs_ensure_buffer_size(state->Reg[3]);
 
-  fseek(f, (long) state->Reg[4], SEEK_SET);
+  fseeko64(f, (off64_t) state->Reg[4], SEEK_SET);
 
   fread(buffer, 1, state->Reg[3], f);
 
@@ -872,7 +899,7 @@
 
   hostfs_ensure_buffer_size(state->Reg[3]);
 
-  fseek(f, (long) state->Reg[4], SEEK_SET);
+  fseeko64(f, (off64_t) state->Reg[4], SEEK_SET);
 
   for (i = 0; i < state->Reg[3]; i++) {
     buffer[i] = ARMul_LoadByte(state, ptr);
@@ -913,7 +940,7 @@
 
   /* Set file to required extent */
   /* FIXME Not defined if file is increased in size */
-  if (ftruncate(fd, (off_t) state->Reg[2])) {
+  if (ftruncate64(fd, (off64_t) state->Reg[2])) {
     fprintf(stderr, "hostfs_args_3_write_file_extent() bad ftruncate(): %s
%d\n",
             strerror(errno), errno);
     return;
@@ -933,9 +960,9 @@
   dbug_hostfs("\tr1 = %u (our file handle)\n", state->Reg[1]);
   dbug_hostfs("\tr2 = %u (size of file to ensure)\n", state->Reg[2]);
 
-  fseek(f, 0L, SEEK_END);
+  fseeko64(f, 0LL, SEEK_END);
 
-  state->Reg[2] = (ARMword) ftell(f);
+  state->Reg[2] = (ARMword) ftello64(f);
 }
 
 static void
@@ -954,7 +981,7 @@
   dbug_hostfs("\tr2 = %u (file offset at which to write)\n", state->Reg[2]);
   dbug_hostfs("\tr3 = %u (number of zero bytes to write)\n", state->Reg[3]);
 
-  fseek(f, (long) state->Reg[2], SEEK_SET);
+  fseeko64(f, (off64_t) state->Reg[2], SEEK_SET);
 
   hostfs_ensure_buffer_size(BUFSIZE);
   memset(buffer, 0, BUFSIZE);




More information about the Rpcemu mailing list