gcc/libjava/java/io/natFile.cc
Bryce McKinlay f404754042 1.3-Compliant Implementation of java.io.File.
* java/lang/natSystem.cc (init_properties): Get "file.separator",
	"path.separator", and "java.io.tmpdir" from the File class, instead
	of setting them explicitly.
	* java/io/File.java: Do not canonicalize paths for security manager
	checks. Call init_native() from static initializer. Do not pass path
	argument to native methods. New native method declarations. Some
	security manager checks moved to checkWrite().
	(equals): Check file system case sensitivity and act appropriatly.
	(hashCode): Likewise.
	(isHidden): New method implemented.
	(performList): Changed prototype. Now takes a class argument specifying
	the class of the returned array: Strings or File objects. Also added
	FileFilter argument.
	(listFiles): New variants with "File" return type implemented.
	(createTempFile): Use createNewFile(). Use maxPathLen.
	(setReadOnly): New method implemented.
	(listRoots): Likewise.
	(compareTo): Likewise.
	(setLastModified): Likewise.
	(checkWrite): New method.
	(setPath): Removed.
	* java/io/natFile.cc: Various functions no longer take canonical path
	argument.
	(stat): Handle ISHIDDEN query.
	(isAbsolute): Remove WIN32 cruft.
	(performList): New arguments. Handle returning either File[] or
	String[] arrays. Check with FileFilter or FilenameFilter arguments as
	appropriate. Use an ArrayList, not a Vector, for the temporary list.
	(performSetReadOnly): New method implemented.
	(performListRoots): Likewise.
	(performSetLastModified): Likewise.
	(performCreate): Likewise.
	(init_native): New initialization function.
	* java/io/natFileWin32.cc: Various functions no longer take canonical
	path argument.
	(stat): Add FIXME about ISHIDDEN query.
	(performList): New arguments. Handle returning either File[] or String[]
	arrays. Check with FileFilter or FilenameFilter arguments as
	appropriate. Use an ArrayList, not a Vector, for the temporary list.
	(performSetReadOnly): New. Stubbed.
	(performListRoots): Likewise.
	(performSetLastModified): Likewise.
	(performCreate): Likewise.
	(init_native) New initialization function.
	* configure.in: Check for utime() and chmod().
	* configure: Rebuilt.
	* include/config.h.in: Rebuilt.

	Resolves PR libgcj/1759.

From-SVN: r40985
2001-04-01 12:16:40 +01:00

351 lines
7.2 KiB
C++

// natFile.cc - Native part of File class for POSIX.
/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#include <config.h>
#include <stdio.h>
#include <errno.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <stdlib.h>
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif
#include <string.h>
#include <utime.h>
#include <gcj/cni.h>
#include <jvm.h>
#include <java/io/File.h>
#include <java/io/IOException.h>
#include <java/util/ArrayList.h>
#include <java/lang/String.h>
#include <java/io/FilenameFilter.h>
#include <java/io/FileFilter.h>
#include <java/lang/System.h>
jboolean
java::io::File::access (jint query)
{
char buf[MAXPATHLEN];
jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
// FIXME?
buf[total] = '\0';
JvAssert (query == READ || query == WRITE || query == EXISTS);
#ifdef HAVE_ACCESS
int mode;
if (query == READ)
mode = R_OK;
else if (query == WRITE)
mode = W_OK;
else
mode = F_OK;
return ::access (buf, mode) == 0;
#else
return false;
#endif
}
jboolean
java::io::File::stat (jint query)
{
char buf[MAXPATHLEN];
jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
// FIXME?
buf[total] = '\0';
if (query == ISHIDDEN)
return (getName()->charAt(0) == '.');
#ifdef HAVE_STAT
struct stat sb;
if (::stat (buf, &sb))
return false;
JvAssert (query == DIRECTORY || query == ISFILE);
jboolean r = S_ISDIR (sb.st_mode);
return query == DIRECTORY ? r : ! r;
#else
return false;
#endif
}
jlong
java::io::File::attr (jint query)
{
char buf[MAXPATHLEN];
jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
// FIXME?
buf[total] = '\0';
#ifdef HAVE_STAT
struct stat sb;
// FIXME: not sure about return value here.
if (::stat (buf, &sb))
return 0;
JvAssert (query == MODIFIED || query == LENGTH);
return query == MODIFIED ? (jlong)sb.st_mtime * 1000 : sb.st_size;
#else
// There's no good choice here.
return 23;
#endif
}
jstring
java::io::File::getCanonicalPath (void)
{
char buf[MAXPATHLEN], buf2[MAXPATHLEN];
jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
// FIXME?
buf[total] = '\0';
#ifdef HAVE_REALPATH
if (realpath (buf, buf2) == NULL)
throw new IOException (JvNewStringLatin1 (strerror (errno)));
// FIXME: what encoding to assume for file names? This affects many
// calls.
return JvNewStringUTF (buf2);
#else
return JvNewStringUTF (buf);
#endif
}
jboolean
java::io::File::isAbsolute (void)
{
return path->charAt(0) == '/';
}
#ifdef HAVE_DIRENT_H
#if defined(__JV_POSIX_THREADS__) && defined(HAVE_READDIR_R)
static struct dirent *
get_entry (DIR *dir, struct dirent *e)
{
struct dirent *r;
if (readdir_r (dir, e, &r) || r == NULL)
return NULL;
return e;
}
#else /* defined(__JV_POSIX_THREADS__) && defined(HAVE_READDIR_R) */
static struct dirent *
get_entry (DIR *dir, struct dirent *)
{
return readdir (dir);
}
#endif /* defined(__JV_POSIX_THREADS__) && defined(HAVE_READDIR_R) */
#endif /* HAVE_DIRENT_H */
jobjectArray
java::io::File::performList (java::io::FilenameFilter *filter,
java::io::FileFilter *fileFilter,
java::lang::Class *result_type)
{
#ifdef HAVE_DIRENT_H
char buf[MAXPATHLEN];
jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
// FIXME?
buf[total] = '\0';
DIR *dir = opendir (buf);
if (! dir)
return NULL;
java::util::ArrayList *list = new java::util::ArrayList ();
struct dirent *d, d2;
while ((d = get_entry (dir, &d2)) != NULL)
{
// Omit "." and "..".
if (d->d_name[0] == '.'
&& (d->d_name[1] == '\0'
|| (d->d_name[1] == '.' && d->d_name[2] == '\0')))
continue;
jstring name = JvNewStringUTF (d->d_name);
if (filter && ! filter->accept(this, name))
continue;
if (result_type == &java::io::File::class$)
{
java::io::File *file = new java::io::File (this, name);
if (fileFilter && ! fileFilter->accept(file))
continue;
list->add(file);
}
else
list->add(name);
}
closedir (dir);
jobjectArray ret = JvNewObjectArray (list->size(), result_type, NULL);
list->toArray(ret);
return ret;
#else /* HAVE_DIRENT_H */
return NULL;
#endif /* HAVE_DIRENT_H */
}
jboolean
java::io::File::performMkdir (void)
{
char buf[MAXPATHLEN];
jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
// FIXME?
buf[total] = '\0';
#ifdef HAVE_MKDIR
return ::mkdir (buf, 0755) == 0;
#else
return false;
#endif
}
jboolean
java::io::File::performSetReadOnly (void)
{
char buf[MAXPATHLEN];
jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
// FIXME?
buf[total] = '\0';
#ifdef HAVE_STAT && HAVE_CHMOD
struct stat sb;
if (::stat (buf, &sb))
return false;
if (::chmod(buf, sb.st_mode & 0555))
return false;
return true;
#else
return false;
#endif
}
static JArray<java::io::File *> *unixroot;
JArray< ::java::io::File *>*
java::io::File::performListRoots ()
{
if (unixroot == NULL)
{
::java::io::File *f = new ::java::io::File (JvNewStringLatin1 ("/"));
unixroot = reinterpret_cast <JArray<java::io::File *>*>
(JvNewObjectArray (1, &java::io::File::class$, f));
elements (unixroot) [0] = f;
}
return unixroot;
}
jboolean
java::io::File::performRenameTo (File *dest)
{
char buf[MAXPATHLEN];
jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
// FIXME?
buf[total] = '\0';
char buf2[MAXPATHLEN];
total = JvGetStringUTFRegion (dest->path, 0, dest->path->length(), buf2);
// FIXME?
buf2[total] = '\0';
#ifdef HAVE_RENAME
return ::rename (buf, buf2) == 0;
#else
return false;
#endif
}
jboolean
java::io::File::performSetLastModified (jlong time)
{
#ifdef HAVE_UTIME
utimbuf tb;
char buf[MAXPATHLEN];
jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
// FIXME?
buf[total] = '\0';
tb.actime = time / 1000;
tb.modtime = time / 1000;
return ::utime (buf, &tb);
#else
return false;
#endif
}
jboolean
java::io::File::performCreate (void)
{
char buf[MAXPATHLEN];
jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
// FIXME?
buf[total] = '\0';
int fd = ::open (buf, O_CREAT | O_EXCL, 0644);
if (fd < 0)
{
if (errno == EEXIST)
return false;
throw new IOException (JvNewStringLatin1 (strerror (errno)));
}
else
{
::close (fd);
return true;
}
}
jboolean
java::io::File::performDelete (void)
{
char buf[MAXPATHLEN];
jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
// FIXME?
buf[total] = '\0';
#ifdef HAVE_UNLINK
#ifdef HAVE_RMDIR
if (! ::rmdir (buf))
return true;
#endif // HAVE_RMDIR
if (errno == ENOTDIR)
return ::unlink (buf) == 0;
#endif // HAVE_UNLINK
return false;
}
void
java::io::File::init_native ()
{
separator = JvNewStringLatin1 ("/");
pathSeparator = JvNewStringLatin1 (":");
char *tmp = ::getenv("TMPDIR");
if (! tmp)
tmp = "/tmp";
tmpdir = JvNewStringLatin1 (tmp);
maxPathLen = MAXPATHLEN;
caseSensitive = true;
}