1 ! Copyright (C) 2008 Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: byte-arrays math io.backend io.files.info
4 io.files.windows io.files.windows.nt kernel windows.kernel32
5 windows.time windows accessors alien.c-types combinators
6 generalizations system alien.strings io.encodings.utf16n
7 sequences splitting windows.errors fry continuations destructors
8 calendar ascii combinators.short-circuit locals classes.struct
9 specialized-arrays.ushort ;
10 IN: io.files.info.windows
12 :: round-up-to ( n multiple -- n' )
19 TUPLE: windows-file-info < file-info attributes ;
21 : get-compressed-file-size ( path -- n )
22 "DWORD" <c-object> [ GetCompressedFileSize ] keep
23 over INVALID_FILE_SIZE = [
24 win32-error-string throw
29 : set-windows-size-on-disk ( file-info path -- file-info )
30 over attributes>> +compressed+ swap member? [
31 get-compressed-file-size
33 drop dup size>> 4096 round-up-to
36 : WIN32_FIND_DATA>file-info ( WIN32_FIND_DATA -- file-info )
37 [ \ windows-file-info new ] dip
39 [ dwFileAttributes>> win32-file-type >>type ]
40 [ dwFileAttributes>> win32-file-attributes >>attributes ]
41 [ [ nFileSizeLow>> ] [ nFileSizeHigh>> ] bi >64bit >>size ]
42 [ dwFileAttributes>> >>permissions ]
43 [ ftCreationTime>> FILETIME>timestamp >>created ]
44 [ ftLastWriteTime>> FILETIME>timestamp >>modified ]
45 [ ftLastAccessTime>> FILETIME>timestamp >>accessed ]
48 : find-first-file-stat ( path -- WIN32_FIND_DATA )
49 WIN32_FIND_DATA <struct> [
51 [ INVALID_HANDLE_VALUE = [ win32-error ] when ] keep
52 FindClose win32-error=0/f
55 : BY_HANDLE_FILE_INFORMATION>file-info ( HANDLE_FILE_INFORMATION -- file-info )
56 [ \ windows-file-info new ] dip
58 [ dwFileAttributes>> win32-file-type >>type ]
59 [ dwFileAttributes>> win32-file-attributes >>attributes ]
62 [ nFileSizeHigh>> ] bi >64bit >>size
64 [ dwFileAttributes>> >>permissions ]
65 [ ftCreationTime>> FILETIME>timestamp >>created ]
66 [ ftLastWriteTime>> FILETIME>timestamp >>modified ]
67 [ ftLastAccessTime>> FILETIME>timestamp >>accessed ]
68 ! [ nNumberOfLinks>> ]
71 ! [ nFileIndexHigh>> ] bi >64bit
75 : get-file-information ( handle -- BY_HANDLE_FILE_INFORMATION )
77 BY_HANDLE_FILE_INFORMATION <struct>
78 [ GetFileInformationByHandle win32-error=0/f ] keep
79 ] keep CloseHandle win32-error=0/f ;
81 : get-file-information-stat ( path -- BY_HANDLE_FILE_INFORMATION )
83 GENERIC_READ FILE_SHARE_READ f
84 OPEN_EXISTING FILE_FLAG_BACKUP_SEMANTICS f
85 CreateFileW dup INVALID_HANDLE_VALUE = [
86 drop find-first-file-stat WIN32_FIND_DATA>file-info
89 get-file-information BY_HANDLE_FILE_INFORMATION>file-info
92 M: windows file-info ( path -- info )
94 [ get-file-information-stat ]
95 [ set-windows-size-on-disk ] bi ;
97 M: windows link-info ( path -- info )
100 : volume-information ( normalized-path -- volume-name volume-serial max-component flags type )
101 MAX_PATH 1 + [ <ushort-array> ] keep
105 MAX_PATH 1 + [ <ushort-array> ] keep
106 [ GetVolumeInformation win32-error=0/f ] 7 nkeep
108 [ utf16n alien>string ] 4 ndip
109 utf16n alien>string ;
111 : file-system-space ( normalized-path -- available-space total-space free-space )
112 "ULARGE_INTEGER" <c-object>
113 "ULARGE_INTEGER" <c-object>
114 "ULARGE_INTEGER" <c-object>
115 [ GetDiskFreeSpaceEx win32-error=0/f ] 3keep ;
117 : calculate-file-system-info ( file-system-info -- file-system-info' )
118 [ dup [ total-space>> ] [ free-space>> ] bi - >>used-space drop ] keep ;
120 TUPLE: win32-file-system-info < file-system-info max-component flags device-serial ;
122 ERROR: not-absolute-path ;
124 : root-directory ( string -- string' )
125 unicode-prefix ?head drop
130 } 1&& [ 2 head "\\" append ] [ not-absolute-path ] if ;
134 : (file-system-info) ( path -- file-system-info )
135 dup [ volume-information ] [ file-system-space ] bi
136 \ win32-file-system-info new
137 swap *ulonglong >>free-space
138 swap *ulonglong >>total-space
139 swap *ulonglong >>available-space
142 swap *uint >>max-component
143 swap *uint >>device-serial
146 calculate-file-system-info ;
150 M: winnt file-system-info ( path -- file-system-info )
151 normalize-path root-directory (file-system-info) ;
153 : volume>paths ( string -- array )
154 16384 <ushort-array> tuck dup length
155 0 <uint> dup [ GetVolumePathNamesForVolumeName 0 = ] dip swap [
156 win32-error-string throw
158 *uint "ushort" heap-size * head
159 utf16n alien>string CHAR: \0 split
162 : find-first-volume ( -- string handle )
163 MAX_PATH 1 + [ <ushort-array> ] keep
165 FindFirstVolume dup win32-error=0/f
166 [ utf16n alien>string ] dip ;
168 : find-next-volume ( handle -- string/f )
169 MAX_PATH 1 + [ <ushort-array> tuck ] keep
171 GetLastError ERROR_NO_MORE_FILES =
172 [ drop f ] [ win32-error-string throw ] if
177 : find-volumes ( -- array )
181 [ _ find-next-volume dup ] [ ] produce nip
184 ] [ '[ _ FindVolumeClose win32-error=0/f ] ] bi [ ] cleanup ;
186 M: winnt file-systems ( -- array )
187 find-volumes [ volume>paths ] map
189 [ (file-system-info) ]
190 [ drop \ file-system-info new swap >>mount-point ] recover
193 : file-times ( path -- timestamp timestamp timestamp )
195 normalize-path open-read &dispose handle>>
199 [ GetFileTime win32-error=0/f ] 3keep
200 [ FILETIME>timestamp >local-time ] tri@
203 : set-file-times ( path timestamp/f timestamp/f timestamp/f -- )
204 #! timestamp order: creation access write
207 normalize-path open-existing &dispose handle>>
208 ] 3dip (set-file-times)
211 : set-file-create-time ( path timestamp -- )
214 : set-file-access-time ( path timestamp -- )
215 [ f ] dip f set-file-times ;
217 : set-file-write-time ( path timestamp -- )
218 [ f f ] dip set-file-times ;