2008-12-15 02:32:21 -05:00
|
|
|
! Copyright (C) 2008 Doug Coleman.
|
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
2008-12-13 05:41:33 -05:00
|
|
|
USING: byte-arrays math io.backend io.files.info
|
2010-09-19 15:02:32 -04:00
|
|
|
io.files.windows kernel windows.kernel32
|
2009-11-21 18:24:37 -05:00
|
|
|
windows.time windows.types windows accessors alien.c-types
|
|
|
|
combinators generalizations system alien.strings
|
2012-06-21 11:32:53 -04:00
|
|
|
sequences splitting windows.errors fry
|
2009-11-21 18:24:37 -05:00
|
|
|
continuations destructors calendar ascii
|
2010-05-23 04:27:40 -04:00
|
|
|
combinators.short-circuit literals locals classes.struct
|
2012-10-24 20:28:50 -04:00
|
|
|
specialized-arrays alien.data libc windows.shell32 ;
|
2009-09-09 23:33:34 -04:00
|
|
|
SPECIALIZED-ARRAY: ushort
|
2012-06-21 11:32:53 -04:00
|
|
|
QUALIFIED: sequences
|
2008-12-15 02:32:21 -05:00
|
|
|
IN: io.files.info.windows
|
|
|
|
|
2009-04-20 17:52:18 -04:00
|
|
|
:: round-up-to ( n multiple -- n' )
|
2009-08-11 19:00:24 -04:00
|
|
|
n multiple rem [
|
|
|
|
n
|
2009-04-20 17:52:18 -04:00
|
|
|
] [
|
|
|
|
multiple swap - n +
|
2009-08-11 19:00:24 -04:00
|
|
|
] if-zero ;
|
2009-04-20 17:52:18 -04:00
|
|
|
|
2013-03-23 22:14:28 -04:00
|
|
|
TUPLE: windows-file-info < file-info-tuple attributes ;
|
2008-12-15 02:32:21 -05:00
|
|
|
|
2009-04-20 17:52:18 -04:00
|
|
|
: get-compressed-file-size ( path -- n )
|
2010-07-16 17:32:05 -04:00
|
|
|
{ DWORD } [ GetCompressedFileSize ] with-out-parameters
|
2010-05-23 03:07:47 -04:00
|
|
|
over INVALID_FILE_SIZE = [ win32-error-string throw ] [ >64bit ] if ;
|
2009-04-20 17:52:18 -04:00
|
|
|
|
|
|
|
: set-windows-size-on-disk ( file-info path -- file-info )
|
|
|
|
over attributes>> +compressed+ swap member? [
|
|
|
|
get-compressed-file-size
|
|
|
|
] [
|
|
|
|
drop dup size>> 4096 round-up-to
|
|
|
|
] if >>size-on-disk ;
|
|
|
|
|
2008-12-15 02:32:21 -05:00
|
|
|
: WIN32_FIND_DATA>file-info ( WIN32_FIND_DATA -- file-info )
|
|
|
|
[ \ windows-file-info new ] dip
|
|
|
|
{
|
2009-08-29 14:45:25 -04:00
|
|
|
[ dwFileAttributes>> win32-file-type >>type ]
|
|
|
|
[ dwFileAttributes>> win32-file-attributes >>attributes ]
|
|
|
|
[ [ nFileSizeLow>> ] [ nFileSizeHigh>> ] bi >64bit >>size ]
|
|
|
|
[ dwFileAttributes>> >>permissions ]
|
|
|
|
[ ftCreationTime>> FILETIME>timestamp >>created ]
|
|
|
|
[ ftLastWriteTime>> FILETIME>timestamp >>modified ]
|
|
|
|
[ ftLastAccessTime>> FILETIME>timestamp >>accessed ]
|
2008-12-15 02:32:21 -05:00
|
|
|
} cleave ;
|
|
|
|
|
|
|
|
: find-first-file-stat ( path -- WIN32_FIND_DATA )
|
2009-08-29 14:45:25 -04:00
|
|
|
WIN32_FIND_DATA <struct> [
|
2008-12-15 02:32:21 -05:00
|
|
|
FindFirstFile
|
|
|
|
[ INVALID_HANDLE_VALUE = [ win32-error ] when ] keep
|
|
|
|
FindClose win32-error=0/f
|
|
|
|
] keep ;
|
|
|
|
|
|
|
|
: BY_HANDLE_FILE_INFORMATION>file-info ( HANDLE_FILE_INFORMATION -- file-info )
|
|
|
|
[ \ windows-file-info new ] dip
|
|
|
|
{
|
2009-08-25 18:23:23 -04:00
|
|
|
[ dwFileAttributes>> win32-file-type >>type ]
|
|
|
|
[ dwFileAttributes>> win32-file-attributes >>attributes ]
|
2008-12-15 02:32:21 -05:00
|
|
|
[
|
2009-08-25 18:23:23 -04:00
|
|
|
[ nFileSizeLow>> ]
|
|
|
|
[ nFileSizeHigh>> ] bi >64bit >>size
|
2008-12-15 02:32:21 -05:00
|
|
|
]
|
2009-08-25 18:23:23 -04:00
|
|
|
[ dwFileAttributes>> >>permissions ]
|
|
|
|
[ ftCreationTime>> FILETIME>timestamp >>created ]
|
|
|
|
[ ftLastWriteTime>> FILETIME>timestamp >>modified ]
|
|
|
|
[ ftLastAccessTime>> FILETIME>timestamp >>accessed ]
|
|
|
|
! [ nNumberOfLinks>> ]
|
2008-12-15 02:32:21 -05:00
|
|
|
! [
|
2009-08-25 18:23:23 -04:00
|
|
|
! [ nFileIndexLow>> ]
|
|
|
|
! [ nFileIndexHigh>> ] bi >64bit
|
2008-12-15 02:32:21 -05:00
|
|
|
! ]
|
|
|
|
} cleave ;
|
|
|
|
|
|
|
|
: get-file-information ( handle -- BY_HANDLE_FILE_INFORMATION )
|
|
|
|
[
|
2009-08-25 18:23:23 -04:00
|
|
|
BY_HANDLE_FILE_INFORMATION <struct>
|
2008-12-15 02:32:21 -05:00
|
|
|
[ GetFileInformationByHandle win32-error=0/f ] keep
|
|
|
|
] keep CloseHandle win32-error=0/f ;
|
|
|
|
|
|
|
|
: get-file-information-stat ( path -- BY_HANDLE_FILE_INFORMATION )
|
|
|
|
dup
|
|
|
|
GENERIC_READ FILE_SHARE_READ f
|
|
|
|
OPEN_EXISTING FILE_FLAG_BACKUP_SEMANTICS f
|
|
|
|
CreateFileW dup INVALID_HANDLE_VALUE = [
|
|
|
|
drop find-first-file-stat WIN32_FIND_DATA>file-info
|
|
|
|
] [
|
|
|
|
nip
|
|
|
|
get-file-information BY_HANDLE_FILE_INFORMATION>file-info
|
|
|
|
] if ;
|
|
|
|
|
2008-12-13 05:41:33 -05:00
|
|
|
M: windows file-info ( path -- info )
|
2009-04-20 17:52:18 -04:00
|
|
|
normalize-path
|
|
|
|
[ get-file-information-stat ]
|
|
|
|
[ set-windows-size-on-disk ] bi ;
|
2008-12-15 02:32:21 -05:00
|
|
|
|
2008-12-13 05:41:33 -05:00
|
|
|
M: windows link-info ( path -- info )
|
2008-12-15 02:32:21 -05:00
|
|
|
file-info ;
|
|
|
|
|
2012-10-24 22:02:59 -04:00
|
|
|
: file-executable-type ( path -- executable/f )
|
|
|
|
normalize-path dup
|
|
|
|
0
|
|
|
|
f
|
|
|
|
! hi is zero means old style executable
|
|
|
|
0 SHGFI_EXETYPE SHGetFileInfoW
|
|
|
|
[
|
|
|
|
file-info drop f
|
|
|
|
] [
|
|
|
|
nip >lo-hi first2 zero? [
|
|
|
|
{
|
|
|
|
{ 0x5A4D [ +dos-executable+ ] }
|
|
|
|
{ 0x4550 [ +win32-console-executable+ ] }
|
|
|
|
[ drop f ]
|
|
|
|
} case
|
|
|
|
] [
|
|
|
|
{
|
|
|
|
{ 0x454C [ +win32-vxd-executable+ ] }
|
|
|
|
{ 0x454E [ +win32-os2-executable+ ] }
|
|
|
|
{ 0x4550 [ +win32-nt-executable+ ] }
|
|
|
|
[ drop f ]
|
|
|
|
} case
|
|
|
|
] if
|
|
|
|
] if-zero ;
|
|
|
|
|
2010-05-23 03:07:47 -04:00
|
|
|
CONSTANT: path-length $[ MAX_PATH 1 + ]
|
|
|
|
|
2008-12-15 02:32:21 -05:00
|
|
|
: volume-information ( normalized-path -- volume-name volume-serial max-component flags type )
|
2010-05-23 03:07:47 -04:00
|
|
|
{ { ushort path-length } DWORD DWORD DWORD { ushort path-length } }
|
|
|
|
[ [ path-length ] 4dip path-length GetVolumeInformation win32-error=0/f ]
|
2010-07-16 17:32:05 -04:00
|
|
|
with-out-parameters
|
2012-06-21 11:32:53 -04:00
|
|
|
[ alien>native-string ] 4dip alien>native-string ;
|
2008-12-15 02:32:21 -05:00
|
|
|
|
|
|
|
: file-system-space ( normalized-path -- available-space total-space free-space )
|
2010-05-23 03:07:47 -04:00
|
|
|
{ ULARGE_INTEGER ULARGE_INTEGER ULARGE_INTEGER }
|
2010-07-16 17:32:05 -04:00
|
|
|
[ GetDiskFreeSpaceEx win32-error=0/f ]
|
2010-05-23 03:07:47 -04:00
|
|
|
with-out-parameters ;
|
2008-12-15 02:32:21 -05:00
|
|
|
|
|
|
|
: calculate-file-system-info ( file-system-info -- file-system-info' )
|
2008-12-18 19:32:00 -05:00
|
|
|
[ dup [ total-space>> ] [ free-space>> ] bi - >>used-space drop ] keep ;
|
2008-12-15 02:32:21 -05:00
|
|
|
|
2013-03-23 22:14:28 -04:00
|
|
|
TUPLE: win32-file-system-info < file-system-info-tuple max-component flags device-serial ;
|
2008-12-15 02:32:21 -05:00
|
|
|
|
2008-12-13 05:41:33 -05:00
|
|
|
ERROR: not-absolute-path ;
|
|
|
|
|
|
|
|
: root-directory ( string -- string' )
|
|
|
|
unicode-prefix ?head drop
|
|
|
|
dup {
|
|
|
|
[ length 2 >= ]
|
|
|
|
[ second CHAR: : = ]
|
|
|
|
[ first Letter? ]
|
|
|
|
} 1&& [ 2 head "\\" append ] [ not-absolute-path ] if ;
|
2008-12-15 02:32:21 -05:00
|
|
|
|
2009-09-08 18:10:19 -04:00
|
|
|
<PRIVATE
|
|
|
|
|
2009-09-08 18:05:05 -04:00
|
|
|
: (file-system-info) ( path -- file-system-info )
|
2008-12-15 02:32:21 -05:00
|
|
|
dup [ volume-information ] [ file-system-space ] bi
|
|
|
|
\ win32-file-system-info new
|
2010-05-23 03:07:47 -04:00
|
|
|
swap >>free-space
|
|
|
|
swap >>total-space
|
|
|
|
swap >>available-space
|
2008-12-15 02:32:21 -05:00
|
|
|
swap >>type
|
2010-05-23 03:07:47 -04:00
|
|
|
swap >>flags
|
|
|
|
swap >>max-component
|
|
|
|
swap >>device-serial
|
2008-12-15 02:32:21 -05:00
|
|
|
swap >>device-name
|
|
|
|
swap >>mount-point
|
|
|
|
calculate-file-system-info ;
|
|
|
|
|
2009-09-08 18:10:19 -04:00
|
|
|
PRIVATE>
|
|
|
|
|
2011-09-18 21:25:06 -04:00
|
|
|
M: windows file-system-info ( path -- file-system-info )
|
2009-09-08 18:05:05 -04:00
|
|
|
normalize-path root-directory (file-system-info) ;
|
|
|
|
|
2010-05-23 03:07:47 -04:00
|
|
|
CONSTANT: names-buf-length 16384
|
2009-11-05 18:03:24 -05:00
|
|
|
|
2008-12-15 02:32:21 -05:00
|
|
|
: find-first-volume ( -- string handle )
|
2010-05-23 03:07:47 -04:00
|
|
|
{ { ushort path-length } }
|
|
|
|
[ path-length FindFirstVolume dup win32-error=0/f ]
|
2012-06-21 11:32:53 -04:00
|
|
|
with-out-parameters alien>native-string swap ;
|
2010-05-23 03:07:47 -04:00
|
|
|
|
|
|
|
: find-next-volume ( handle -- string/f )
|
|
|
|
{ { ushort path-length } }
|
2010-07-16 17:32:05 -04:00
|
|
|
[ path-length FindNextVolume ] with-out-parameters
|
|
|
|
swap 0 = [
|
|
|
|
GetLastError ERROR_NO_MORE_FILES =
|
|
|
|
[ drop f ] [ win32-error-string throw ] if
|
2012-06-21 11:32:53 -04:00
|
|
|
] [ alien>native-string ] if ;
|
2008-12-15 02:32:21 -05:00
|
|
|
|
|
|
|
: find-volumes ( -- array )
|
|
|
|
find-first-volume
|
|
|
|
[
|
|
|
|
'[
|
2009-02-28 16:31:34 -05:00
|
|
|
[ _ find-next-volume dup ] [ ] produce nip
|
2008-12-15 02:32:21 -05:00
|
|
|
swap prefix
|
|
|
|
]
|
|
|
|
] [ '[ _ FindVolumeClose win32-error=0/f ] ] bi [ ] cleanup ;
|
|
|
|
|
2012-06-21 11:32:53 -04:00
|
|
|
! Windows may return a volume which looks up to path ""
|
|
|
|
! For now, treat it like there is not a volume here
|
|
|
|
: volume>paths ( string -- array )
|
|
|
|
[
|
|
|
|
names-buf-length
|
|
|
|
[ ushort malloc-array &free ] keep
|
|
|
|
0 uint <ref>
|
|
|
|
[ GetVolumePathNamesForVolumeName win32-error=0/f ] 3keep nip
|
|
|
|
uint deref head but-last-slice
|
2013-03-31 19:04:11 -04:00
|
|
|
{ 0 } split-slice harvest
|
|
|
|
[ { } ] [ [ { 0 } append alien>native-string ] map ] if-empty
|
2012-06-21 11:32:53 -04:00
|
|
|
] with-destructors ;
|
|
|
|
|
2012-09-16 20:23:25 -04:00
|
|
|
! Can error with T{ windows-error f 21 "The device is not ready." }
|
|
|
|
! if there is a D: that is not ready, for instance. Ignore these drives.
|
2011-09-18 21:25:06 -04:00
|
|
|
M: windows file-systems ( -- array )
|
2012-06-21 11:32:53 -04:00
|
|
|
find-volumes [ volume>paths ] map concat [
|
2012-09-16 20:23:25 -04:00
|
|
|
[ (file-system-info) ] [ 2drop f ] recover
|
|
|
|
] map sift ;
|
2008-12-15 02:32:21 -05:00
|
|
|
|
|
|
|
: file-times ( path -- timestamp timestamp timestamp )
|
|
|
|
[
|
2009-08-25 18:34:06 -04:00
|
|
|
normalize-path open-read &dispose handle>>
|
2010-05-23 03:07:47 -04:00
|
|
|
{ FILETIME FILETIME FILETIME }
|
|
|
|
[ GetFileTime win32-error=0/f ]
|
|
|
|
with-out-parameters
|
2010-07-16 17:32:05 -04:00
|
|
|
[ FILETIME>timestamp >local-time ] tri@
|
2008-12-15 02:32:21 -05:00
|
|
|
] with-destructors ;
|
|
|
|
|
|
|
|
: set-file-times ( path timestamp/f timestamp/f timestamp/f -- )
|
|
|
|
#! timestamp order: creation access write
|
|
|
|
[
|
|
|
|
[
|
|
|
|
normalize-path open-existing &dispose handle>>
|
|
|
|
] 3dip (set-file-times)
|
|
|
|
] with-destructors ;
|
|
|
|
|
|
|
|
: set-file-create-time ( path timestamp -- )
|
|
|
|
f f set-file-times ;
|
|
|
|
|
|
|
|
: set-file-access-time ( path timestamp -- )
|
|
|
|
[ f ] dip f set-file-times ;
|
|
|
|
|
|
|
|
: set-file-write-time ( path timestamp -- )
|
|
|
|
[ f f ] dip set-file-times ;
|
2012-10-24 20:28:50 -04:00
|
|
|
|
|
|
|
M: windows file-readable? file-info >boolean ;
|
|
|
|
M: windows file-writable? file-info attributes>> +read-only+ swap member? not ;
|
|
|
|
M: windows file-executable? file-executable-type windows-executable? ;
|