blob: bfc55cd4d900b72414acf2807c2128cd0898a975 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2001-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26/* Access APIs for Win2K and above */
27#ifndef _WIN32_WINNT
28#define _WIN32_WINNT 0x0500
29#endif
30
31#include <assert.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <ctype.h>
35#include <direct.h>
36#include <windows.h>
37#include <io.h>
38
39#include "jvm.h"
40#include "jni.h"
41#include "jni_util.h"
42#include "io_util.h"
43#include "jlong.h"
44#include "io_util_md.h"
45#include "dirent_md.h"
46#include "java_io_FileSystem.h"
47
48#define MAX_PATH_LENGTH 1024
49
50static struct {
51 jfieldID path;
52} ids;
53
54JNIEXPORT void JNICALL
55Java_java_io_WinNTFileSystem_initIDs(JNIEnv *env, jclass cls)
56{
57 jclass fileClass = (*env)->FindClass(env, "java/io/File");
58 if (!fileClass) return;
59 ids.path =
60 (*env)->GetFieldID(env, fileClass, "path", "Ljava/lang/String;");
61}
62
63/* -- Path operations -- */
64
65extern int wcanonicalize(const WCHAR *path, WCHAR *out, int len);
66extern int wcanonicalizeWithPrefix(const WCHAR *canonicalPrefix, const WCHAR *pathWithCanonicalPrefix, WCHAR *out, int len);
67
68JNIEXPORT jstring JNICALL
69Java_java_io_WinNTFileSystem_canonicalize0(JNIEnv *env, jobject this,
70 jstring pathname)
71{
72 jstring rv = NULL;
73 WCHAR canonicalPath[MAX_PATH_LENGTH];
74
75 WITH_UNICODE_STRING(env, pathname, path) {
76 /*we estimate the max length of memory needed as
77 "currentDir. length + pathname.length"
78 */
79 int len = wcslen(path);
80 len += currentDirLength(path, len);
81 if (len > MAX_PATH_LENGTH - 1) {
82 WCHAR *cp = (WCHAR*)malloc(len * sizeof(WCHAR));
83 if (cp != NULL) {
84 if (wcanonicalize(path, cp, len) >= 0) {
85 rv = (*env)->NewString(env, cp, wcslen(cp));
86 }
87 free(cp);
88 }
89 } else
90 if (wcanonicalize(path, canonicalPath, MAX_PATH_LENGTH) >= 0) {
91 rv = (*env)->NewString(env, canonicalPath, wcslen(canonicalPath));
92 }
93 } END_UNICODE_STRING(env, path);
94 if (rv == NULL) {
95 JNU_ThrowIOExceptionWithLastError(env, "Bad pathname");
96 }
97 return rv;
98}
99
100
101JNIEXPORT jstring JNICALL
102Java_java_io_WinNTFileSystem_canonicalizeWithPrefix0(JNIEnv *env, jobject this,
103 jstring canonicalPrefixString,
104 jstring pathWithCanonicalPrefixString)
105{
106 jstring rv = NULL;
107 WCHAR canonicalPath[MAX_PATH_LENGTH];
108 WITH_UNICODE_STRING(env, canonicalPrefixString, canonicalPrefix) {
109 WITH_UNICODE_STRING(env, pathWithCanonicalPrefixString, pathWithCanonicalPrefix) {
110 int len = wcslen(canonicalPrefix) + MAX_PATH;
111 if (len > MAX_PATH_LENGTH) {
112 WCHAR *cp = (WCHAR*)malloc(len * sizeof(WCHAR));
113 if (cp != NULL) {
114 if (wcanonicalizeWithPrefix(canonicalPrefix,
115 pathWithCanonicalPrefix,
116 cp, len) >= 0) {
117 rv = (*env)->NewString(env, cp, wcslen(cp));
118 }
119 free(cp);
120 }
121 } else
122 if (wcanonicalizeWithPrefix(canonicalPrefix,
123 pathWithCanonicalPrefix,
124 canonicalPath, MAX_PATH_LENGTH) >= 0) {
125 rv = (*env)->NewString(env, canonicalPath, wcslen(canonicalPath));
126 }
127 } END_UNICODE_STRING(env, pathWithCanonicalPrefix);
128 } END_UNICODE_STRING(env, canonicalPrefix);
129 if (rv == NULL) {
130 JNU_ThrowIOExceptionWithLastError(env, "Bad pathname");
131 }
132 return rv;
133}
134
135/* -- Attribute accessors -- */
136
137/* Check whether or not the file name in "path" is a Windows reserved
138 device name (CON, PRN, AUX, NUL, COM[1-9], LPT[1-9]) based on the
139 returned result from GetFullPathName, which should be in thr form of
140 "\\.\[ReservedDeviceName]" if the path represents a reserved device
141 name.
142 Note1: GetFullPathName doesn't think "CLOCK$" (which is no longer
143 important anyway) is a device name, so we don't check it here.
144 GetFileAttributesEx will catch it later by returning 0 on NT/XP/
145 200X.
146
147 Note2: Theoretically the implementation could just lookup the table
148 below linearly if the first 4 characters of the fullpath returned
149 from GetFullPathName are "\\.\". The current implementation should
150 achieve the same result. If Microsoft add more names into their
151 reserved device name repository in the future, which probably will
152 never happen, we will need to revisit the lookup implementation.
153
154static WCHAR* ReservedDEviceNames[] = {
155 L"CON", L"PRN", L"AUX", L"NUL",
156 L"COM1", L"COM2", L"COM3", L"COM4", L"COM5", L"COM6", L"COM7", L"COM8", L"COM9",
157 L"LPT1", L"LPT2", L"LPT3", L"LPT4", L"LPT5", L"LPT6", L"LPT7", L"LPT8", L"LPT9",
158 L"CLOCK$"
159};
160 */
161
162static BOOL isReservedDeviceNameW(WCHAR* path) {
163#define BUFSIZE 9
164 WCHAR buf[BUFSIZE];
165 WCHAR *lpf = NULL;
166 DWORD retLen = GetFullPathNameW(path,
167 BUFSIZE,
168 buf,
169 &lpf);
170 if ((retLen == BUFSIZE - 1 || retLen == BUFSIZE - 2) &&
171 buf[0] == L'\\' && buf[1] == L'\\' &&
172 buf[2] == L'.' && buf[3] == L'\\') {
173 WCHAR* dname = _wcsupr(buf + 4);
174 if (wcscmp(dname, L"CON") == 0 ||
175 wcscmp(dname, L"PRN") == 0 ||
176 wcscmp(dname, L"AUX") == 0 ||
177 wcscmp(dname, L"NUL") == 0)
178 return TRUE;
179 if ((wcsncmp(dname, L"COM", 3) == 0 ||
180 wcsncmp(dname, L"LPT", 3) == 0) &&
181 dname[3] - L'0' > 0 &&
182 dname[3] - L'0' <= 9)
183 return TRUE;
184 }
185 return FALSE;
186}
187
188JNIEXPORT jint JNICALL
189Java_java_io_WinNTFileSystem_getBooleanAttributes(JNIEnv *env, jobject this,
190 jobject file)
191{
192
193 jint rv = 0;
194 jint pathlen;
195
196 /* both pagefile.sys and hiberfil.sys have length 12 */
197#define SPECIALFILE_NAMELEN 12
198
199 WCHAR *pathbuf = fileToNTPath(env, file, ids.path);
200 WIN32_FILE_ATTRIBUTE_DATA wfad;
201 if (pathbuf == NULL)
202 return rv;
203 if (!isReservedDeviceNameW(pathbuf)) {
204 if (GetFileAttributesExW(pathbuf, GetFileExInfoStandard, &wfad)) {
205 rv = (java_io_FileSystem_BA_EXISTS
206 | ((wfad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
207 ? java_io_FileSystem_BA_DIRECTORY
208 : java_io_FileSystem_BA_REGULAR)
209 | ((wfad.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
210 ? java_io_FileSystem_BA_HIDDEN : 0));
211 } else { /* pagefile.sys is a special case */
212 if (GetLastError() == ERROR_SHARING_VIOLATION) {
213 rv = java_io_FileSystem_BA_EXISTS;
214 if ((pathlen = wcslen(pathbuf)) >= SPECIALFILE_NAMELEN &&
215 (_wcsicmp(pathbuf + pathlen - SPECIALFILE_NAMELEN,
216 L"pagefile.sys") == 0) ||
217 (_wcsicmp(pathbuf + pathlen - SPECIALFILE_NAMELEN,
218 L"hiberfil.sys") == 0))
219 rv |= java_io_FileSystem_BA_REGULAR;
220 }
221 }
222 }
223 free(pathbuf);
224 return rv;
225}
226
227
228JNIEXPORT jboolean
229JNICALL Java_java_io_WinNTFileSystem_checkAccess(JNIEnv *env, jobject this,
230 jobject file, jint access)
231{
232 jboolean rv = JNI_FALSE;
233 int mode;
234 WCHAR *pathbuf = fileToNTPath(env, file, ids.path);
235 if (pathbuf == NULL)
236 return JNI_FALSE;
237 switch (access) {
238 case java_io_FileSystem_ACCESS_READ:
239 case java_io_FileSystem_ACCESS_EXECUTE:
240 mode = 4;
241 break;
242 case java_io_FileSystem_ACCESS_WRITE:
243 mode = 2;
244 break;
245 default: assert(0);
246 }
247 if (_waccess(pathbuf, mode) == 0) {
248 rv = JNI_TRUE;
249 }
250 free(pathbuf);
251 return rv;
252}
253
254JNIEXPORT jboolean JNICALL
255Java_java_io_WinNTFileSystem_setPermission(JNIEnv *env, jobject this,
256 jobject file,
257 jint access,
258 jboolean enable,
259 jboolean owneronly)
260{
261 jboolean rv = JNI_FALSE;
262 WCHAR *pathbuf;
263 DWORD a;
264 if (access == java_io_FileSystem_ACCESS_READ ||
265 access == java_io_FileSystem_ACCESS_EXECUTE) {
266 return enable;
267 }
268 pathbuf = fileToNTPath(env, file, ids.path);
269 if (pathbuf == NULL)
270 return JNI_FALSE;
271 a = GetFileAttributesW(pathbuf);
272 if (a != INVALID_FILE_ATTRIBUTES) {
273 if (enable)
274 a = a & ~FILE_ATTRIBUTE_READONLY;
275 else
276 a = a | FILE_ATTRIBUTE_READONLY;
277 if (SetFileAttributesW(pathbuf, a))
278 rv = JNI_TRUE;
279 }
280 free(pathbuf);
281 return rv;
282}
283
284JNIEXPORT jlong JNICALL
285Java_java_io_WinNTFileSystem_getLastModifiedTime(JNIEnv *env, jobject this,
286 jobject file)
287{
288 jlong rv = 0;
289 LARGE_INTEGER modTime;
290 FILETIME t;
291 HANDLE h;
292 WCHAR *pathbuf = fileToNTPath(env, file, ids.path);
293 if (pathbuf == NULL)
294 return rv;
295 h = CreateFileW(pathbuf,
296 /* Device query access */
297 0,
298 /* Share it */
299 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
300 /* No security attributes */
301 NULL,
302 /* Open existing or fail */
303 OPEN_EXISTING,
304 /* Backup semantics for directories */
305 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
306 /* No template file */
307 NULL);
308 if (h != INVALID_HANDLE_VALUE) {
309 GetFileTime(h, NULL, NULL, &t);
310 CloseHandle(h);
311 modTime.LowPart = (DWORD) t.dwLowDateTime;
312 modTime.HighPart = (LONG) t.dwHighDateTime;
313 rv = modTime.QuadPart / 10000;
314 rv -= 11644473600000;
315 }
316 free(pathbuf);
317 return rv;
318}
319
320JNIEXPORT jlong JNICALL
321Java_java_io_WinNTFileSystem_getLength(JNIEnv *env, jobject this, jobject file)
322{
323 jlong rv = 0;
324 WIN32_FILE_ATTRIBUTE_DATA wfad;
325 WCHAR *pathbuf = fileToNTPath(env, file, ids.path);
326 if (pathbuf == NULL)
327 return rv;
328 if (GetFileAttributesExW(pathbuf,
329 GetFileExInfoStandard,
330 &wfad)) {
331 rv = wfad.nFileSizeHigh * ((jlong)MAXDWORD + 1) + wfad.nFileSizeLow;
332 } else {
333 if (GetLastError() == ERROR_SHARING_VIOLATION) {
334 /* The error is "share violation", which means the file/dir
335 must exists. Try _wstati64, we know this at least works
336 for pagefile.sys and hiberfil.sys.
337 */
338 struct _stati64 sb;
339 if (_wstati64(pathbuf, &sb) == 0) {
340 rv = sb.st_size;
341 }
342 }
343 }
344 free(pathbuf);
345 return rv;
346}
347
348/* -- File operations -- */
349
350JNIEXPORT jboolean JNICALL
351Java_java_io_WinNTFileSystem_createFileExclusively(JNIEnv *env, jclass cls,
352 jstring path)
353{
354 HANDLE h = NULL;
355 WCHAR *pathbuf = pathToNTPath(env, path, JNI_FALSE);
356 if (pathbuf == NULL)
357 return JNI_FALSE;
358 h = CreateFileW(
359 pathbuf, /* Wide char path name */
360 GENERIC_READ | GENERIC_WRITE, /* Read and write permission */
361 FILE_SHARE_READ | FILE_SHARE_WRITE, /* File sharing flags */
362 NULL, /* Security attributes */
363 CREATE_NEW, /* creation disposition */
364 FILE_ATTRIBUTE_NORMAL, /* flags and attributes */
365 NULL);
366
367 if (h == INVALID_HANDLE_VALUE) {
368 DWORD error = GetLastError();
369 if ((error != ERROR_FILE_EXISTS) && (error != ERROR_ALREADY_EXISTS)) {
370
371 // If a directory by the named path already exists,
372 // return false (behavior of solaris and linux) instead of
373 // throwing an exception
374 DWORD fattr = GetFileAttributesW(pathbuf);
375 if ((fattr == INVALID_FILE_ATTRIBUTES) ||
376 (fattr & ~FILE_ATTRIBUTE_DIRECTORY)) {
377 SetLastError(error);
378 JNU_ThrowIOExceptionWithLastError(env, "Could not open file");
379 }
380 }
381 free(pathbuf);
382 return JNI_FALSE;
383 }
384 free(pathbuf);
385 CloseHandle(h);
386 return JNI_TRUE;
387}
388
389static int
390removeFileOrDirectory(const jchar *path)
391{
392 /* Returns 0 on success */
393 DWORD a;
394
395 SetFileAttributesW(path, 0);
396 a = GetFileAttributesW(path);
397 if (a == ((DWORD)-1)) {
398 return 1;
399 } else if (a & FILE_ATTRIBUTE_DIRECTORY) {
400 return !RemoveDirectoryW(path);
401 } else {
402 return !DeleteFileW(path);
403 }
404}
405
406JNIEXPORT jboolean JNICALL
407Java_java_io_WinNTFileSystem_delete0(JNIEnv *env, jobject this, jobject file)
408{
409 jboolean rv = JNI_FALSE;
410 WCHAR *pathbuf = fileToNTPath(env, file, ids.path);
411 if (pathbuf == NULL) {
412 return JNI_FALSE;
413 }
414 if (removeFileOrDirectory(pathbuf) == 0) {
415 rv = JNI_TRUE;
416 }
417 free(pathbuf);
418 return rv;
419}
420
421JNIEXPORT jobjectArray JNICALL
422Java_java_io_WinNTFileSystem_list(JNIEnv *env, jobject this, jobject file)
423{
424 WCHAR *search_path;
425 HANDLE handle;
426 WIN32_FIND_DATAW find_data;
427 int len, maxlen;
428 jobjectArray rv, old;
429 DWORD fattr;
430 jstring name;
431
432 WCHAR *pathbuf = fileToNTPath(env, file, ids.path);
433 if (pathbuf == NULL)
434 return NULL;
435 search_path = (WCHAR*)malloc(2*wcslen(pathbuf) + 6);
436 if (search_path == 0) {
437 free (pathbuf);
438 errno = ENOMEM;
439 return NULL;
440 }
441 wcscpy(search_path, pathbuf);
442 free(pathbuf);
443 fattr = GetFileAttributesW(search_path);
444 if (fattr == INVALID_FILE_ATTRIBUTES) {
445 free(search_path);
446 return NULL;
447 } else if ((fattr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
448 free(search_path);
449 return NULL;
450 }
451
452 /* Remove trailing space chars from directory name */
453 len = wcslen(search_path);
454 while (search_path[len-1] == ' ') {
455 len--;
456 }
457 search_path[len] = 0;
458
459 /* Append "*", or possibly "\\*", to path */
460 if ((search_path[0] == L'\\' && search_path[1] == L'\0') ||
461 (search_path[1] == L':'
462 && (search_path[2] == L'\0'
463 || (search_path[2] == L'\\' && search_path[3] == L'\0')))) {
464 /* No '\\' needed for cases like "\" or "Z:" or "Z:\" */
465 wcscat(search_path, L"*");
466 } else {
467 wcscat(search_path, L"\\*");
468 }
469
470 /* Open handle to the first file */
471 handle = FindFirstFileW(search_path, &find_data);
472 free(search_path);
473 if (handle == INVALID_HANDLE_VALUE) {
474 if (GetLastError() != ERROR_FILE_NOT_FOUND) {
475 // error
476 return NULL;
477 } else {
478 // No files found - return an empty array
479 rv = (*env)->NewObjectArray(env, 0, JNU_ClassString(env), NULL);
480 return rv;
481 }
482 }
483
484 /* Allocate an initial String array */
485 len = 0;
486 maxlen = 16;
487 rv = (*env)->NewObjectArray(env, maxlen, JNU_ClassString(env), NULL);
488 if (rv == NULL) // Couldn't allocate an array
489 return NULL;
490 /* Scan the directory */
491 do {
492 if (!wcscmp(find_data.cFileName, L".")
493 || !wcscmp(find_data.cFileName, L".."))
494 continue;
495 name = (*env)->NewString(env, find_data.cFileName,
496 wcslen(find_data.cFileName));
497 if (name == NULL)
498 return NULL; // error;
499 if (len == maxlen) {
500 old = rv;
501 rv = (*env)->NewObjectArray(env, maxlen <<= 1,
502 JNU_ClassString(env), NULL);
503 if ( rv == NULL
504 || JNU_CopyObjectArray(env, rv, old, len) < 0)
505 return NULL; // error
506 (*env)->DeleteLocalRef(env, old);
507 }
508 (*env)->SetObjectArrayElement(env, rv, len++, name);
509 (*env)->DeleteLocalRef(env, name);
510
511 } while (FindNextFileW(handle, &find_data));
512
513 if (GetLastError() != ERROR_NO_MORE_FILES)
514 return NULL; // error
515 FindClose(handle);
516
517 /* Copy the final results into an appropriately-sized array */
518 old = rv;
519 rv = (*env)->NewObjectArray(env, len, JNU_ClassString(env), NULL);
520 if (rv == NULL)
521 return NULL; /* error */
522 if (JNU_CopyObjectArray(env, rv, old, len) < 0)
523 return NULL; /* error */
524 return rv;
525}
526
527
528JNIEXPORT jboolean JNICALL
529Java_java_io_WinNTFileSystem_createDirectory(JNIEnv *env, jobject this,
530 jobject file)
531{
532 BOOL h = FALSE;
533 WCHAR *pathbuf = fileToNTPath(env, file, ids.path);
534 if (pathbuf == NULL) {
535 /* Exception is pending */
536 return JNI_FALSE;
537 }
538 h = CreateDirectoryW(pathbuf, NULL);
539 free(pathbuf);
540
541 if (h == 0) {
542 return JNI_FALSE;
543 }
544
545 return JNI_TRUE;
546}
547
548
549JNIEXPORT jboolean JNICALL
550Java_java_io_WinNTFileSystem_rename0(JNIEnv *env, jobject this, jobject from,
551 jobject to)
552{
553
554 jboolean rv = JNI_FALSE;
555 WCHAR *frompath = fileToNTPath(env, from, ids.path);
556 WCHAR *topath = fileToNTPath(env, to, ids.path);
557 if (frompath == NULL || topath == NULL)
558 return JNI_FALSE;
559 if (_wrename(frompath, topath) == 0) {
560 rv = JNI_TRUE;
561 }
562 free(frompath);
563 free(topath);
564 return rv;
565}
566
567
568JNIEXPORT jboolean JNICALL
569Java_java_io_WinNTFileSystem_setLastModifiedTime(JNIEnv *env, jobject this,
570 jobject file, jlong time)
571{
572 jboolean rv = JNI_FALSE;
573 WCHAR *pathbuf = fileToNTPath(env, file, ids.path);
574 HANDLE h;
575 if (pathbuf == NULL)
576 return JNI_FALSE;
577 h = CreateFileW(pathbuf, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
578 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
579 if (h != INVALID_HANDLE_VALUE) {
580 LARGE_INTEGER modTime;
581 FILETIME t;
582 modTime.QuadPart = (time + 11644473600000L) * 10000L;
583 t.dwLowDateTime = (DWORD)modTime.LowPart;
584 t.dwHighDateTime = (DWORD)modTime.HighPart;
585 if (SetFileTime(h, NULL, NULL, &t)) {
586 rv = JNI_TRUE;
587 }
588 CloseHandle(h);
589 }
590 free(pathbuf);
591
592 return rv;
593}
594
595
596JNIEXPORT jboolean JNICALL
597Java_java_io_WinNTFileSystem_setReadOnly(JNIEnv *env, jobject this,
598 jobject file)
599{
600 jboolean rv = JNI_FALSE;
601 DWORD a;
602 WCHAR *pathbuf = fileToNTPath(env, file, ids.path);
603 if (pathbuf == NULL)
604 return JNI_FALSE;
605 a = GetFileAttributesW(pathbuf);
606 if (a != INVALID_FILE_ATTRIBUTES) {
607 if (SetFileAttributesW(pathbuf, a | FILE_ATTRIBUTE_READONLY))
608 rv = JNI_TRUE;
609 }
610 free(pathbuf);
611 return rv;
612}
613
614/* -- Filesystem interface -- */
615
616
617JNIEXPORT jobject JNICALL
618Java_java_io_WinNTFileSystem_getDriveDirectory(JNIEnv *env, jobject this,
619 jint drive)
620{
621 jstring ret = NULL;
622 jchar *p = _wgetdcwd(drive, NULL, MAX_PATH);
623 jchar *pf = p;
624 if (p == NULL) return NULL;
625 if (iswalpha(*p) && (p[1] == L':')) p += 2;
626 ret = (*env)->NewString(env, p, wcslen(p));
627 free (pf);
628 return ret;
629}
630
631typedef BOOL (WINAPI* GetVolumePathNameProc) (LPCWSTR, LPWSTR, DWORD);
632
633JNIEXPORT jlong JNICALL
634Java_java_io_WinNTFileSystem_getSpace0(JNIEnv *env, jobject this,
635 jobject file, jint t)
636{
637 WCHAR volname[MAX_PATH_LENGTH + 1];
638 jlong rv = 0L;
639 WCHAR *pathbuf = fileToNTPath(env, file, ids.path);
640
641 HMODULE h = LoadLibrary("kernel32");
642 GetVolumePathNameProc getVolumePathNameW = NULL;
643 if (h) {
644 getVolumePathNameW
645 = (GetVolumePathNameProc)GetProcAddress(h, "GetVolumePathNameW");
646 }
647
648 if (getVolumePathNameW(pathbuf, volname, MAX_PATH_LENGTH)) {
649 ULARGE_INTEGER totalSpace, freeSpace, usableSpace;
650 if (GetDiskFreeSpaceExW(volname, &usableSpace, &totalSpace, &freeSpace)) {
651 switch(t) {
652 case java_io_FileSystem_SPACE_TOTAL:
653 rv = long_to_jlong(totalSpace.QuadPart);
654 break;
655 case java_io_FileSystem_SPACE_FREE:
656 rv = long_to_jlong(freeSpace.QuadPart);
657 break;
658 case java_io_FileSystem_SPACE_USABLE:
659 rv = long_to_jlong(usableSpace.QuadPart);
660 break;
661 default:
662 assert(0);
663 }
664 }
665 }
666
667 if (h) {
668 FreeLibrary(h);
669 }
670 free(pathbuf);
671 return rv;
672}