1 // natFileWin32.cc - Native part of File class for Win32.
3 /* Copyright (C) 1998, 1999, 2002, 2003, 2012 Free Software Foundation, Inc.
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
19 #include <java/io/File.h>
20 #include <java/io/IOException.h>
21 #include <java/util/Vector.h>
22 #include <java/lang/String.h>
23 #include <java/io/FilenameFilter.h>
24 #include <java/io/FileFilter.h>
25 #include <java/lang/System.h>
27 // Java timestamps are milliseconds since the UNIX epoch (00:00:00 UTC on
28 // January 1, 1970) while Win32 file-times are 100-nanosecond intervals
29 // since the Win32 epoch (00:00:00 UTC on January 1, 1601). The following
30 // constant represents the number of milliseconds to be added to a
31 // Java timestamp to base it on the Win32 epoch.
33 // There were 369 years between 1601 and 1970, including 89 leap years
34 // (since 1700, 1800 and 1900 were not leap years):
36 // (89*366 + 280*365) days * 86400 seconds/day = 11644473600 seconds
38 #define WIN32_EPOCH_MILLIS 11644473600000LL
41 java::io::File::access (jint query
)
43 JV_TEMP_STRING_WIN32 (canon
, getCanonicalPath());
47 JvAssert (query
== READ
|| query
== WRITE
|| query
== EXISTS
50 // FIXME: Is it possible to differentiate between existing and reading?
51 // If the file exists but cannot be read because of the secuirty attributes
52 // on an NTFS disk this wont work (it reports it can be read but cant)
53 // Could we use something from the security API?
54 DWORD attributes
= GetFileAttributes (canon
);
58 if ((query
== EXISTS
) || (query
== READ
))
59 return (attributes
== 0xffffffff) ? false : true;
61 return ((attributes
!= 0xffffffff) &&
62 ((attributes
& FILE_ATTRIBUTE_READONLY
) == 0)) ? true : false;
66 java::io::File::stat (jint query
)
68 JV_TEMP_STRING_WIN32 (canon
, getCanonicalPath());
72 JvAssert (query
== DIRECTORY
|| query
== ISFILE
);
74 DWORD attributes
= GetFileAttributes (canon
);
75 if (attributes
== 0xffffffff)
78 if (query
== DIRECTORY
)
79 return attributes
& FILE_ATTRIBUTE_DIRECTORY
? true : false;
81 return attributes
& FILE_ATTRIBUTE_DIRECTORY
? false : true;
85 java::io::File::attr (jint query
)
87 JV_TEMP_STRING_WIN32 (canon
, getCanonicalPath());
91 JvAssert (query
== MODIFIED
|| query
== LENGTH
);
95 if ( ( sHandle
= FindFirstFile( canon
, &info
)) == INVALID_HANDLE_VALUE
)
101 return ((long long)info
.nFileSizeHigh
) << 32
102 | (unsigned long long)info
.nFileSizeLow
;
105 // The file time as returned by Windows is in terms of the number
106 // of 100-nanosecond intervals since 00:00:00 UTC, January 1, 1601.
107 return (((((long long)info
.ftLastWriteTime
.dwHighDateTime
) << 32)
108 | ((unsigned long long)info
.ftLastWriteTime
.dwLowDateTime
))
109 - WIN32_EPOCH_MILLIS
*10000LL) / 10000LL;
114 java::io::File::getCanonicalPath (void)
116 JV_TEMP_STRING_WIN32 (cpath
, path
);
118 // If the filename is blank, use the current directory.
119 LPCTSTR thepath
= cpath
.buf();
124 TCHAR buf2
[MAX_PATH
];
125 if(!GetFullPathName(thepath
, MAX_PATH
, buf2
, &unused
))
126 throw new IOException (JvNewStringLatin1 ("GetFullPathName failed"));
128 return _Jv_Win32NewString (buf2
);
132 java::io::File::isAbsolute (void)
134 // See if the path represents a Windows UNC network path.
135 if (path
->length () > 2
136 && (path
->charAt (0) == '\\') && (path
->charAt (1) == '\\'))
139 // Note that the path is not an absolute path even if it starts with
140 // a '/' or a '\' because it lacks a drive specifier.
142 if (path
->length() < 3)
144 // Hard-code A-Za-z because Windows (I think) can't use non-ASCII
145 // letters as drive names.
146 if ((path
->charAt(0) < 'a' || path
->charAt(0) > 'z')
147 && (path
->charAt(0) < 'A' || path
->charAt(0) > 'Z'))
149 return (path
->charAt(1) == ':'
150 && (path
->charAt(2) == '/' || path
->charAt(2) == '\\'));
153 void java::io::File::init_native ()
155 maxPathLen
= MAX_PATH
;
156 caseSensitive
= false;
160 java::io::File::performList (java::io::FilenameFilter
*filter
,
161 java::io::FileFilter
*fileFilter
,
162 java::lang::Class
*clazz
)
164 jstring canon
= getCanonicalPath();
168 int len
= canon
->length();
171 JV_TEMP_STRING_WIN32(canonstr
, canon
);
173 _tcscpy(buf
, canonstr
);
174 if (buf
[len
- 1] == _T('\\'))
175 _tcscpy (&buf
[len
], _T("*.*"));
177 _tcscpy (&buf
[len
], _T("\\*.*"));
179 WIN32_FIND_DATA data
;
180 HANDLE handle
= FindFirstFile (buf
, &data
);
181 if (handle
== INVALID_HANDLE_VALUE
)
184 java::util::Vector
*vec
= new java::util::Vector ();
188 if (_tcscmp (data
.cFileName
, _T(".")) &&
189 _tcscmp (data
.cFileName
, _T("..")))
191 jstring name
= _Jv_Win32NewString (data
.cFileName
);
193 if (filter
&& !filter
->accept(this, name
))
195 if (clazz
== &java::io::File::class$
)
197 java::io::File
*file
= new java::io::File (this, name
);
198 if (fileFilter
&& !fileFilter
->accept(file
))
200 vec
->addElement (file
);
203 vec
->addElement (name
);
206 while (FindNextFile (handle
, &data
));
208 if (GetLastError () != ERROR_NO_MORE_FILES
)
213 jobjectArray ret
= JvNewObjectArray (vec
->size(), clazz
, NULL
);
219 java::io::File::setFilePermissions (jboolean enable
,
223 JV_TEMP_STRING_WIN32 (canon
, getCanonicalPath());
227 DWORD attrs
= GetFileAttributes (canon
);
228 if (attrs
!= INVALID_FILE_ATTRIBUTES
)
238 java::io::File::performMkdir (void)
240 JV_TEMP_STRING_WIN32 (cpath
, path
);
241 return (CreateDirectory(cpath
, NULL
)) ? true : false;
245 java::io::File::performRenameTo (File
*dest
)
247 JV_TEMP_STRING_WIN32 (pathFrom
, path
);
248 JV_TEMP_STRING_WIN32 (pathTo
, dest
->path
);
249 return (MoveFile(pathFrom
, pathTo
)) ? true : false;
253 java::io::File::performDelete ()
255 JV_TEMP_STRING_WIN32 (canon
, getCanonicalPath());
259 DWORD attributes
= GetFileAttributes (canon
);
260 if (attributes
== 0xffffffff)
263 if (attributes
& FILE_ATTRIBUTE_DIRECTORY
)
264 return (RemoveDirectory (canon
)) ? true : false;
266 return (DeleteFile (canon
)) ? true : false;
269 jboolean
java::io::File::performCreate (void)
271 JV_TEMP_STRING_WIN32 (canon
, getCanonicalPath());
275 HANDLE h
= CreateFile (canon
, 0, 0, NULL
, CREATE_NEW
,
276 FILE_ATTRIBUTE_NORMAL
, NULL
);
277 if (h
!= INVALID_HANDLE_VALUE
)
284 if (GetLastError () == ERROR_ALREADY_EXISTS
)
287 throw new IOException (JvNewStringLatin1 ("CreateFile failed"));
291 jboolean
java::io::File::performSetReadOnly ()
293 JV_TEMP_STRING_WIN32 (canon
, getCanonicalPath());
297 DWORD attrs
= GetFileAttributes (canon
);
298 if (attrs
!= INVALID_FILE_ATTRIBUTES
)
300 if (SetFileAttributes (canon
, attrs
| FILE_ATTRIBUTE_READONLY
) != 0)
309 jboolean
java::io::File::performSetLastModified (jlong time
)
311 JV_TEMP_STRING_WIN32 (canon
, getCanonicalPath());
316 long long mTime100ns
= ((long long) time
/* Ha! */
317 + WIN32_EPOCH_MILLIS
) * 10000LL;
319 modTime
.dwLowDateTime
= (DWORD
) mTime100ns
;
320 modTime
.dwHighDateTime
= (DWORD
) (mTime100ns
>> 32);
322 jboolean retVal
= false;
323 HANDLE h
= CreateFile (canon
, FILE_WRITE_ATTRIBUTES
,
324 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
325 NULL
, OPEN_EXISTING
, 0, NULL
);
327 if (h
!= INVALID_HANDLE_VALUE
)
329 if (SetFileTime (h
, NULL
, &modTime
, &modTime
) != 0)
338 JArray
<java::io::File
*>* java::io::File::performListRoots ()
340 DWORD drivesBitmap
= GetLogicalDrives ();
343 // Possible drive letters are from ASCII 'A'-'Z'.
346 for (int i
= 0; i
< 26; i
++)
348 if ((drivesBitmap
& mask
) != 0)
353 JArray
<java::io::File
*> *roots
354 = reinterpret_cast <JArray
<java::io::File
*>*>
355 (JvNewObjectArray (numDrives
, &java::io::File::class$
, NULL
));
357 ::java::io::File
**rootsArray
= elements (roots
);
359 char aDriveRoot
[] = {'A', ':', '\\', '\0'};
361 for (int i
= 0, j
= 0; i
< 26; i
++)
363 if ((drivesBitmap
& mask
) != 0)
366 = new ::java::io::File (JvNewStringLatin1 (aDriveRoot
));