source: trunk/gcc/libjava/java/io/natFileWin32.cc

Last change on this file was 1392, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 10.3 KB
Line 
1// natFileWin32.cc - Native part of File class for Win32.
2
3/* Copyright (C) 1998, 1999, 2002, 2003 Free Software Foundation, Inc.
4
5 This file is part of libgcj.
6
7This software is copyrighted work licensed under the terms of the
8Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9details. */
10
11#include <config.h>
12
13#include <stdio.h>
14#include <string.h>
15
16#include <windows.h>
17#undef STRICT
18
19#include <gcj/cni.h>
20#include <jvm.h>
21#include <java/io/File.h>
22#include <java/io/IOException.h>
23#include <java/util/Vector.h>
24#include <java/lang/String.h>
25#include <java/io/FilenameFilter.h>
26#include <java/io/FileFilter.h>
27#include <java/lang/System.h>
28
29// Java timestamps are milliseconds since the UNIX epoch (00:00:00 UTC on
30// January 1, 1970) while Win32 file-times are 100-nanosecond intervals
31// since the Win32 epoch (00:00:00 UTC on January 1, 1601). The following
32// constant represents the number of milliseconds to be added to a
33// Java timestamp to base it on the Win32 epoch.
34//
35// There were 369 years between 1601 and 1970, including 89 leap years
36// (since 1700, 1800 and 1900 were not leap years):
37//
38// (89*366 + 280*365) days * 86400 seconds/day = 11644473600 seconds
39//
40#define WIN32_EPOCH_MILLIS 11644473600000LL
41
42jboolean
43java::io::File::_access (jint query)
44{
45 jstring canon = getCanonicalPath();
46 if (! canon)
47 return false;
48 char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (canon) + 1);
49 jsize total = JvGetStringUTFRegion (canon, 0, canon->length(), buf);
50 buf[total] = '\0';
51
52 JvAssert (query == READ || query == WRITE || query == EXISTS);
53
54 // FIXME: Is it possible to differentiate between existing and reading?
55 // If the file exists but cannot be read because of the secuirty attributes
56 // on an NTFS disk this wont work (it reports it can be read but cant)
57 // Could we use something from the security API?
58 DWORD attributes = GetFileAttributes (buf);
59 if ((query == EXISTS) || (query == READ))
60 return (attributes == 0xffffffff) ? false : true;
61 else
62 return ((attributes != 0xffffffff) && ((attributes & FILE_ATTRIBUTE_READONLY) == 0)) ? true : false;
63}
64
65jboolean
66java::io::File::_stat (jint query)
67{
68 jstring canon = getCanonicalPath();
69 if (! canon)
70 return false;
71 char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (canon) + 1);
72 jsize total = JvGetStringUTFRegion (canon, 0, canon->length(), buf);
73 buf[total] = '\0';
74
75 JvAssert (query == DIRECTORY || query == ISFILE);
76
77 DWORD attributes = GetFileAttributes (buf);
78 if (attributes == 0xffffffff)
79 return false;
80
81 if (query == DIRECTORY)
82 return attributes & FILE_ATTRIBUTE_DIRECTORY ? true : false;
83 else
84 return attributes & FILE_ATTRIBUTE_DIRECTORY ? false : true;
85}
86
87jlong
88java::io::File::attr (jint query)
89{
90 jstring canon = getCanonicalPath();
91 if (! canon)
92 return false;
93 char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (canon) + 1);
94 jsize total = JvGetStringUTFRegion (canon, 0, canon->length(), buf);
95 buf[total] = '\0';
96
97 JvAssert (query == MODIFIED || query == LENGTH);
98
99 WIN32_FIND_DATA info;
100 HANDLE sHandle;
101 if ( ( sHandle = FindFirstFile( buf, &info)) == INVALID_HANDLE_VALUE)
102 return 0;
103
104 FindClose( sHandle);
105
106 if (query == LENGTH)
107 return ((long long)info.nFileSizeHigh) << 32
108 | (unsigned long long)info.nFileSizeLow;
109 else
110 {
111 // The file time as returned by Windows is in terms of the number
112 // of 100-nanosecond intervals since 00:00:00 UTC, January 1, 1601.
113 return (((((long long)info.ftLastWriteTime.dwHighDateTime) << 32)
114 | ((unsigned long long)info.ftLastWriteTime.dwLowDateTime))
115 - WIN32_EPOCH_MILLIS*10000LL) / 10000LL;
116 }
117}
118
119jstring
120java::io::File::getCanonicalPath (void)
121{
122 char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1);
123 jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
124 buf[total] = '\0';
125
126 LPTSTR unused;
127 char buf2[MAX_PATH];
128 if(!GetFullPathName(buf, MAX_PATH, buf2, &unused))
129 throw new IOException (JvNewStringLatin1 ("GetFullPathName failed"));
130
131 // FIXME: what encoding to assume for file names? This affects many
132 // calls.
133 return JvNewStringUTF(buf2);
134}
135
136jboolean
137java::io::File::isAbsolute (void)
138{
139 // See if the path represents a Windows UNC network path.
140 if (path->length () > 2
141 && (path->charAt (0) == '\\') && (path->charAt (1) == '\\'))
142 return true;
143
144 // Note that the path is not an absolute path even if it starts with
145 // a '/' or a '\' because it lacks a drive specifier.
146
147 if (path->length() < 3)
148 return false;
149 // Hard-code A-Za-z because Windows (I think) can't use non-ASCII
150 // letters as drive names.
151 if ((path->charAt(0) < 'a' || path->charAt(0) > 'z')
152 && (path->charAt(0) < 'A' || path->charAt(0) > 'Z'))
153 return false;
154 return (path->charAt(1) == ':'
155 && (path->charAt(2) == '/' || path->charAt(2) == '\\'));
156}
157
158void java::io::File::init_native ()
159{
160 maxPathLen = MAX_PATH;
161 caseSensitive = false;
162}
163
164jobjectArray
165java::io::File::performList (java::io::FilenameFilter *filter,
166 java::io::FileFilter *fileFilter,
167 java::lang::Class *clazz)
168{
169 jstring canon = getCanonicalPath();
170 if (! canon)
171 return NULL;
172 char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (canon) + 5);
173 jsize total = JvGetStringUTFRegion (canon, 0, canon->length(), buf);
174 if (buf[total-1] == '\\')
175 strcpy (&buf[total], "*.*");
176 else
177 strcpy (&buf[total], "\\*.*");
178
179 WIN32_FIND_DATA data;
180 HANDLE handle = FindFirstFile (buf, &data);
181 if (handle == INVALID_HANDLE_VALUE)
182 return NULL;
183
184 java::util::Vector *vec = new java::util::Vector ();
185
186 do
187 {
188 if (strcmp (data.cFileName, ".") && strcmp (data.cFileName, ".."))
189 {
190 jstring name = JvNewStringUTF (data.cFileName);
191
192 if (filter && !filter->accept(this, name))
193 continue;
194 if (clazz == &java::io::File::class$)
195 {
196 java::io::File *file = new java::io::File (this, name);
197 if (fileFilter && !fileFilter->accept(file))
198 continue;
199 vec->addElement (file);
200 }
201 else
202 vec->addElement (name);
203 }
204 }
205 while (FindNextFile (handle, &data));
206
207 if (GetLastError () != ERROR_NO_MORE_FILES)
208 return NULL;
209
210 FindClose (handle);
211
212 jobjectArray ret = JvNewObjectArray (vec->size(), clazz, NULL);
213 vec->copyInto (ret);
214 return ret;
215}
216
217jboolean
218java::io::File::performMkdir (void)
219{
220 char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1);
221 jsize total = JvGetStringUTFRegion(path, 0, path->length(), buf);
222 buf[total] = '\0';
223
224 return (CreateDirectory(buf, NULL)) ? true : false;
225}
226
227jboolean
228java::io::File::performRenameTo (File *dest)
229{
230 char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1);
231 jsize total = JvGetStringUTFRegion(path, 0, path->length(), buf);
232 buf[total] = '\0';
233 char *buf2 = (char *) __builtin_alloca (JvGetStringUTFLength (dest->path)
234 + 1);
235 total = JvGetStringUTFRegion(dest->path, 0, dest->path->length(), buf2);
236 buf2[total] = '\0';
237
238 return (MoveFile(buf, buf2)) ? true : false;
239}
240
241jboolean
242java::io::File::performDelete ()
243{
244 jstring canon = getCanonicalPath();
245 char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (canon) + 1);
246 jsize total = JvGetStringUTFRegion(canon, 0, canon->length(), buf);
247 buf[total] = '\0';
248
249 DWORD attributes = GetFileAttributes (buf);
250 if (attributes == 0xffffffff)
251 return false;
252
253 if (attributes & FILE_ATTRIBUTE_DIRECTORY)
254 return (RemoveDirectory (buf)) ? true : false;
255 else
256 return (DeleteFile (buf)) ? true : false;
257}
258
259jboolean java::io::File::performCreate (void)
260{
261 jstring canon = getCanonicalPath ();
262 char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (canon) + 1);
263 jsize total = JvGetStringUTFRegion (canon, 0, canon->length (), buf);
264 buf[total] = '\0';
265
266 HANDLE h = CreateFile (buf, 0, 0, NULL, CREATE_NEW,
267 FILE_ATTRIBUTE_NORMAL, NULL);
268 if (h != INVALID_HANDLE_VALUE)
269 {
270 CloseHandle (h);
271 return true;
272 }
273 else
274 {
275 if (GetLastError () == ERROR_ALREADY_EXISTS)
276 return false;
277 else
278 throw new IOException (JvNewStringLatin1 ("CreateFile failed"));
279 }
280}
281
282jboolean java::io::File::performSetReadOnly ()
283{
284 jstring canon = getCanonicalPath ();
285 char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (canon) + 1);
286 jsize total = JvGetStringUTFRegion (canon, 0, canon->length (), buf);
287 buf[total] = '\0';
288
289 DWORD attrs = GetFileAttributes (buf);
290 if (attrs != INVALID_FILE_ATTRIBUTES)
291 {
292 if (SetFileAttributes (buf, attrs | FILE_ATTRIBUTE_READONLY) != 0)
293 return true;
294 else
295 return false;
296 }
297 else
298 return false;
299}
300
301jboolean java::io::File::performSetLastModified (jlong time)
302{
303 jstring canon = getCanonicalPath ();
304 char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (canon) + 1);
305 jsize total = JvGetStringUTFRegion (canon, 0, canon->length (), buf);
306 buf[total] = '\0';
307
308 FILETIME modTime;
309 long long mTime100ns = ((long long) time /* Ha! */
310 + WIN32_EPOCH_MILLIS) * 10000LL;
311
312 modTime.dwLowDateTime = (DWORD) mTime100ns;
313 modTime.dwHighDateTime = (DWORD) (mTime100ns >> 32);
314
315 jboolean retVal = false;
316 HANDLE h = CreateFile (buf, FILE_WRITE_ATTRIBUTES,
317 FILE_SHARE_READ | FILE_SHARE_WRITE,
318 NULL, OPEN_EXISTING, 0, NULL);
319
320 if (h != INVALID_HANDLE_VALUE)
321 {
322 if (SetFileTime (h, NULL, &modTime, &modTime) != 0)
323 retVal = true;
324
325 CloseHandle (h);
326 }
327
328 return retVal;
329}
330
331JArray<java::io::File*>* java::io::File::performListRoots ()
332{
333 DWORD drivesBitmap = GetLogicalDrives ();
334 DWORD mask;
335
336 // Possible drive letters are from ASCII 'A'-'Z'.
337 int numDrives = 0;
338 mask = 1;
339 for (int i = 0; i < 26; i++)
340 {
341 if ((drivesBitmap & mask) != 0)
342 numDrives++;
343 mask <<= 1;
344 }
345
346 JArray<java::io::File *> *roots
347 = reinterpret_cast <JArray<java::io::File *>*>
348 (JvNewObjectArray (numDrives, &java::io::File::class$, NULL));
349
350 ::java::io::File **rootsArray = elements (roots);
351
352 char aDriveRoot[] = {'A', ':', '\\', '\0'};
353 mask = 1;
354 for (int i = 0, j = 0; i < 26; i++)
355 {
356 if ((drivesBitmap & mask) != 0)
357 {
358 rootsArray[j]
359 = new ::java::io::File (JvNewStringLatin1 (aDriveRoot));
360 j++;
361 }
362 mask <<= 1;
363 aDriveRoot[0]++;
364 }
365
366 return roots;
367}
Note: See TracBrowser for help on using the repository browser.