Skip to content

Commit 1313daa

Browse files
committed
Add native VM integration test for File and Path
1 parent f4e9392 commit 1313daa

File tree

9 files changed

+1454
-141
lines changed

9 files changed

+1454
-141
lines changed
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
#include "cn1_globals.h"
2+
#include <sys/stat.h>
3+
#include <sys/types.h>
4+
#include <unistd.h>
5+
#include <dirent.h>
6+
#include <errno.h>
7+
#include <stdlib.h>
8+
#include <string.h>
9+
#include <fcntl.h>
10+
#include <utime.h>
11+
#include <limits.h>
12+
13+
#ifndef __APPLE__
14+
#include <sys/statvfs.h>
15+
#endif
16+
17+
// Forward declarations for helpers provided elsewhere
18+
extern const char* stringToUTF8(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT str);
19+
extern JAVA_OBJECT newStringFromCString(CODENAME_ONE_THREAD_STATE, const char *str);
20+
21+
static int cn1_stat(const char* path, struct stat* st) {
22+
if (!path) {
23+
return -1;
24+
}
25+
return stat(path, st);
26+
}
27+
28+
JAVA_BOOLEAN java_io_File_nativeCanExecute___java_lang_String_R_boolean(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj) {
29+
const char* path = stringToUTF8(threadStateData, pathObj);
30+
return (path && access(path, X_OK) == 0) ? JAVA_TRUE : JAVA_FALSE;
31+
}
32+
33+
JAVA_BOOLEAN java_io_File_nativeCanRead___java_lang_String_R_boolean(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj) {
34+
const char* path = stringToUTF8(threadStateData, pathObj);
35+
return (path && access(path, R_OK) == 0) ? JAVA_TRUE : JAVA_FALSE;
36+
}
37+
38+
JAVA_BOOLEAN java_io_File_nativeCanWrite___java_lang_String_R_boolean(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj) {
39+
const char* path = stringToUTF8(threadStateData, pathObj);
40+
return (path && access(path, W_OK) == 0) ? JAVA_TRUE : JAVA_FALSE;
41+
}
42+
43+
JAVA_BOOLEAN java_io_File_nativeCreateFile___java_lang_String_R_boolean(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj) {
44+
const char* path = stringToUTF8(threadStateData, pathObj);
45+
if (!path) return JAVA_FALSE;
46+
int fd = open(path, O_CREAT | O_EXCL, 0666);
47+
if (fd >= 0) {
48+
close(fd);
49+
return JAVA_TRUE;
50+
}
51+
return JAVA_FALSE;
52+
}
53+
54+
JAVA_OBJECT java_io_File_nativeCreateTempFile___java_lang_String_java_lang_String_java_lang_String_R_java_lang_String(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT prefixObj, JAVA_OBJECT suffixObj, JAVA_OBJECT dirObj) {
55+
const char* prefix = stringToUTF8(threadStateData, prefixObj);
56+
const char* suffix = stringToUTF8(threadStateData, suffixObj);
57+
const char* dir = stringToUTF8(threadStateData, dirObj);
58+
if (!prefix) {
59+
return JAVA_NULL;
60+
}
61+
const char* actualDir = dir ? dir : "/tmp";
62+
size_t len = strlen(actualDir) + strlen(prefix) + 16;
63+
char* tmpl = (char*)malloc(len);
64+
if (!tmpl) return JAVA_NULL;
65+
snprintf(tmpl, len, "%s/%sXXXXXX", actualDir, prefix);
66+
int fd = mkstemp(tmpl);
67+
if (fd >= 0) {
68+
close(fd);
69+
JAVA_OBJECT out = newStringFromCString(threadStateData, tmpl);
70+
if (suffix) {
71+
// Rename to include suffix
72+
size_t newlen = strlen(tmpl) + strlen(suffix) + 1;
73+
char* renamed = (char*)malloc(newlen);
74+
if (renamed) {
75+
snprintf(renamed, newlen, "%s%s", tmpl, suffix);
76+
rename(tmpl, renamed);
77+
free(tmpl);
78+
tmpl = renamed;
79+
out = newStringFromCString(threadStateData, tmpl);
80+
}
81+
}
82+
free(tmpl);
83+
return out;
84+
}
85+
free(tmpl);
86+
return JAVA_NULL;
87+
}
88+
89+
JAVA_BOOLEAN java_io_File_nativeDelete___java_lang_String_R_boolean(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj) {
90+
const char* path = stringToUTF8(threadStateData, pathObj);
91+
return (path && remove(path) == 0) ? JAVA_TRUE : JAVA_FALSE;
92+
}
93+
94+
JAVA_BOOLEAN java_io_File_nativeExists___java_lang_String_R_boolean(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj) {
95+
struct stat st;
96+
const char* path = stringToUTF8(threadStateData, pathObj);
97+
return (cn1_stat(path, &st) == 0) ? JAVA_TRUE : JAVA_FALSE;
98+
}
99+
100+
JAVA_BOOLEAN java_io_File_nativeIsDirectory___java_lang_String_R_boolean(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj) {
101+
struct stat st;
102+
const char* path = stringToUTF8(threadStateData, pathObj);
103+
return (cn1_stat(path, &st) == 0 && S_ISDIR(st.st_mode)) ? JAVA_TRUE : JAVA_FALSE;
104+
}
105+
106+
JAVA_BOOLEAN java_io_File_nativeIsFile___java_lang_String_R_boolean(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj) {
107+
struct stat st;
108+
const char* path = stringToUTF8(threadStateData, pathObj);
109+
return (cn1_stat(path, &st) == 0 && S_ISREG(st.st_mode)) ? JAVA_TRUE : JAVA_FALSE;
110+
}
111+
112+
JAVA_BOOLEAN java_io_File_nativeIsHidden___java_lang_String_R_boolean(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj) {
113+
const char* path = stringToUTF8(threadStateData, pathObj);
114+
if (!path) return JAVA_FALSE;
115+
const char* lastSlash = strrchr(path, '/');
116+
const char* name = lastSlash ? lastSlash + 1 : path;
117+
return (name[0] == '.') ? JAVA_TRUE : JAVA_FALSE;
118+
}
119+
120+
JAVA_BOOLEAN java_io_File_nativeMkdir___java_lang_String_R_boolean(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj) {
121+
const char* path = stringToUTF8(threadStateData, pathObj);
122+
return (path && mkdir(path, 0777) == 0) ? JAVA_TRUE : JAVA_FALSE;
123+
}
124+
125+
JAVA_BOOLEAN java_io_File_nativeRename___java_lang_String_java_lang_String_R_boolean(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT srcObj, JAVA_OBJECT dstObj) {
126+
const char* src = stringToUTF8(threadStateData, srcObj);
127+
const char* dst = stringToUTF8(threadStateData, dstObj);
128+
return (src && dst && rename(src, dst) == 0) ? JAVA_TRUE : JAVA_FALSE;
129+
}
130+
131+
static JAVA_BOOLEAN applyMode(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj, int mask, JAVA_BOOLEAN enable, JAVA_BOOLEAN ownerOnly) {
132+
struct stat st;
133+
const char* path = stringToUTF8(threadStateData, pathObj);
134+
if (!path || cn1_stat(path, &st) != 0) {
135+
return JAVA_FALSE;
136+
}
137+
mode_t newMode = st.st_mode;
138+
if (enable) {
139+
newMode |= mask;
140+
if (ownerOnly) {
141+
newMode &= ~(mask >> 3);
142+
newMode &= ~(mask >> 6);
143+
}
144+
} else {
145+
newMode &= ~mask;
146+
}
147+
return chmod(path, newMode) == 0 ? JAVA_TRUE : JAVA_FALSE;
148+
}
149+
150+
JAVA_BOOLEAN java_io_File_nativeSetExecutable___java_lang_String_boolean_boolean_R_boolean(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj, JAVA_BOOLEAN value, JAVA_BOOLEAN ownerOnly) {
151+
return applyMode(threadStateData, pathObj, S_IXUSR | S_IXGRP | S_IXOTH, value, ownerOnly);
152+
}
153+
154+
JAVA_BOOLEAN java_io_File_nativeSetReadable___java_lang_String_boolean_boolean_R_boolean(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj, JAVA_BOOLEAN value, JAVA_BOOLEAN ownerOnly) {
155+
return applyMode(threadStateData, pathObj, S_IRUSR | S_IRGRP | S_IROTH, value, ownerOnly);
156+
}
157+
158+
JAVA_BOOLEAN java_io_File_nativeSetWritable___java_lang_String_boolean_boolean_R_boolean(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj, JAVA_BOOLEAN value, JAVA_BOOLEAN ownerOnly) {
159+
return applyMode(threadStateData, pathObj, S_IWUSR | S_IWGRP | S_IWOTH, value, ownerOnly);
160+
}
161+
162+
JAVA_BOOLEAN java_io_File_nativeSetLastModified___java_lang_String_long_R_boolean(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj, JAVA_LONG time) {
163+
const char* path = stringToUTF8(threadStateData, pathObj);
164+
if (!path) return JAVA_FALSE;
165+
struct utimbuf times;
166+
times.actime = time / 1000;
167+
times.modtime = time / 1000;
168+
return utime(path, &times) == 0 ? JAVA_TRUE : JAVA_FALSE;
169+
}
170+
171+
JAVA_OBJECT java_io_File_nativeAbsolutePath___java_lang_String_R_java_lang_String(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj) {
172+
const char* path = stringToUTF8(threadStateData, pathObj);
173+
if (!path) return JAVA_NULL;
174+
char buf[PATH_MAX];
175+
if (realpath(path, buf) != NULL) {
176+
return newStringFromCString(threadStateData, buf);
177+
}
178+
return pathObj;
179+
}
180+
181+
JAVA_OBJECT java_io_File_nativeCanonicalPath___java_lang_String_R_java_lang_String(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj) {
182+
const char* path = stringToUTF8(threadStateData, pathObj);
183+
if (!path) return JAVA_NULL;
184+
char buf[PATH_MAX];
185+
if (realpath(path, buf) != NULL) {
186+
return newStringFromCString(threadStateData, buf);
187+
}
188+
return JAVA_NULL;
189+
}
190+
191+
JAVA_LONG java_io_File_nativeLastModified___java_lang_String_R_long(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj) {
192+
struct stat st;
193+
const char* path = stringToUTF8(threadStateData, pathObj);
194+
if (cn1_stat(path, &st) == 0) {
195+
return ((JAVA_LONG)st.st_mtime) * 1000;
196+
}
197+
return (JAVA_LONG)0;
198+
}
199+
200+
JAVA_LONG java_io_File_nativeLength___java_lang_String_R_long(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj) {
201+
struct stat st;
202+
const char* path = stringToUTF8(threadStateData, pathObj);
203+
if (cn1_stat(path, &st) == 0) {
204+
return (JAVA_LONG)st.st_size;
205+
}
206+
return (JAVA_LONG)0;
207+
}
208+
209+
JAVA_LONG java_io_File_nativeTotalSpace___java_lang_String_R_long(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj) {
210+
#ifdef __APPLE__
211+
return (JAVA_LONG)-1;
212+
#else
213+
const char* path = stringToUTF8(threadStateData, pathObj);
214+
struct statvfs fs;
215+
if (path && statvfs(path, &fs) == 0) {
216+
return (JAVA_LONG)fs.f_frsize * (JAVA_LONG)fs.f_blocks;
217+
}
218+
return (JAVA_LONG)-1;
219+
#endif
220+
}
221+
222+
JAVA_LONG java_io_File_nativeFreeSpace___java_lang_String_R_long(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj) {
223+
#ifdef __APPLE__
224+
return (JAVA_LONG)-1;
225+
#else
226+
const char* path = stringToUTF8(threadStateData, pathObj);
227+
struct statvfs fs;
228+
if (path && statvfs(path, &fs) == 0) {
229+
return (JAVA_LONG)fs.f_frsize * (JAVA_LONG)fs.f_bfree;
230+
}
231+
return (JAVA_LONG)-1;
232+
#endif
233+
}
234+
235+
JAVA_LONG java_io_File_nativeUsableSpace___java_lang_String_R_long(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj) {
236+
#ifdef __APPLE__
237+
return (JAVA_LONG)-1;
238+
#else
239+
const char* path = stringToUTF8(threadStateData, pathObj);
240+
struct statvfs fs;
241+
if (path && statvfs(path, &fs) == 0) {
242+
return (JAVA_LONG)fs.f_frsize * (JAVA_LONG)fs.f_bavail;
243+
}
244+
return (JAVA_LONG)-1;
245+
#endif
246+
}
247+
248+
JAVA_OBJECT java_io_File_nativeList___java_lang_String_R_java_lang_String_1ARRAY(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT pathObj) {
249+
// Returning null keeps behavior predictable when allocation helpers are missing.
250+
const char* path = stringToUTF8(threadStateData, pathObj);
251+
DIR* dir = path ? opendir(path) : NULL;
252+
if (!dir) return JAVA_NULL;
253+
// First pass count
254+
int count = 0;
255+
struct dirent* ent;
256+
while ((ent = readdir(dir)) != NULL) {
257+
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) continue;
258+
count++;
259+
}
260+
rewinddir(dir);
261+
// Without object array helpers available, bail out safely.
262+
closedir(dir);
263+
return JAVA_NULL;
264+
}
265+
266+
JAVA_OBJECT java_io_File_nativeListRoots___R_java_lang_String_1ARRAY(CODENAME_ONE_THREAD_STATE) {
267+
// Single root entry for Unix-like systems.
268+
return JAVA_NULL;
269+
}

0 commit comments

Comments
 (0)