2011-07-13 14:25:21 +00:00
|
|
|
/* Copyright (c) 2008-2011, Avian Contributors
|
2008-02-19 18:06:52 +00:00
|
|
|
|
|
|
|
Permission to use, copy, modify, and/or distribute this software
|
|
|
|
for any purpose with or without fee is hereby granted, provided
|
|
|
|
that the above copyright notice and this permission notice appear
|
|
|
|
in all copies.
|
|
|
|
|
|
|
|
There is NO WARRANTY for this software. See license.txt for
|
|
|
|
details. */
|
|
|
|
|
2007-07-27 00:06:05 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
2011-06-01 19:56:03 +00:00
|
|
|
#include "jni.h"
|
2007-08-27 13:46:17 +00:00
|
|
|
#include "jni-util.h"
|
2007-07-27 00:06:05 +00:00
|
|
|
|
2009-08-27 00:26:44 +00:00
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
|
2008-11-11 15:20:49 +00:00
|
|
|
# include <windows.h>
|
2007-07-27 00:06:05 +00:00
|
|
|
# include <io.h>
|
2009-06-05 20:31:53 +00:00
|
|
|
# include <direct.h>
|
2009-08-27 00:26:44 +00:00
|
|
|
# include <share.h>
|
2007-10-24 17:24:19 +00:00
|
|
|
|
2010-09-12 20:46:14 +00:00
|
|
|
# define ACCESS _waccess
|
2007-07-27 00:06:05 +00:00
|
|
|
# define CLOSE _close
|
|
|
|
# define READ _read
|
|
|
|
# define WRITE _write
|
2010-04-20 16:03:07 +00:00
|
|
|
# define STAT _wstat
|
2007-07-27 00:06:05 +00:00
|
|
|
# define STRUCT_STAT struct _stat
|
2010-04-20 16:03:07 +00:00
|
|
|
# define MKDIR(path, mode) _wmkdir(path)
|
|
|
|
# define UNLINK _wunlink
|
|
|
|
# define RENAME _wrename
|
2007-07-27 00:06:05 +00:00
|
|
|
# define OPEN_MASK O_BINARY
|
2009-08-27 00:26:44 +00:00
|
|
|
|
|
|
|
# ifdef _MSC_VER
|
2011-01-21 23:14:21 +00:00
|
|
|
# define S_ISREG(x) ((x) & _S_IFREG)
|
|
|
|
# define S_ISDIR(x) ((x) & _S_IFDIR)
|
2009-08-27 00:26:44 +00:00
|
|
|
# define S_IRUSR _S_IREAD
|
|
|
|
# define S_IWUSR _S_IWRITE
|
2011-01-21 23:14:21 +00:00
|
|
|
# define W_OK 2
|
|
|
|
# define R_OK 4
|
2009-08-27 00:26:44 +00:00
|
|
|
# else
|
2010-04-20 16:03:07 +00:00
|
|
|
# define OPEN _wopen
|
|
|
|
# define CREAT _wcreat
|
2009-08-27 00:26:44 +00:00
|
|
|
# endif
|
|
|
|
|
2010-04-20 16:03:07 +00:00
|
|
|
# define GET_CHARS GetStringChars
|
|
|
|
# define RELEASE_CHARS(path, chars) ReleaseStringChars(path, reinterpret_cast<const jchar*>(chars))
|
|
|
|
|
|
|
|
typedef wchar_t char_t;
|
|
|
|
|
2009-08-27 00:26:44 +00:00
|
|
|
#else // not PLATFORM_WINDOWS
|
|
|
|
|
|
|
|
# include <dirent.h>
|
2007-07-27 00:06:05 +00:00
|
|
|
# include <unistd.h>
|
2008-11-11 15:20:49 +00:00
|
|
|
# include "sys/mman.h"
|
2007-10-24 17:24:19 +00:00
|
|
|
|
2010-09-12 20:46:14 +00:00
|
|
|
# define ACCESS access
|
2007-07-27 00:06:05 +00:00
|
|
|
# define OPEN open
|
|
|
|
# define CLOSE close
|
|
|
|
# define READ read
|
|
|
|
# define WRITE write
|
|
|
|
# define STAT stat
|
|
|
|
# define STRUCT_STAT struct stat
|
|
|
|
# define MKDIR mkdir
|
|
|
|
# define CREAT creat
|
2007-09-12 01:13:05 +00:00
|
|
|
# define UNLINK unlink
|
2010-04-20 16:03:07 +00:00
|
|
|
# define RENAME rename
|
2007-07-27 00:06:05 +00:00
|
|
|
# define OPEN_MASK 0
|
2009-08-27 00:26:44 +00:00
|
|
|
|
2010-04-20 16:03:07 +00:00
|
|
|
# define GET_CHARS GetStringUTFChars
|
|
|
|
# define RELEASE_CHARS ReleaseStringUTFChars
|
|
|
|
|
|
|
|
typedef char char_t;
|
|
|
|
|
2009-08-27 00:26:44 +00:00
|
|
|
#endif // not PLATFORM_WINDOWS
|
2007-07-27 00:06:05 +00:00
|
|
|
|
2008-11-11 15:20:49 +00:00
|
|
|
inline void* operator new(size_t, void* p) throw() { return p; }
|
|
|
|
|
2010-04-20 16:03:07 +00:00
|
|
|
typedef const char_t* string_t;
|
|
|
|
|
2007-07-27 00:06:05 +00:00
|
|
|
namespace {
|
|
|
|
|
2009-08-27 00:26:44 +00:00
|
|
|
#ifdef _MSC_VER
|
2010-04-20 16:03:07 +00:00
|
|
|
inline int
|
|
|
|
OPEN(string_t path, int mask, int mode)
|
2009-08-27 00:26:44 +00:00
|
|
|
{
|
2010-04-20 16:03:07 +00:00
|
|
|
int fd;
|
|
|
|
if (_wsopen_s(&fd, path, mask, _SH_DENYNO, mode) == 0) {
|
|
|
|
return fd;
|
2009-08-27 00:26:44 +00:00
|
|
|
} else {
|
2010-04-20 16:03:07 +00:00
|
|
|
return -1;
|
2009-08-27 00:26:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline int
|
2010-04-20 16:03:07 +00:00
|
|
|
CREAT(string_t path, int mode)
|
2009-08-27 00:26:44 +00:00
|
|
|
{
|
|
|
|
return OPEN(path, _O_CREAT, mode);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-07-27 00:06:05 +00:00
|
|
|
inline bool
|
2010-04-20 16:03:07 +00:00
|
|
|
exists(string_t path)
|
2007-07-27 00:06:05 +00:00
|
|
|
{
|
|
|
|
STRUCT_STAT s;
|
|
|
|
return STAT(path, &s) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline int
|
2010-04-20 16:03:07 +00:00
|
|
|
doOpen(JNIEnv* e, string_t path, int mask)
|
2007-07-27 00:06:05 +00:00
|
|
|
{
|
|
|
|
int fd = OPEN(path, mask | OPEN_MASK, S_IRUSR | S_IWUSR);
|
|
|
|
if (fd == -1) {
|
2009-08-21 15:23:03 +00:00
|
|
|
if (errno == ENOENT) {
|
2009-08-27 00:26:44 +00:00
|
|
|
throwNewErrno(e, "java/io/FileNotFoundException");
|
2009-08-21 15:23:03 +00:00
|
|
|
} else {
|
2009-08-27 00:26:44 +00:00
|
|
|
throwNewErrno(e, "java/io/IOException");
|
2009-08-21 15:23:03 +00:00
|
|
|
}
|
2007-07-27 00:06:05 +00:00
|
|
|
}
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
doClose(JNIEnv* e, jint fd)
|
|
|
|
{
|
|
|
|
int r = CLOSE(fd);
|
|
|
|
if (r == -1) {
|
2009-08-27 00:26:44 +00:00
|
|
|
throwNewErrno(e, "java/io/IOException");
|
2007-07-27 00:06:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline int
|
|
|
|
doRead(JNIEnv* e, jint fd, jbyte* data, jint length)
|
|
|
|
{
|
|
|
|
int r = READ(fd, data, length);
|
|
|
|
if (r > 0) {
|
|
|
|
return r;
|
|
|
|
} else if (r == 0) {
|
|
|
|
return -1;
|
|
|
|
} else {
|
2009-08-27 00:26:44 +00:00
|
|
|
throwNewErrno(e, "java/io/IOException");
|
2007-07-27 00:06:05 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
doWrite(JNIEnv* e, jint fd, const jbyte* data, jint length)
|
|
|
|
{
|
|
|
|
int r = WRITE(fd, data, length);
|
|
|
|
if (r != length) {
|
2009-08-27 00:26:44 +00:00
|
|
|
throwNewErrno(e, "java/io/IOException");
|
2008-11-11 15:20:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-27 00:26:44 +00:00
|
|
|
#ifdef PLATFORM_WINDOWS
|
2008-11-11 15:20:49 +00:00
|
|
|
|
|
|
|
class Mapping {
|
|
|
|
public:
|
|
|
|
Mapping(uint8_t* start, size_t length, HANDLE mapping, HANDLE file):
|
|
|
|
start(start),
|
|
|
|
length(length),
|
|
|
|
mapping(mapping),
|
|
|
|
file(file)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
uint8_t* start;
|
|
|
|
size_t length;
|
|
|
|
HANDLE mapping;
|
|
|
|
HANDLE file;
|
|
|
|
};
|
|
|
|
|
|
|
|
inline Mapping*
|
2010-04-20 16:03:07 +00:00
|
|
|
map(JNIEnv* e, string_t path)
|
2008-11-11 15:20:49 +00:00
|
|
|
{
|
|
|
|
Mapping* result = 0;
|
2010-04-20 16:03:07 +00:00
|
|
|
HANDLE file = CreateFileW(path, FILE_READ_DATA, FILE_SHARE_READ, 0,
|
|
|
|
OPEN_EXISTING, 0, 0);
|
2008-11-11 15:20:49 +00:00
|
|
|
if (file != INVALID_HANDLE_VALUE) {
|
|
|
|
unsigned size = GetFileSize(file, 0);
|
|
|
|
if (size != INVALID_FILE_SIZE) {
|
|
|
|
HANDLE mapping = CreateFileMapping(file, 0, PAGE_READONLY, 0, size, 0);
|
|
|
|
if (mapping) {
|
|
|
|
void* data = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
|
|
|
|
if (data) {
|
|
|
|
void* p = allocate(e, sizeof(Mapping));
|
2009-12-17 02:25:03 +00:00
|
|
|
if (not e->ExceptionCheck()) {
|
2008-11-11 15:20:49 +00:00
|
|
|
result = new (p)
|
|
|
|
Mapping(static_cast<uint8_t*>(data), size, file, mapping);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result == 0) {
|
|
|
|
CloseHandle(mapping);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result == 0) {
|
|
|
|
CloseHandle(file);
|
|
|
|
}
|
|
|
|
}
|
2009-12-17 02:25:03 +00:00
|
|
|
if (result == 0 and not e->ExceptionCheck()) {
|
2008-11-11 15:20:49 +00:00
|
|
|
throwNew(e, "java/io/IOException", "%d", GetLastError());
|
|
|
|
}
|
|
|
|
return result;
|
2007-07-27 00:06:05 +00:00
|
|
|
}
|
|
|
|
|
2008-11-11 15:20:49 +00:00
|
|
|
inline void
|
|
|
|
unmap(JNIEnv*, Mapping* mapping)
|
|
|
|
{
|
|
|
|
UnmapViewOfFile(mapping->start);
|
|
|
|
CloseHandle(mapping->mapping);
|
|
|
|
CloseHandle(mapping->file);
|
|
|
|
free(mapping);
|
|
|
|
}
|
|
|
|
|
2009-08-27 00:26:44 +00:00
|
|
|
class Directory {
|
|
|
|
public:
|
|
|
|
Directory(): handle(0), findNext(false) { }
|
|
|
|
|
2010-04-20 16:03:07 +00:00
|
|
|
virtual string_t next() {
|
2009-08-27 00:26:44 +00:00
|
|
|
if (handle and handle != INVALID_HANDLE_VALUE) {
|
|
|
|
if (findNext) {
|
2010-04-20 16:03:07 +00:00
|
|
|
if (FindNextFileW(handle, &data)) {
|
2009-08-27 00:26:44 +00:00
|
|
|
return data.cFileName;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
findNext = true;
|
|
|
|
return data.cFileName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dispose() {
|
|
|
|
if (handle and handle != INVALID_HANDLE_VALUE) {
|
|
|
|
FindClose(handle);
|
|
|
|
}
|
|
|
|
free(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
HANDLE handle;
|
2010-04-20 16:03:07 +00:00
|
|
|
WIN32_FIND_DATAW data;
|
2009-08-27 00:26:44 +00:00
|
|
|
bool findNext;
|
|
|
|
};
|
|
|
|
|
|
|
|
#else // not PLATFORM_WINDOWS
|
2008-11-11 15:20:49 +00:00
|
|
|
|
|
|
|
class Mapping {
|
|
|
|
public:
|
|
|
|
Mapping(uint8_t* start, size_t length):
|
|
|
|
start(start),
|
|
|
|
length(length)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
uint8_t* start;
|
|
|
|
size_t length;
|
|
|
|
};
|
|
|
|
|
|
|
|
inline Mapping*
|
2010-04-20 16:03:07 +00:00
|
|
|
map(JNIEnv* e, string_t path)
|
2008-11-11 15:20:49 +00:00
|
|
|
{
|
|
|
|
Mapping* result = 0;
|
|
|
|
int fd = open(path, O_RDONLY);
|
|
|
|
if (fd != -1) {
|
|
|
|
struct stat s;
|
|
|
|
int r = fstat(fd, &s);
|
|
|
|
if (r != -1) {
|
|
|
|
void* data = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
|
|
|
if (data) {
|
|
|
|
void* p = allocate(e, sizeof(Mapping));
|
2009-12-17 02:25:03 +00:00
|
|
|
if (not e->ExceptionCheck()) {
|
2008-11-11 15:20:49 +00:00
|
|
|
result = new (p) Mapping(static_cast<uint8_t*>(data), s.st_size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close(fd);
|
|
|
|
}
|
2009-12-17 02:25:03 +00:00
|
|
|
if (result == 0 and not e->ExceptionCheck()) {
|
2009-08-27 00:26:44 +00:00
|
|
|
throwNewErrno(e, "java/io/IOException");
|
2008-11-11 15:20:49 +00:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
unmap(JNIEnv*, Mapping* mapping)
|
|
|
|
{
|
|
|
|
munmap(mapping->start, mapping->length);
|
|
|
|
free(mapping);
|
|
|
|
}
|
|
|
|
|
2009-08-27 00:26:44 +00:00
|
|
|
#endif // not PLATFORM_WINDOWS
|
2008-11-11 15:20:49 +00:00
|
|
|
|
2007-07-27 00:06:05 +00:00
|
|
|
} // namespace
|
|
|
|
|
2010-04-20 16:03:07 +00:00
|
|
|
inline string_t getChars(JNIEnv* e, jstring path) {
|
|
|
|
return reinterpret_cast<string_t>(e->GET_CHARS(path, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void releaseChars(JNIEnv* e, jstring path, string_t chars) {
|
|
|
|
e->RELEASE_CHARS(path, chars);
|
|
|
|
}
|
|
|
|
|
2007-08-21 00:24:54 +00:00
|
|
|
extern "C" JNIEXPORT jstring JNICALL
|
|
|
|
Java_java_io_File_toCanonicalPath(JNIEnv* /*e*/, jclass, jstring path)
|
|
|
|
{
|
|
|
|
// todo
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2007-07-27 00:06:05 +00:00
|
|
|
extern "C" JNIEXPORT jstring JNICALL
|
2011-08-15 22:37:15 +00:00
|
|
|
Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path)
|
2007-07-27 00:06:05 +00:00
|
|
|
{
|
2011-08-11 14:52:49 +00:00
|
|
|
#ifdef PLATFORM_WINDOWS
|
2007-07-27 00:06:05 +00:00
|
|
|
// todo
|
|
|
|
return path;
|
2011-08-11 14:52:49 +00:00
|
|
|
#else
|
|
|
|
jstring result = path;
|
|
|
|
string_t chars = getChars(e, path);
|
|
|
|
if (chars) {
|
|
|
|
if (chars[0] != '/') {
|
|
|
|
char* cwd = getcwd(NULL, 0);
|
|
|
|
if (cwd) {
|
|
|
|
unsigned size = strlen(cwd) + strlen(chars) + 2;
|
|
|
|
RUNTIME_ARRAY(char, buffer, size);
|
|
|
|
snprintf(RUNTIME_ARRAY_BODY(buffer), size, "%s/%s", cwd, chars);
|
|
|
|
result = e->NewStringUTF(RUNTIME_ARRAY_BODY(buffer));
|
|
|
|
free(cwd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
releaseChars(e, path, chars);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
#endif
|
2007-07-27 00:06:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jlong JNICALL
|
|
|
|
Java_java_io_File_length(JNIEnv* e, jclass, jstring path)
|
|
|
|
{
|
2011-09-14 17:50:56 +00:00
|
|
|
|
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
|
|
|
|
LARGE_INTEGER fileSize;
|
2011-09-14 19:27:17 +00:00
|
|
|
string_t chars = getChars(e, path);
|
|
|
|
HANDLE file = CreateFileW
|
|
|
|
(chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
|
|
|
releaseChars(e, path, chars);
|
2011-09-14 17:50:56 +00:00
|
|
|
if (file != INVALID_HANDLE_VALUE)
|
|
|
|
GetFileSizeEx(file, &fileSize);
|
2011-09-14 19:27:17 +00:00
|
|
|
else return 0;
|
2011-09-14 17:50:56 +00:00
|
|
|
CloseHandle(file);
|
2011-09-14 19:27:17 +00:00
|
|
|
return static_cast<jlong>(fileSize.QuadPart);
|
2011-09-14 17:50:56 +00:00
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
string_t chars = getChars(e, path);
|
|
|
|
if (chars) {
|
|
|
|
STRUCT_STAT s;
|
|
|
|
int r = STAT(chars, &s);
|
|
|
|
releaseChars(e, path, chars);
|
|
|
|
if (r == 0) {
|
|
|
|
return s.st_size;
|
|
|
|
}
|
2007-07-27 00:06:05 +00:00
|
|
|
}
|
2011-09-14 17:50:56 +00:00
|
|
|
|
|
|
|
#endif
|
2007-07-27 00:06:05 +00:00
|
|
|
|
2011-01-17 16:48:34 +00:00
|
|
|
return 0;
|
2007-07-27 00:06:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Java_java_io_File_mkdir(JNIEnv* e, jclass, jstring path)
|
|
|
|
{
|
2010-04-20 16:03:07 +00:00
|
|
|
string_t chars = getChars(e, path);
|
2007-07-27 00:06:05 +00:00
|
|
|
if (chars) {
|
|
|
|
if (not exists(chars)) {
|
|
|
|
int r = ::MKDIR(chars, 0700);
|
|
|
|
if (r != 0) {
|
2009-08-27 00:26:44 +00:00
|
|
|
throwNewErrno(e, "java/io/IOException");
|
2007-07-27 00:06:05 +00:00
|
|
|
}
|
|
|
|
}
|
2010-04-20 16:03:07 +00:00
|
|
|
releaseChars(e, path, chars);
|
2007-07-27 00:06:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Java_java_io_File_createNewFile(JNIEnv* e, jclass, jstring path)
|
|
|
|
{
|
2010-04-20 16:03:07 +00:00
|
|
|
string_t chars = getChars(e, path);
|
2007-07-27 00:06:05 +00:00
|
|
|
if (chars) {
|
|
|
|
if (not exists(chars)) {
|
|
|
|
int fd = CREAT(chars, 0600);
|
|
|
|
if (fd == -1) {
|
2009-08-27 00:26:44 +00:00
|
|
|
throwNewErrno(e, "java/io/IOException");
|
2007-07-27 00:06:05 +00:00
|
|
|
} else {
|
|
|
|
doClose(e, fd);
|
|
|
|
}
|
|
|
|
}
|
2010-04-20 16:03:07 +00:00
|
|
|
releaseChars(e, path, chars);
|
2007-07-27 00:06:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-07 23:44:43 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL
|
2007-09-12 01:13:05 +00:00
|
|
|
Java_java_io_File_delete(JNIEnv* e, jclass, jstring path)
|
|
|
|
{
|
2010-04-20 16:03:07 +00:00
|
|
|
string_t chars = getChars(e, path);
|
2007-09-12 01:13:05 +00:00
|
|
|
if (chars) {
|
2008-05-07 23:44:43 +00:00
|
|
|
int r = UNLINK(chars);
|
|
|
|
if (r != 0) {
|
2009-08-27 00:26:44 +00:00
|
|
|
throwNewErrno(e, "java/io/IOException");
|
2008-05-07 23:44:43 +00:00
|
|
|
}
|
2010-04-20 16:03:07 +00:00
|
|
|
releaseChars(e, path, chars);
|
2007-09-12 01:13:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-15 13:06:36 +00:00
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
|
|
|
Java_java_io_File_canRead(JNIEnv* e, jclass, jstring path)
|
|
|
|
{
|
|
|
|
string_t chars = getChars(e, path);
|
|
|
|
if (chars) {
|
2010-09-12 20:46:14 +00:00
|
|
|
int r = ACCESS(chars, R_OK);
|
2010-08-15 13:06:36 +00:00
|
|
|
releaseChars(e, path, chars);
|
|
|
|
return (r == 0);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
|
|
|
Java_java_io_File_canWrite(JNIEnv* e, jclass, jstring path)
|
|
|
|
{
|
|
|
|
string_t chars = getChars(e, path);
|
|
|
|
if (chars) {
|
2010-09-12 20:46:14 +00:00
|
|
|
int r = ACCESS(chars, W_OK);
|
2010-08-15 13:06:36 +00:00
|
|
|
releaseChars(e, path, chars);
|
|
|
|
return (r == 0);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-09-28 23:45:47 +00:00
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
|
|
|
Java_java_io_File_rename(JNIEnv* e, jclass, jstring old, jstring new_)
|
|
|
|
{
|
2010-04-20 16:03:07 +00:00
|
|
|
string_t oldChars = getChars(e, old);
|
|
|
|
string_t newChars = getChars(e, new_);
|
2009-09-28 23:45:47 +00:00
|
|
|
if (oldChars) {
|
|
|
|
bool v;
|
|
|
|
if (newChars) {
|
2010-04-20 16:03:07 +00:00
|
|
|
v = RENAME(oldChars, newChars) == 0;
|
2009-09-28 23:45:47 +00:00
|
|
|
|
2010-04-20 16:03:07 +00:00
|
|
|
releaseChars(e, new_, newChars);
|
2009-09-28 23:45:47 +00:00
|
|
|
} else {
|
|
|
|
v = false;
|
|
|
|
}
|
2010-04-20 16:03:07 +00:00
|
|
|
releaseChars(e, old, oldChars);
|
2009-09-28 23:45:47 +00:00
|
|
|
return v;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-29 20:57:33 +00:00
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
|
|
|
Java_java_io_File_isDirectory(JNIEnv* e, jclass, jstring path)
|
|
|
|
{
|
2010-04-20 16:03:07 +00:00
|
|
|
string_t chars = getChars(e, path);
|
2007-10-29 20:57:33 +00:00
|
|
|
if (chars) {
|
|
|
|
STRUCT_STAT s;
|
|
|
|
int r = STAT(chars, &s);
|
|
|
|
bool v = (r == 0 and S_ISDIR(s.st_mode));
|
2010-04-20 16:03:07 +00:00
|
|
|
releaseChars(e, path, chars);
|
2007-10-29 20:57:33 +00:00
|
|
|
return v;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-04 23:59:07 +00:00
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
|
|
|
Java_java_io_File_isFile(JNIEnv* e, jclass, jstring path)
|
|
|
|
{
|
2010-04-20 16:03:07 +00:00
|
|
|
string_t chars = getChars(e, path);
|
2009-08-04 23:59:07 +00:00
|
|
|
if (chars) {
|
|
|
|
STRUCT_STAT s;
|
|
|
|
int r = STAT(chars, &s);
|
|
|
|
bool v = (r == 0 and S_ISREG(s.st_mode));
|
2010-04-20 16:03:07 +00:00
|
|
|
releaseChars(e, path, chars);
|
2009-08-04 23:59:07 +00:00
|
|
|
return v;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-27 00:06:05 +00:00
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
|
|
|
Java_java_io_File_exists(JNIEnv* e, jclass, jstring path)
|
|
|
|
{
|
2010-04-20 16:03:07 +00:00
|
|
|
string_t chars = getChars(e, path);
|
2007-07-27 00:06:05 +00:00
|
|
|
if (chars) {
|
|
|
|
bool v = exists(chars);
|
2010-04-20 16:03:07 +00:00
|
|
|
releaseChars(e, path, chars);
|
2007-07-27 00:06:05 +00:00
|
|
|
return v;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-27 00:26:44 +00:00
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jlong JNICALL
|
|
|
|
Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path)
|
|
|
|
{
|
2010-04-20 16:03:07 +00:00
|
|
|
string_t chars = getChars(e, path);
|
2009-08-27 00:26:44 +00:00
|
|
|
if (chars) {
|
2010-04-20 16:03:07 +00:00
|
|
|
unsigned length = wcslen(chars);
|
|
|
|
unsigned size = length * sizeof(char_t);
|
2009-09-03 23:57:32 +00:00
|
|
|
|
2010-04-20 16:03:07 +00:00
|
|
|
RUNTIME_ARRAY(char_t, buffer, length + 3);
|
|
|
|
memcpy(RUNTIME_ARRAY_BODY(buffer), chars, size);
|
|
|
|
memcpy(RUNTIME_ARRAY_BODY(buffer) + length, L"\\*", 6);
|
2009-09-03 23:57:32 +00:00
|
|
|
|
2010-04-20 16:03:07 +00:00
|
|
|
releaseChars(e, path, chars);
|
2009-09-03 23:57:32 +00:00
|
|
|
|
2009-08-27 00:26:44 +00:00
|
|
|
Directory* d = new (malloc(sizeof(Directory))) Directory;
|
2010-04-20 16:03:07 +00:00
|
|
|
d->handle = FindFirstFileW(RUNTIME_ARRAY_BODY(buffer), &(d->data));
|
2009-08-27 00:26:44 +00:00
|
|
|
if (d->handle == INVALID_HANDLE_VALUE) {
|
|
|
|
d->dispose();
|
|
|
|
d = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return reinterpret_cast<jlong>(d);
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jstring JNICALL
|
|
|
|
Java_java_io_File_readDir(JNIEnv* e, jclass, jlong handle)
|
|
|
|
{
|
|
|
|
Directory* d = reinterpret_cast<Directory*>(handle);
|
2010-04-20 16:03:07 +00:00
|
|
|
|
2010-01-10 02:18:39 +00:00
|
|
|
while (true) {
|
2010-04-20 16:03:07 +00:00
|
|
|
string_t s = d->next();
|
2010-01-10 02:18:39 +00:00
|
|
|
if (s) {
|
2010-04-20 16:03:07 +00:00
|
|
|
if (wcscmp(s, L".") == 0 || wcscmp(s, L"..") == 0) {
|
2010-01-10 02:18:39 +00:00
|
|
|
// skip . or .. and try again
|
|
|
|
} else {
|
2010-04-20 16:03:07 +00:00
|
|
|
return e->NewString(reinterpret_cast<const jchar*>(s), wcslen(s));
|
2010-01-10 02:18:39 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
2009-08-27 00:26:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Java_java_io_File_closeDir(JNIEnv* , jclass, jlong handle)
|
|
|
|
{
|
|
|
|
reinterpret_cast<Directory*>(handle)->dispose();
|
|
|
|
}
|
|
|
|
|
|
|
|
#else // not PLATFORM_WINDOWS
|
|
|
|
|
2008-07-14 00:14:37 +00:00
|
|
|
extern "C" JNIEXPORT jlong JNICALL
|
|
|
|
Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path)
|
|
|
|
{
|
2010-04-20 16:03:07 +00:00
|
|
|
string_t chars = getChars(e, path);
|
2008-07-14 00:14:37 +00:00
|
|
|
if (chars) {
|
|
|
|
jlong handle = reinterpret_cast<jlong>(opendir(chars));
|
2010-04-20 16:03:07 +00:00
|
|
|
releaseChars(e, path, chars);
|
2008-07-14 00:14:37 +00:00
|
|
|
return handle;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jstring JNICALL
|
|
|
|
Java_java_io_File_readDir(JNIEnv* e, jclass, jlong handle)
|
|
|
|
{
|
|
|
|
struct dirent * directoryEntry;
|
2010-01-10 02:18:39 +00:00
|
|
|
|
2008-07-14 00:14:37 +00:00
|
|
|
if (handle!=0) {
|
2010-01-10 02:18:39 +00:00
|
|
|
while (true) {
|
|
|
|
directoryEntry = readdir(reinterpret_cast<DIR*>(handle));
|
|
|
|
if (directoryEntry == NULL) {
|
|
|
|
return NULL;
|
|
|
|
} else if (strcmp(directoryEntry->d_name, ".") == 0
|
|
|
|
|| strcmp(directoryEntry->d_name, "..") == 0)
|
|
|
|
{
|
|
|
|
// skip . or .. and try again
|
|
|
|
} else {
|
|
|
|
return e->NewStringUTF(directoryEntry->d_name);
|
|
|
|
}
|
2008-07-14 00:14:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Java_java_io_File_closeDir(JNIEnv* , jclass, jlong handle)
|
|
|
|
{
|
|
|
|
if (handle!=0) {
|
|
|
|
closedir(reinterpret_cast<DIR*>(handle));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-27 00:26:44 +00:00
|
|
|
#endif // not PLATFORM_WINDOWS
|
|
|
|
|
2007-07-27 00:06:05 +00:00
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
|
|
|
Java_java_io_FileInputStream_open(JNIEnv* e, jclass, jstring path)
|
|
|
|
{
|
2010-04-20 16:03:07 +00:00
|
|
|
string_t chars = getChars(e, path);
|
2007-07-27 00:06:05 +00:00
|
|
|
if (chars) {
|
|
|
|
int fd = doOpen(e, chars, O_RDONLY);
|
2010-04-20 16:03:07 +00:00
|
|
|
releaseChars(e, path, chars);
|
|
|
|
return fd;
|
2007-07-27 00:06:05 +00:00
|
|
|
} else {
|
2010-04-20 16:03:07 +00:00
|
|
|
return -1;
|
2007-07-27 00:06:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
|
|
|
Java_java_io_FileInputStream_read__I(JNIEnv* e, jclass, jint fd)
|
|
|
|
{
|
|
|
|
jbyte data;
|
|
|
|
int r = doRead(e, fd, &data, 1);
|
|
|
|
if (r <= 0) {
|
|
|
|
return -1;
|
|
|
|
} else {
|
2007-10-04 19:57:39 +00:00
|
|
|
return data & 0xff;
|
2007-07-27 00:06:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
|
|
|
Java_java_io_FileInputStream_read__I_3BII
|
|
|
|
(JNIEnv* e, jclass, jint fd, jbyteArray b, jint offset, jint length)
|
|
|
|
{
|
|
|
|
jbyte* data = static_cast<jbyte*>(malloc(length));
|
|
|
|
if (data == 0) {
|
|
|
|
throwNew(e, "java/lang/OutOfMemoryError", 0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int r = doRead(e, fd, data, length);
|
|
|
|
|
|
|
|
e->SetByteArrayRegion(b, offset, length, data);
|
|
|
|
|
|
|
|
free(data);
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Java_java_io_FileInputStream_close(JNIEnv* e, jclass, jint fd)
|
|
|
|
{
|
|
|
|
doClose(e, fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-08-15 01:05:18 +00:00
|
|
|
Java_java_io_FileOutputStream_open(JNIEnv* e, jclass, jstring path, jboolean append)
|
2007-07-27 00:06:05 +00:00
|
|
|
{
|
2010-04-20 16:03:07 +00:00
|
|
|
string_t chars = getChars(e, path);
|
2007-07-27 00:06:05 +00:00
|
|
|
if (chars) {
|
2011-01-14 18:26:00 +00:00
|
|
|
int fd = doOpen(e, chars, append
|
|
|
|
? (O_WRONLY | O_CREAT | O_APPEND)
|
|
|
|
: (O_WRONLY | O_CREAT | O_TRUNC));
|
2010-04-20 16:03:07 +00:00
|
|
|
releaseChars(e, path, chars);
|
2007-07-27 00:06:05 +00:00
|
|
|
return fd;
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Java_java_io_FileOutputStream_write__II(JNIEnv* e, jclass, jint fd, jint c)
|
|
|
|
{
|
|
|
|
jbyte data = c;
|
|
|
|
doWrite(e, fd, &data, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Java_java_io_FileOutputStream_write__I_3BII
|
|
|
|
(JNIEnv* e, jclass, jint fd, jbyteArray b, jint offset, jint length)
|
|
|
|
{
|
|
|
|
jbyte* data = static_cast<jbyte*>(malloc(length));
|
|
|
|
if (data == 0) {
|
|
|
|
throwNew(e, "java/lang/OutOfMemoryError", 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
e->GetByteArrayRegion(b, offset, length, data);
|
|
|
|
|
|
|
|
if (not e->ExceptionCheck()) {
|
|
|
|
doWrite(e, fd, data, length);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Java_java_io_FileOutputStream_close(JNIEnv* e, jclass, jint fd)
|
|
|
|
{
|
|
|
|
doClose(e, fd);
|
|
|
|
}
|
2008-11-11 15:20:49 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path,
|
|
|
|
jlongArray result)
|
|
|
|
{
|
2010-04-20 16:03:07 +00:00
|
|
|
string_t chars = getChars(e, path);
|
2008-11-11 15:20:49 +00:00
|
|
|
if (chars) {
|
|
|
|
Mapping* mapping = map(e, chars);
|
|
|
|
|
|
|
|
jlong peer = reinterpret_cast<jlong>(mapping);
|
|
|
|
e->SetLongArrayRegion(result, 0, 1, &peer);
|
|
|
|
|
|
|
|
jlong length = (mapping ? mapping->length : 0);
|
|
|
|
e->SetLongArrayRegion(result, 1, 1, &length);
|
|
|
|
|
2010-04-20 16:03:07 +00:00
|
|
|
releaseChars(e, path, chars);
|
2008-11-11 15:20:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Java_java_io_RandomAccessFile_copy(JNIEnv* e, jclass, jlong peer,
|
|
|
|
jlong position, jbyteArray buffer,
|
|
|
|
int offset, int length)
|
|
|
|
{
|
|
|
|
uint8_t* dst = reinterpret_cast<uint8_t*>
|
|
|
|
(e->GetPrimitiveArrayCritical(buffer, 0));
|
|
|
|
|
|
|
|
memcpy(dst + offset,
|
|
|
|
reinterpret_cast<Mapping*>(peer)->start + position,
|
|
|
|
length);
|
|
|
|
|
|
|
|
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Java_java_io_RandomAccessFile_close(JNIEnv* e, jclass, jlong peer)
|
|
|
|
{
|
|
|
|
unmap(e, reinterpret_cast<Mapping*>(peer));
|
|
|
|
}
|