I'm committing this patch. A mauve test will follow as soon as I figure
out a way to get a valid result for comparison (I'm thinking about using
df here, but may not work well an all systems).

The method was tricky because it seems that statvfs does not work
equally well on all system, so I expect few bug reports on this one.
Tested on Linux, should work at least on Solaris, AIX and MacOSX (and
maybe other *BSD), testing on these platform is welcomed (or you can buy
me a playstation 3 and an imac and I will test by myself :)

The return value is in line with the jdk, but with a small difference.
When the root user asks for available space, free space is returned
instead. This is obvious since root has reserved space in addition to
system space. OpenJDK does not take into account this difference. I
don't see a problem here because the returned number of bytes is
explicitly stated to be used as an "hint".

2007-11-06  Mario Torre  <[EMAIL PROTECTED]>

        * vm/reference/java/io/VMFile.java: 
        (getTotalSpace): new method.
        (getUsableSpace): likewise.
        (getFreeSpace): likewise.
        * java/io/File.java: (getTotalSpace): new method. 
        (getUsableSpace): likewise.
        (getFreeSpace): likewise.
        * native/jni/java-io/java_io_VMFile.c:
        (Java_java_io_VMFile_getTotalSpace): new function.
        (Java_java_io_VMFile_getFreeSpace): likewise.
        (Java_java_io_VMFile_getUsableSpace): likewise.
        * native/jni/native-lib/cpio.h: (cpio_df): new function.
        (CPFILE_DF_TYPE): enum type for cpio_df.
        * native/jni/native-lib/cpio.c: (cpio_df): new function.
        * include/java_io_VMFile.h: regenerated.
        * configure.ac: added check for statvfs.
-- 
Lima Software - http://www.limasoftware.net/
GNU Classpath Developer - http://www.classpath.org/
Fedora Ambassador - http://fedoraproject.org/wiki/MarioTorre
Jabber: [EMAIL PROTECTED]
pgp key: http://subkeys.pgp.net/ PGP Key ID: 80F240CF
Fingerprint: BA39 9666 94EC 8B73 27FA  FC7C 4086 63E3 80F2 40CF

Please, support open standards:
http://opendocumentfellowship.org/petition/
http://www.nosoftwarepatents.com/
### Eclipse Workspace Patch 1.0
#P classpath
Index: native/jni/native-lib/cpio.c
===================================================================
RCS file: /sources/classpath/classpath/native/jni/native-lib/cpio.c,v
retrieving revision 1.8
diff -u -r1.8 cpio.c
--- native/jni/native-lib/cpio.c	24 May 2007 22:15:21 -0000	1.8
+++ native/jni/native-lib/cpio.c	6 Nov 2007 13:03:33 -0000
@@ -71,6 +71,10 @@
 #include <sys/select.h>
 #endif
 
+#if defined(HAVE_STATVFS)
+#include <sys/statvfs.h>
+#endif
+
 #include <utime.h>
 
 #include "cpnative.h"
@@ -395,6 +399,43 @@
   return 0;
 }
 
+JNIEXPORT long long
+cpio_df (const char *path, CPFILE_DF_TYPE type)
+{
+  long long result = 0L;
+  
+#if defined(HAVE_STATVFS)
+
+  long long scale_factor = 0L;
+  struct statvfs buf;
+  
+  if (statvfs (path, &buf) < 0)
+    return 0L;
+  
+  /* f_blocks, f_bfree and f_bavail are defined in terms of f_frsize */
+  scale_factor = (long long) (buf.f_frsize);
+
+  switch (type)
+    {
+      case TOTAL:
+        result = (long long) (buf.f_blocks * scale_factor);
+        break;
+      case FREE:
+        result = (long long) (buf.f_bfree * scale_factor);
+        break;
+      case USABLE:
+        result = (long long) (buf.f_bavail * scale_factor);
+        break;
+      default:
+        result = 0L;
+        break;  
+    }
+    
+#endif
+
+  return result;
+}
+
 int cpio_checkAccess (const char *filename, unsigned int flag)
 {
   struct stat statbuf;
@@ -544,7 +585,6 @@
   return 0;
 }
 
-
 int
 cpio_closeOnExec(int fd)
 {
Index: native/jni/native-lib/cpio.h
===================================================================
RCS file: /sources/classpath/classpath/native/jni/native-lib/cpio.h,v
retrieving revision 1.6
diff -u -r1.6 cpio.h
--- native/jni/native-lib/cpio.h	9 Feb 2007 19:51:07 -0000	1.6
+++ native/jni/native-lib/cpio.h	6 Nov 2007 13:03:33 -0000
@@ -83,6 +83,15 @@
 JNIEXPORT int cpio_mkdir (const char *filename);
 JNIEXPORT int cpio_rename (const char *old_name, const char *new_name);
 
+/* to be used with cpio_df */
+typedef enum {
+  TOTAL = 0,
+  FREE,
+  USABLE
+} CPFILE_DF_TYPE;
+
+JNIEXPORT long long cpio_df (const char *path, CPFILE_DF_TYPE type);
+
 JNIEXPORT int cpio_openDir (const char *dirname, void **handle);
 JNIEXPORT int cpio_closeDir (void *handle);
 JNIEXPORT int cpio_readDir (void *handle, char *filename);
Index: include/java_io_VMFile.h
===================================================================
RCS file: /sources/classpath/classpath/include/java_io_VMFile.h,v
retrieving revision 1.6
diff -u -r1.6 java_io_VMFile.h
--- include/java_io_VMFile.h	9 Feb 2007 19:51:07 -0000	1.6
+++ include/java_io_VMFile.h	6 Nov 2007 13:03:30 -0000
@@ -1,10 +1,10 @@
 /* DO NOT EDIT THIS FILE - it is machine generated */
 
+#include <jni.h>
+
 #ifndef __java_io_VMFile__
 #define __java_io_VMFile__
 
-#include <jni.h>
-
 #ifdef __cplusplus
 extern "C"
 {
@@ -20,6 +20,9 @@
 JNIEXPORT jboolean JNICALL Java_java_io_VMFile_delete (JNIEnv *env, jclass, jstring);
 JNIEXPORT jboolean JNICALL Java_java_io_VMFile_setLastModified (JNIEnv *env, jclass, jstring, jlong);
 JNIEXPORT jboolean JNICALL Java_java_io_VMFile_mkdir (JNIEnv *env, jclass, jstring);
+JNIEXPORT jlong JNICALL Java_java_io_VMFile_getTotalSpace (JNIEnv *env, jclass, jstring);
+JNIEXPORT jlong JNICALL Java_java_io_VMFile_getFreeSpace (JNIEnv *env, jclass, jstring);
+JNIEXPORT jlong JNICALL Java_java_io_VMFile_getUsableSpace (JNIEnv *env, jclass, jstring);
 JNIEXPORT jboolean JNICALL Java_java_io_VMFile_setReadable (JNIEnv *env, jclass, jstring, jboolean, jboolean);
 JNIEXPORT jboolean JNICALL Java_java_io_VMFile_setWritable (JNIEnv *env, jclass, jstring, jboolean, jboolean);
 JNIEXPORT jboolean JNICALL Java_java_io_VMFile_setExecutable (JNIEnv *env, jclass, jstring, jboolean, jboolean);
@@ -29,6 +32,7 @@
 JNIEXPORT jboolean JNICALL Java_java_io_VMFile_canExecute (JNIEnv *env, jclass, jstring);
 JNIEXPORT jboolean JNICALL Java_java_io_VMFile_isDirectory (JNIEnv *env, jclass, jstring);
 JNIEXPORT jstring JNICALL Java_java_io_VMFile_toCanonicalForm (JNIEnv *env, jclass, jstring);
+
 #undef java_io_VMFile_IS_CASE_SENSITIVE
 #define java_io_VMFile_IS_CASE_SENSITIVE 1L
 #undef java_io_VMFile_IS_DOS_8_3
Index: configure.ac
===================================================================
RCS file: /sources/classpath/classpath/configure.ac,v
retrieving revision 1.218
diff -u -r1.218 configure.ac
--- configure.ac	2 Nov 2007 21:41:24 -0000	1.218
+++ configure.ac	6 Nov 2007 13:03:30 -0000
@@ -394,6 +394,7 @@
 		  gethostbyname_r localtime_r \
 		  strerror_r \
                   fcntl \
+		  statvfs \  
 		  mmap munmap mincore msync madvise getpagesize sysconf \
 		  lstat readlink \
  		  inet_aton inet_addr inet_pton \
Index: java/io/File.java
===================================================================
RCS file: /sources/classpath/classpath/java/io/File.java,v
retrieving revision 1.71
diff -u -r1.71 File.java
--- java/io/File.java	9 Feb 2007 20:24:08 -0000	1.71
+++ java/io/File.java	6 Nov 2007 13:03:31 -0000
@@ -1293,6 +1293,73 @@
   }
 
   /**
+   * Get the total space for the partition pointed by this file path, in bytes.
+   * 
+   * @return the total number of bytes in this partition. 
+   * @since 1.6
+   */
+  public long getTotalSpace()
+  {
+    // check security manager.
+    SecurityManager s = System.getSecurityManager();
+    if (s != null)
+      s.checkPermission(new RuntimePermission("getFileSystemAttributes"));
+    checkRead();
+    
+    return VMFile.getTotalSpace(path);
+  }
+  
+  /**
+   * Get the free space in the partition pointed by this file path, in bytes.
+   * 
+   * @return the number of free bytes in this partition. 
+   * @since 1.6
+   */
+  public long getFreeSpace()
+  {
+    // check security manager.
+    SecurityManager s = System.getSecurityManager();
+    if (s != null)
+      s.checkPermission(new RuntimePermission("getFileSystemAttributes"));
+    checkRead();
+    
+    return VMFile.getFreeSpace(path);
+  }
+  
+  /**
+   * Get the usable space in the partition pointed by this file path, in bytes.
+   * This is not necessarily the same as the number returned by
+   * [EMAIL PROTECTED] #getFreeSpace()}.
+   * 
+   * <strong>Implementation note</strong>: Unlike the RI, on Linux and UNIX
+   * like systems this methods take into account the reserved space for the
+   * "root" user. This means that the returned results will be a little
+   * different if a normal user or root perform the query.
+   * 
+   * Also, the bytes returned should be interpreted as an hint, and may be
+   * different at each call of this method or even right after the method
+   * returns.
+   * 
+   * @return the number of usable bytes in this partition. 
+   * @since 1.6
+   */
+  public long getUsableSpace()
+  {
+    // check security manager.
+    SecurityManager s = System.getSecurityManager();
+    if (s != null)
+      s.checkPermission(new RuntimePermission("getFileSystemAttributes"));
+    checkRead();
+    
+    // root users can use the reserved extra space
+    String user = System.getProperty("user.name");
+    if (user != null && user.equals("root"))
+      return VMFile.getFreeSpace(path);
+    
+    return VMFile.getUsableSpace(path);
+  }
+  
+  /**
    * This method sets the file represented by this object to be read only.
    * A read only file or directory cannot be modified.  Please note that 
    * GNU systems allow read only files to be deleted if the directory it
Index: native/jni/java-io/java_io_VMFile.c
===================================================================
RCS file: /sources/classpath/classpath/native/jni/java-io/java_io_VMFile.c,v
retrieving revision 1.15
diff -u -r1.15 java_io_VMFile.c
--- native/jni/java-io/java_io_VMFile.c	9 Feb 2007 19:51:07 -0000	1.15
+++ native/jni/java-io/java_io_VMFile.c	6 Nov 2007 13:03:33 -0000
@@ -334,6 +334,94 @@
   return set_file_permissions (env, name, executable, ownerOnly,
                                CPFILE_FLAG_EXEC);
 }
+
+/*************************************************************************/
+
+JNIEXPORT jlong JNICALL
+Java_java_io_VMFile_getTotalSpace (JNIEnv *env,
+                                   jclass clazz __attribute__ ((__unused__)),
+                                   jstring path)
+{
+#ifndef WITHOUT_FILESYSTEM
+  
+  jlong result;
+  const char *_path = NULL;
+  
+  _path = (*env)->GetStringUTFChars (env, path, 0);
+  if (_path == NULL)
+    {
+      return 0L;
+    }
+
+  result = cpio_df (_path, TOTAL);
+
+  (*env)->ReleaseStringUTFChars (env, path, _path);
+
+  return result;
+
+#else /* not WITHOUT_FILESYSTEM */
+  return 0L;
+#endif /* not WITHOUT_FILESYSTEM */  
+}
+
+/*************************************************************************/
+
+JNIEXPORT jlong JNICALL
+Java_java_io_VMFile_getFreeSpace (JNIEnv *env,
+                                  jclass clazz __attribute__ ((__unused__)),
+                                  jstring path)
+{
+#ifndef WITHOUT_FILESYSTEM
+  
+  jlong result;
+  const char *_path = NULL;
+  
+  _path = (*env)->GetStringUTFChars (env, path, 0);
+  if (_path == NULL)
+    {
+      return 0L;
+    }
+
+  result = cpio_df (_path, FREE);
+
+  (*env)->ReleaseStringUTFChars (env, path, _path);
+
+  return result;
+
+#else /* not WITHOUT_FILESYSTEM */
+  return 0L;
+#endif /* not WITHOUT_FILESYSTEM */  
+}
+
+/*************************************************************************/
+
+JNIEXPORT jlong JNICALL
+Java_java_io_VMFile_getUsableSpace (JNIEnv *env,
+                                    jclass clazz __attribute__ ((__unused__)),
+                                    jstring path)
+{
+#ifndef WITHOUT_FILESYSTEM
+  
+  jlong result;
+  const char *_path = NULL;
+  
+  _path = (*env)->GetStringUTFChars (env, path, 0);
+  if (_path == NULL)
+    {
+      return 0L;
+    }
+
+  result = cpio_df (_path, USABLE);
+
+  (*env)->ReleaseStringUTFChars (env, path, _path);
+
+  return result;
+
+#else /* not WITHOUT_FILESYSTEM */
+  return 0L;
+#endif /* not WITHOUT_FILESYSTEM */  
+}
+
 /*************************************************************************/
 
 /*
Index: vm/reference/java/io/VMFile.java
===================================================================
RCS file: /sources/classpath/classpath/vm/reference/java/io/VMFile.java,v
retrieving revision 1.10
diff -u -r1.10 VMFile.java
--- vm/reference/java/io/VMFile.java	9 Feb 2007 19:51:07 -0000	1.10
+++ vm/reference/java/io/VMFile.java	6 Nov 2007 13:03:35 -0000
@@ -117,6 +117,21 @@
   static native boolean mkdir(String dirpath);
 
   /**
+   * Gets the total bytes of the filesystem named by path.
+   */
+  public static native long getTotalSpace(String path);
+  
+  /**
+   * Gets the total free bytes of the filesystem named by path.
+   */
+  public static native long getFreeSpace(String path);
+  
+  /**
+   * Gets the available bytes of the filesystem named by path.
+   */
+  public static native long getUsableSpace(String path);
+  
+  /**
    * Set the read permission of the file.
    */
   public static synchronized native boolean setReadable(String path,

Reply via email to