Hello! I have implemented few of the missing 1.6 methods for java.io.File.
I would like some comments about them. I have added 3 flags and 2 functions to classpath cpio: #define CPFILE_FLAG_EXEC 0x0100 #define CPFILE_FLAG_USR 0x0400 #define CPFILE_FLAG_OFF 0x0800 JNIEXPORT int cpio_chmod (const char *filename, int permissions); JNIEXPORT int cpio_statFlag (const char *filename, unsigned int flag); and 3 native methods to java_io_VMFile/VMFile: Java_java_io_VMFile_setReadable Java_java_io_VMFile_setWritable Java_java_io_VMFile_setExecutable I have also added the stubs for the other missing methods, which will be implemented shortly after this patch is committed. I'm still testing the patch and I have to write mauve tests, so things can change if I find I've done something horrible :), but I would like some comments on it before continue. Thank you, Mario -- Lima Software, SO.PR.IND. s.r.l. http://www.limasoftware.net/ pgp key: http://subkeys.pgp.net/ 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: /cvsroot/classpath/classpath/native/jni/native-lib/cpio.c,v retrieving revision 1.6 diff -u -r1.6 cpio.c --- native/jni/native-lib/cpio.c 25 Oct 2006 00:33:26 -0000 1.6 +++ native/jni/native-lib/cpio.c 28 Dec 2006 01:49:14 -0000 @@ -352,6 +352,75 @@ return 0; } +int cpio_chmod (const char *filename, int permissions) +{ + struct stat statbuf; + int perms = 0; + + if (stat(filename, &statbuf) < 0) + return errno; + + /* check for permission flags */ + if (permissions & CPFILE_FLAG_USR) + { + if (permissions & CPFILE_FLAG_READ) + perms |= S_IRUSR; + + if (permissions & CPFILE_FLAG_WRITE) + perms |= S_IWUSR; + + if (permissions & CPFILE_FLAG_EXEC) + perms |= S_IXUSR; + } + else + { + if (permissions & CPFILE_FLAG_READ) + perms |= (S_IRUSR | S_IRGRP | S_IROTH); + + if (permissions & CPFILE_FLAG_WRITE) + perms |= (S_IWUSR | S_IWGRP | S_IWOTH); + + if (permissions & CPFILE_FLAG_EXEC) + perms |= (S_IXUSR | S_IXGRP | S_IXOTH); + } + + if (permissions & CPFILE_FLAG_OFF) + perms = statbuf.st_mode & ~perms; + else + perms = statbuf.st_mode | perms; + + if (chmod(filename, perms) < 0) + return errno; + + return 0; +} + +int cpio_statFlag (const char *filename, unsigned int flag) +{ + struct stat statbuf; + unsigned int perms = 0; + + if (stat(filename, &statbuf) < 0) + return errno; + + switch (flag) + { + case CPFILE_FLAG_READ: + perms |= S_IRUSR; + break; + + case CPFILE_FLAG_WRITE: + perms |= S_IWUSR; + break; + + case CPFILE_FLAG_EXEC: + perms |= S_IXUSR; + break; + } + + return ((statbuf.st_mode & perms) == perms) ? 0 : 1; +} + int cpio_isFileExists (const char *filename) { struct stat statbuf; Index: native/jni/native-lib/cpio.h =================================================================== RCS file: /cvsroot/classpath/classpath/native/jni/native-lib/cpio.h,v retrieving revision 1.5 diff -u -r1.5 cpio.h --- native/jni/native-lib/cpio.h 25 Oct 2006 00:33:26 -0000 1.5 +++ native/jni/native-lib/cpio.h 28 Dec 2006 01:49:14 -0000 @@ -48,6 +48,9 @@ #define CPFILE_FLAG_BINARY 0x0020 #define CPFILE_FLAG_READ 0x0040 #define CPFILE_FLAG_WRITE 0x0080 +#define CPFILE_FLAG_EXEC 0x0100 +#define CPFILE_FLAG_USR 0x0400 +#define CPFILE_FLAG_OFF 0x0800 #define CPFILE_PERMISSION_NORMAL 1 @@ -70,6 +73,8 @@ #define CPFILE_DIRECTORY 1 JNIEXPORT int cpio_setFileReadonly (const char *filename); +JNIEXPORT int cpio_chmod (const char *filename, int permissions); +JNIEXPORT int cpio_statFlag (const char *filename, unsigned int flag); JNIEXPORT int cpio_isFileExists (const char *filename); JNIEXPORT int cpio_checkType (const char *filename, jint *entryType); JNIEXPORT int cpio_getModificationTime (const char *filename, jlong *mtime); Index: java/io/File.java =================================================================== RCS file: /cvsroot/classpath/classpath/java/io/File.java,v retrieving revision 1.69 diff -u -r1.69 File.java --- java/io/File.java 10 Dec 2006 20:25:44 -0000 1.69 +++ java/io/File.java 28 Dec 2006 01:49:13 -0000 @@ -39,6 +39,7 @@ package java.io; +import gnu.classpath.NotImplementedException; import gnu.classpath.SystemProperties; import java.net.MalformedURLException; @@ -164,6 +165,29 @@ } /** + * This method tests whether or not the current thread is allowed to + * to execute the file pointed to by this object. This will be true if and + * and only if 1) the file exists and 2) the <code>SecurityManager</code> + * (if any) allows access to the file via it's <code>checkExec</code> + * method 3) the file is executable. + * + * @return <code>true</code> if execution is allowed, + * <code>false</code> otherwise + * + * @exception SecurityException If the <code>SecurityManager</code> + * does not allow access to the file + */ + public boolean canExecute() + { + if (!VMFile.exists(path)) + return false; + + checkExec(); + + return VMFile.canExecute(path); + } + + /** * This method creates a new file of zero length with the same name as * the path of this <code>File</code> object if an only if that file * does not already exist. @@ -1123,6 +1147,173 @@ } /** + * This method sets the owner's read permission for the File represented by + * this object. + * + * It is the same as calling <code>setReadable(readable, true)</code>. + * + * @param <code>readable</code> <code>true</code> to set read permission, + * <code>false</code> to unset the read permission. + * @return <code>true</code> if the file permissions are changed, + * <code>false</code> otherwise. + * @exception SecurityException If write access of the file is not permitted. + * @see #setReadable(boolean, boolean) + */ + public boolean setReadable(boolean readable) + { + return setReadable(readable, true); + } + + /** + * This method sets the read permissions for the File represented by + * this object. + * + * If <code>ownerOnly</code> is set to <code>true</code> then only the + * read permission bit for the owner of the file is changed. + * + * If <code>ownerOnly</code> is set to <code>false</code>, the file + * permissions are changed so that the file can be read by everyone. + * + * On unix like systems this sets the <code>user</code>, <code>group</code> + * and <code>other</code> read bits and is equal to call + * <code>chmod a+r</code> on the file. + * + * @param <code>readable</code> <code>true</code> to set read permission, + * <code>false</code> to unset the read permission. + * @param <code>ownerOnly</code> <code>true</code> to set read permission + * for owner only, <code>false</code> for all. + * @return <code>true</code> if the file permissions are changed, + * <code>false</code> otherwise. + * @exception SecurityException If write access of the file is not permitted. + * @see #setReadable(boolean) + */ + public boolean setReadable(boolean readable, boolean ownerOnly) + { + checkWrite(); + return VMFile.setReadable(path, readable, ownerOnly); + } + + /** + * This method sets the owner's write permission for the File represented by + * this object. + * + * It is the same as calling <code>setWritable(readable, true)</code>. + * + * @param <code>writable</code> <code>true</code> to set write permission, + * <code>false</code> to unset write permission. + * @return <code>true</code> if the file permissions are changed, + * <code>false</code> otherwise. + * @exception SecurityException If write access of the file is not permitted. + * @see #setWritable(boolean, boolean) + */ + public boolean setWritable(boolean writable) + { + return setWritable(writable, true); + } + + /** + * This method sets the write permissions for the File represented by + * this object. + * + * If <code>ownerOnly</code> is set to <code>true</code> then only the + * write permission bit for the owner of the file is changed. + * + * If <code>ownerOnly</code> is set to <code>false</code>, the file + * permissions are changed so that the file can be written by everyone. + * + * On unix like systems this set the <code>user</code>, <code>group</code> + * and <code>other</code> write bits and is equal to call + * <code>chmod a+w</code> on the file. + * + * @param <code>writable</code> <code>true</code> to set write permission, + * <code>false</code> to unset write permission. + * @param <code>ownerOnly</code> <code>true</code> to set write permission + * for owner only, <code>false</code> for all. + * @return <code>true</code> if the file permissions are changed, + * <code>false</code> otherwise. + * @exception SecurityException If write access of the file is not permitted. + * @see #setWritable(boolean) + */ + public boolean setWritable(boolean writable, boolean ownerOnly) + { + checkWrite(); + return VMFile.setWritable(path, writable, ownerOnly); + } + + /** + * This method sets the owner's execute permission for the File represented + * by this object. + * + * It is the same as calling <code>setExecutable(readable, true)</code>. + * + * @param executable + * @return + */ + public boolean setExecutable(boolean executable) + { + return setExecutable(executable, true); + } + + /** + * This method sets the execute permissions for the File represented by + * this object. + * + * If <code>ownerOnly</code> is set to <code>true</code> then only the + * execute permission bit for the owner of the file is changed. + * + * If <code>ownerOnly</code> is set to <code>false</code>, the file + * permissions are changed so that the file can be executed by everyone. + * + * On unix like systems this set the <code>user</code>, <code>group</code> + * and <code>other</code> write bits and is equal to call + * <code>chmod a+x</code> on the file. + * + * @param <code>executable</code> <code>true</code> to set write permission, + * <code>false</code> to unset write permission. + * @param <code>ownerOnly</code> <code>true</code> to set write permission + * for owner only, <code>false</code> for all. + * @return <code>true</code> if the file permissions are changed, + * <code>false</code> otherwise. + * @exception SecurityException If write access of the file is not permitted. + * @see #setExecutable(boolean) + */ + public boolean setExecutable(boolean executable, boolean ownerOnly) + { + checkWrite(); + return VMFile.setExecutable(path, executable, ownerOnly); + } + + /** + * + * @return + */ + public long getTotalSpace() + throws NotImplementedException + { + return 0L; + } + + /** + * + * @return + */ + public long getFreeSpace() + throws NotImplementedException + { + return 0L; + } + + /** + * + * @return + */ + public long getUsableSpace() + throws NotImplementedException + { + return 0L; + } + + /** * 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 @@ -1315,6 +1506,15 @@ s.checkRead(path); } + private void checkExec() + { + // Check the SecurityManager + SecurityManager s = System.getSecurityManager(); + + if (s != null) + s.checkExec(path); + } + /** * Calling this method requests that the file represented by this object * be deleted when the virtual machine exits. Note that this request cannot Index: native/jni/java-io/java_io_VMFile.c =================================================================== RCS file: /cvsroot/classpath/classpath/native/jni/java-io/java_io_VMFile.c,v retrieving revision 1.14 diff -u -r1.14 java_io_VMFile.c --- native/jni/java-io/java_io_VMFile.c 23 Sep 2006 05:17:45 -0000 1.14 +++ native/jni/java-io/java_io_VMFile.c 28 Dec 2006 01:49:14 -0000 @@ -189,6 +189,46 @@ /*************************************************************************/ /* + * This method checks to see if we have execute permission on a file. + * + * Class: java_io_VMFile + * Method: canExecute + * Signature: (Ljava/lang/String;)Z + */ + +JNIEXPORT jboolean JNICALL +Java_java_io_VMFile_canExecute (JNIEnv * env, + jclass clazz __attribute__ ((__unused__)), + jstring name) +{ +#ifndef WITHOUT_FILESYSTEM + const char *filename; + int result; + + /* Don't use the JCL convert function because it throws an exception + on failure */ + filename = (*env)->GetStringUTFChars (env, name, 0); + if (filename == NULL) + { + return JNI_FALSE; + } + + result = cpio_statFlag (filename, CPFILE_FLAG_EXEC); + + (*env)->ReleaseStringUTFChars (env, name, filename); + if (result != CPNATIVE_OK) + return JNI_FALSE; + + return JNI_TRUE; +#else /* not WITHOUT_FILESYSTEM */ + return JNI_FALSE; +#endif /* not WITHOUT_FILESYSTEM */ +} + + +/*************************************************************************/ + +/* * This method makes a file read only. * * Class: java_io_VMFile @@ -225,6 +265,153 @@ /*************************************************************************/ /* + * This method changes the read permission bit of a file. + * + * Class: java_io_VMFile + * Method: setReadable + * Signature: (Ljava/lang/String;ZZ)Z + */ +JNIEXPORT jboolean JNICALL +Java_java_io_VMFile_setReadable (JNIEnv *env, + jclass clazz __attribute__ ((__unused__)), + jstring name, + jboolean readable, + jboolean ownerOnly) +{ +#ifndef WITHOUT_FILESYSTEM + const char *filename; + int permissions = CPFILE_FLAG_READ; + int result = JNI_FALSE; + + /* Don't use the JCL convert function because it throws an exception + on failure */ + filename = (*env)->GetStringUTFChars (env, name, 0); + if (filename == NULL) + { + return 0; + } + + if (ownerOnly) + { + permissions |= CPFILE_FLAG_USR; + } + + if (!readable) + { + permissions |= CPFILE_FLAG_OFF; + } + + result = cpio_chmod (filename, permissions); + (*env)->ReleaseStringUTFChars (env, name, filename); + + return result == CPNATIVE_OK ? JNI_TRUE : JNI_FALSE; + +#else /* not WITHOUT_FILESYSTEM */ + return JNI_FALSE; +#endif /* not WITHOUT_FILESYSTEM */ +} + + +/*************************************************************************/ + +/* + * This method changes the write permission bit of a file. + * + * Class: java_io_VMFile + * Method: setWritable + * Signature: (Ljava/lang/String;ZZ)Z + */ +JNIEXPORT jboolean JNICALL +Java_java_io_VMFile_setWritable (JNIEnv *env, + jclass clazz __attribute__ ((__unused__)), + jstring name, + jboolean writable, + jboolean ownerOnly) +{ +#ifndef WITHOUT_FILESYSTEM + const char *filename; + int permissions = CPFILE_FLAG_WRITE; + int result = JNI_FALSE; + + /* Don't use the JCL convert function because it throws an exception + on failure */ + filename = (*env)->GetStringUTFChars (env, name, 0); + if (filename == NULL) + { + return 0; + } + + if (ownerOnly) + { + permissions |= CPFILE_FLAG_USR; + } + + if (!writable) + { + permissions |= CPFILE_FLAG_OFF; + } + + result = cpio_chmod (filename, permissions); + (*env)->ReleaseStringUTFChars (env, name, filename); + + return result == CPNATIVE_OK ? JNI_TRUE : JNI_FALSE; + +#else /* not WITHOUT_FILESYSTEM */ + return JNI_FALSE; +#endif /* not WITHOUT_FILESYSTEM */ +} + +/*************************************************************************/ + +/* + * This method changes the execute permission bit of a file. + * + * Class: java_io_VMFile + * Method: setExecutable + * Signature: (Ljava/lang/String;ZZ)Z + */ +JNIEXPORT jboolean JNICALL +Java_java_io_VMFile_setExecutable (JNIEnv *env, + jclass clazz __attribute__ ((__unused__)), + jstring name, + jboolean executable, + jboolean ownerOnly) +{ +#ifndef WITHOUT_FILESYSTEM + const char *filename; + int permissions = CPFILE_FLAG_EXEC; + int result = JNI_FALSE; + + /* Don't use the JCL convert function because it throws an exception + on failure */ + filename = (*env)->GetStringUTFChars (env, name, 0); + if (filename == NULL) + { + return 0; + } + + if (ownerOnly) + { + permissions |= CPFILE_FLAG_USR; + } + + if (!executable) + { + permissions |= CPFILE_FLAG_OFF; + } + + result = cpio_chmod (filename, permissions); + (*env)->ReleaseStringUTFChars (env, name, filename); + + return result == CPNATIVE_OK ? JNI_TRUE : JNI_FALSE; + +#else /* not WITHOUT_FILESYSTEM */ + return JNI_FALSE; +#endif /* not WITHOUT_FILESYSTEM */ +} +/*************************************************************************/ + +/* * This method checks to see if a file exists. * * Class: java_io_VMFile Index: vm/reference/java/io/VMFile.java =================================================================== RCS file: /cvsroot/classpath/classpath/vm/reference/java/io/VMFile.java,v retrieving revision 1.9 diff -u -r1.9 VMFile.java --- vm/reference/java/io/VMFile.java 21 Aug 2006 09:23:01 -0000 1.9 +++ vm/reference/java/io/VMFile.java 28 Dec 2006 01:49:16 -0000 @@ -116,6 +116,27 @@ */ static native boolean mkdir(String dirpath); + /** + * Set the read permission of the file. + */ + public static native boolean setReadable(String path, + boolean readable, + boolean ownerOnly); + + /** + * Set the write permission of the file. + */ + public static native boolean setWritable(String path, + boolean writable, + boolean ownerOnly); + + /** + * Set the execute permission of the file. + */ + public static native boolean setExecutable(String path, + boolean executable, + boolean ownerOnly); + /* * This native method does the actual check of whether or not a file * is a plain file or not. It also handles the existence check to @@ -127,7 +148,7 @@ * This native method checks file permissions for writing */ static synchronized native boolean canWrite(String path); - + /** * This methods checks if a directory can be written to. */ @@ -150,6 +171,11 @@ */ static synchronized native boolean canRead(String path); + /** + * This native method checks file permissions for execution + */ + static synchronized native boolean canExecute(String path); + /* * This method does the actual check of whether or not a file is a * directory or not. It also handle the existence check to eliminate