factor/basis/io/windows/files/files.factor

367 lines
12 KiB
Factor
Raw Normal View History

2008-03-04 23:35:45 -05:00
! Copyright (C) 2008 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: alien.c-types io.binary io.backend io.files io.buffers
2008-10-19 16:29:59 -04:00
io.windows kernel math splitting fry alien.strings
2008-03-29 00:00:20 -04:00
windows windows.kernel32 windows.time calendar combinators
2008-09-11 02:27:23 -04:00
math.functions sequences namespaces make words symbols system
2008-10-19 16:29:59 -04:00
io.ports destructors accessors math.bitwise continuations
2008-10-22 23:02:33 -04:00
windows.errors arrays byte-arrays ;
2008-03-04 23:35:45 -05:00
IN: io.windows.files
2008-05-15 02:45:32 -04:00
: open-file ( path access-mode create-mode flags -- handle )
[
>r >r share-mode default-security-attributes r> r>
CreateFile-flags f CreateFile opened-file
2008-05-15 02:45:32 -04:00
] with-destructors ;
: open-pipe-r/w ( path -- win32-file )
{ GENERIC_READ GENERIC_WRITE } flags
OPEN_EXISTING 0 open-file ;
: open-read ( path -- win32-file )
GENERIC_READ OPEN_EXISTING 0 open-file 0 >>ptr ;
: open-write ( path -- win32-file )
GENERIC_WRITE CREATE_ALWAYS 0 open-file 0 >>ptr ;
: (open-append) ( path -- win32-file )
GENERIC_WRITE OPEN_ALWAYS 0 open-file ;
: open-existing ( path -- win32-file )
{ GENERIC_READ GENERIC_WRITE } flags
share-mode
f
OPEN_EXISTING
FILE_FLAG_BACKUP_SEMANTICS
f CreateFileW dup win32-error=0/f <win32-file> ;
: maybe-create-file ( path -- win32-file ? )
#! return true if file was just created
{ GENERIC_READ GENERIC_WRITE } flags
share-mode
f
OPEN_ALWAYS
0 CreateFile-flags
f CreateFileW dup win32-error=0/f <win32-file>
GetLastError ERROR_ALREADY_EXISTS = not ;
: set-file-pointer ( handle length method -- )
>r dupd d>w/w <uint> r> SetFilePointer
INVALID_SET_FILE_POINTER = [
CloseHandle "SetFilePointer failed" throw
] when drop ;
HOOK: open-append os ( path -- win32-file )
TUPLE: FileArgs
hFile lpBuffer nNumberOfBytesToRead
lpNumberOfBytesRet lpOverlapped ;
C: <FileArgs> FileArgs
: make-FileArgs ( port -- <FileArgs> )
{
[ handle>> check-disposed ]
2008-05-15 02:45:32 -04:00
[ handle>> handle>> ]
[ buffer>> ]
[ buffer>> buffer-length ]
[ drop "DWORD" <c-object> ]
[ FileArgs-overlapped ]
} cleave <FileArgs> ;
: setup-read ( <FileArgs> -- hFile lpBuffer nNumberOfBytesToRead lpNumberOfBytesRead lpOverlapped )
{
[ hFile>> ]
[ lpBuffer>> buffer-end ]
[ lpBuffer>> buffer-capacity ]
[ lpNumberOfBytesRet>> ]
[ lpOverlapped>> ]
} cleave ;
: setup-write ( <FileArgs> -- hFile lpBuffer nNumberOfBytesToWrite lpNumberOfBytesWritten lpOverlapped )
{
[ hFile>> ]
[ lpBuffer>> buffer@ ]
[ lpBuffer>> buffer-length ]
[ lpNumberOfBytesRet>> ]
[ lpOverlapped>> ]
} cleave ;
M: windows (file-reader) ( path -- stream )
open-read <input-port> ;
M: windows (file-writer) ( path -- stream )
open-write <output-port> ;
M: windows (file-appender) ( path -- stream )
open-append <output-port> ;
M: windows move-file ( from to -- )
[ normalize-path ] bi@ MoveFile win32-error=0/f ;
M: windows delete-file ( path -- )
normalize-path DeleteFile win32-error=0/f ;
M: windows copy-file ( from to -- )
dup parent-directory make-directories
[ normalize-path ] bi@ 0 CopyFile win32-error=0/f ;
M: windows make-directory ( path -- )
normalize-path
f CreateDirectory win32-error=0/f ;
M: windows delete-directory ( path -- )
normalize-path
RemoveDirectory win32-error=0/f ;
2008-10-19 16:29:59 -04:00
: find-first-file ( path -- WIN32_FIND_DATA handle )
"WIN32_FIND_DATA" <c-object> tuck
FindFirstFile
[ INVALID_HANDLE_VALUE = [ win32-error ] when ] keep ;
: find-next-file ( path -- WIN32_FIND_DATA/f )
"WIN32_FIND_DATA" <c-object> tuck
FindNextFile 0 = [
GetLastError ERROR_NO_MORE_FILES = [
win32-error
] unless drop f
] when ;
M: windows (directory-entries) ( path -- seq )
"\\" ?tail drop "\\*" append
find-first-file [ >directory-entry ] dip
[
'[
[ _ find-next-file dup ]
[ >directory-entry ]
[ drop ] produce
over name>> "." = [ nip ] [ swap prefix ] if
]
] [ '[ _ FindClose win32-error=0/f ] ] bi [ ] cleanup ;
2008-05-15 02:45:32 -04:00
2008-03-07 22:25:26 -05:00
SYMBOLS: +read-only+ +hidden+ +system+
2008-03-15 07:22:57 -04:00
+archive+ +device+ +normal+ +temporary+
2008-03-07 22:25:26 -05:00
+sparse-file+ +reparse-point+ +compressed+ +offline+
+not-content-indexed+ +encrypted+ ;
2008-03-04 23:35:45 -05:00
2008-11-14 01:03:24 -05:00
TUPLE: windows-file-info < file-info attributes ;
: win32-file-attribute ( n attr symbol -- )
rot mask? [ , ] [ drop ] if ;
2008-03-04 23:35:45 -05:00
: win32-file-attributes ( n -- seq )
2008-03-04 23:35:45 -05:00
[
2008-11-14 01:03:24 -05:00
{
[ +read-only+ FILE_ATTRIBUTE_READONLY win32-file-attribute ]
[ +hidden+ FILE_ATTRIBUTE_HIDDEN win32-file-attribute ]
[ +system+ FILE_ATTRIBUTE_SYSTEM win32-file-attribute ]
[ +directory+ FILE_ATTRIBUTE_DIRECTORY win32-file-attribute ]
[ +archive+ FILE_ATTRIBUTE_ARCHIVE win32-file-attribute ]
[ +device+ FILE_ATTRIBUTE_DEVICE win32-file-attribute ]
[ +normal+ FILE_ATTRIBUTE_NORMAL win32-file-attribute ]
[ +temporary+ FILE_ATTRIBUTE_TEMPORARY win32-file-attribute ]
[ +sparse-file+ FILE_ATTRIBUTE_SPARSE_FILE win32-file-attribute ]
[ +reparse-point+ FILE_ATTRIBUTE_REPARSE_POINT win32-file-attribute ]
[ +compressed+ FILE_ATTRIBUTE_COMPRESSED win32-file-attribute ]
[ +offline+ FILE_ATTRIBUTE_OFFLINE win32-file-attribute ]
[ +not-content-indexed+ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED win32-file-attribute ]
[ +encrypted+ FILE_ATTRIBUTE_ENCRYPTED win32-file-attribute ]
} cleave
2008-03-04 23:35:45 -05:00
] { } make ;
: win32-file-type ( n -- symbol )
FILE_ATTRIBUTE_DIRECTORY mask? +directory+ +regular-file+ ? ;
2008-11-19 17:40:50 -05:00
TUPLE: windows-directory-entry < directory-entry attributes ;
M: windows >directory-entry ( byte-array -- directory-entry )
[ WIN32_FIND_DATA-cFileName utf16n alien>string ]
[ WIN32_FIND_DATA-dwFileAttributes win32-file-type ]
[ WIN32_FIND_DATA-dwFileAttributes win32-file-attributes ]
tri
dupd remove windows-directory-entry boa ;
2008-11-19 17:40:50 -05:00
2008-06-09 17:27:52 -04:00
: WIN32_FIND_DATA>file-info ( WIN32_FIND_DATA -- file-info )
2008-11-14 01:03:24 -05:00
[ \ windows-file-info new ] dip
2008-03-04 23:35:45 -05:00
{
2008-10-06 18:28:42 -04:00
[ WIN32_FIND_DATA-dwFileAttributes win32-file-type >>type ]
2008-11-14 01:03:24 -05:00
[ WIN32_FIND_DATA-dwFileAttributes win32-file-attributes >>attributes ]
2008-03-04 23:35:45 -05:00
[
[ WIN32_FIND_DATA-nFileSizeLow ]
2008-10-06 18:28:42 -04:00
[ WIN32_FIND_DATA-nFileSizeHigh ] bi >64bit >>size
2008-03-04 23:35:45 -05:00
]
2008-10-06 19:07:40 -04:00
[ WIN32_FIND_DATA-dwFileAttributes >>permissions ]
2008-10-06 18:28:42 -04:00
[ WIN32_FIND_DATA-ftCreationTime FILETIME>timestamp >>created ]
[ WIN32_FIND_DATA-ftLastWriteTime FILETIME>timestamp >>modified ]
[ WIN32_FIND_DATA-ftLastAccessTime FILETIME>timestamp >>accessed ]
} cleave ;
2008-03-04 23:35:45 -05:00
: find-first-file-stat ( path -- WIN32_FIND_DATA )
"WIN32_FIND_DATA" <c-object> [
FindFirstFile
[ INVALID_HANDLE_VALUE = [ win32-error ] when ] keep
FindClose win32-error=0/f
] keep ;
2008-06-09 17:27:52 -04:00
: BY_HANDLE_FILE_INFORMATION>file-info ( HANDLE_FILE_INFORMATION -- file-info )
2008-11-14 01:03:24 -05:00
[ \ windows-file-info new ] dip
2008-03-04 23:35:45 -05:00
{
2008-10-06 18:28:42 -04:00
[ BY_HANDLE_FILE_INFORMATION-dwFileAttributes win32-file-type >>type ]
2008-11-14 01:03:24 -05:00
[ BY_HANDLE_FILE_INFORMATION-dwFileAttributes win32-file-attributes >>attributes ]
2008-03-04 23:35:45 -05:00
[
[ BY_HANDLE_FILE_INFORMATION-nFileSizeLow ]
2008-10-06 18:28:42 -04:00
[ BY_HANDLE_FILE_INFORMATION-nFileSizeHigh ] bi >64bit >>size
]
2008-10-06 19:07:40 -04:00
[ BY_HANDLE_FILE_INFORMATION-dwFileAttributes >>permissions ]
2008-10-06 18:28:42 -04:00
[
BY_HANDLE_FILE_INFORMATION-ftCreationTime
FILETIME>timestamp >>created
]
[
BY_HANDLE_FILE_INFORMATION-ftLastWriteTime
FILETIME>timestamp >>modified
]
[
BY_HANDLE_FILE_INFORMATION-ftLastAccessTime
FILETIME>timestamp >>accessed
2008-03-04 23:35:45 -05:00
]
! [ BY_HANDLE_FILE_INFORMATION-nNumberOfLinks ]
! [
! [ BY_HANDLE_FILE_INFORMATION-nFileIndexLow ]
! [ BY_HANDLE_FILE_INFORMATION-nFileIndexHigh ] bi >64bit
! ]
2008-10-06 18:28:42 -04:00
} cleave ;
2008-03-04 23:35:45 -05:00
: get-file-information ( handle -- BY_HANDLE_FILE_INFORMATION )
[
"BY_HANDLE_FILE_INFORMATION" <c-object>
[ 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-04-02 21:09:56 -04:00
M: winnt file-info ( path -- info )
normalize-path get-file-information-stat ;
2008-03-26 23:39:16 -04:00
2008-04-02 21:09:56 -04:00
M: winnt link-info ( path -- info )
2008-03-26 23:39:16 -04:00
file-info ;
2008-03-28 14:37:05 -04:00
HOOK: root-directory os ( string -- string' )
2008-10-21 03:27:39 -04:00
TUPLE: winnt-file-system-info < file-system-info
total-bytes total-free-bytes ;
2008-10-22 23:02:33 -04:00
: file-system-type ( normalized-path -- str )
MAX_PATH 1+ <byte-array>
MAX_PATH 1+
"DWORD" <c-object> "DWORD" <c-object> "DWORD" <c-object>
MAX_PATH 1+ <byte-array>
MAX_PATH 1+
[ GetVolumeInformation win32-error=0/f ] 2keep drop
utf16n alien>string ;
: file-system-space ( normalized-path -- free-space total-bytes total-free-bytes )
2008-10-21 03:27:39 -04:00
"ULARGE_INTEGER" <c-object>
"ULARGE_INTEGER" <c-object>
"ULARGE_INTEGER" <c-object>
2008-10-22 23:02:33 -04:00
[ GetDiskFreeSpaceEx win32-error=0/f ] 3keep ;
M: winnt file-system-info ( path -- file-system-info )
normalize-path root-directory
dup [ file-system-type ] [ file-system-space ] bi
2008-10-21 03:27:39 -04:00
\ winnt-file-system-info new
2008-10-19 18:43:22 -04:00
swap *ulonglong >>total-free-bytes
swap *ulonglong >>total-bytes
swap *ulonglong >>free-space
2008-10-22 23:02:33 -04:00
swap >>type
2008-10-23 14:18:00 -04:00
swap >>mount-point ;
2008-10-22 23:02:33 -04:00
2008-11-11 16:17:35 -05:00
: volume>paths ( string -- array )
16384 "ushort" <c-array> tuck dup length
0 <uint> dup [ GetVolumePathNamesForVolumeName 0 = ] dip swap [
win32-error-string throw
] [
*uint "ushort" heap-size * head
utf16n alien>string CHAR: \0 split
] if ;
2008-11-09 18:27:39 -05:00
: find-first-volume ( -- string handle )
2008-10-22 23:02:33 -04:00
MAX_PATH 1+ <byte-array> dup length
dupd
FindFirstVolume dup win32-error=0/f
[ utf16n alien>string ] dip ;
2008-11-11 16:17:35 -05:00
: find-next-volume ( handle -- string/f )
2008-10-22 23:02:33 -04:00
MAX_PATH 1+ <byte-array> dup length
2008-11-11 16:17:35 -05:00
over [ FindNextVolume ] dip swap 0 = [
GetLastError ERROR_NO_MORE_FILES =
[ drop f ] [ win32-error ] if
] [
utf16n alien>string
] if ;
2008-10-22 23:02:33 -04:00
: find-volumes ( -- array )
2008-10-22 23:02:33 -04:00
find-first-volume
[
'[
[ _ find-next-volume dup ]
[ ]
[ drop ] produce
swap prefix
]
] [ '[ _ FindVolumeClose win32-error=0/f ] ] bi [ ] cleanup ;
M: winnt file-systems ( -- array )
find-volumes [ volume>paths ] map
concat [
[ file-system-info ]
[ drop winnt-file-system-info new swap >>mount-point ] recover
] map ;
2008-10-21 03:27:39 -04:00
2008-03-28 14:37:05 -04:00
: file-times ( path -- timestamp timestamp timestamp )
[
normalize-path open-existing &dispose handle>>
2008-03-28 14:37:05 -04:00
"FILETIME" <c-object>
"FILETIME" <c-object>
"FILETIME" <c-object>
[ GetFileTime win32-error=0/f ] 3keep
[ FILETIME>timestamp >local-time ] tri@
2008-03-28 14:37:05 -04:00
] with-destructors ;
: (set-file-times) ( handle timestamp/f timestamp/f timestamp/f -- )
[ timestamp>FILETIME ] tri@
2008-03-28 14:37:05 -04:00
SetFileTime win32-error=0/f ;
: set-file-times ( path timestamp/f timestamp/f timestamp/f -- )
#! timestamp order: creation access write
[
>r >r >r
normalize-path open-existing &dispose handle>>
2008-03-28 14:37:05 -04:00
r> r> r> (set-file-times)
] with-destructors ;
: set-file-create-time ( path timestamp -- )
f f set-file-times ;
: set-file-access-time ( path timestamp -- )
>r f r> f set-file-times ;
: set-file-write-time ( path timestamp -- )
>r f f r> set-file-times ;
2008-04-02 21:09:56 -04:00
M: winnt touch-file ( path -- )
2008-03-28 14:37:05 -04:00
[
normalize-path
2008-05-15 02:45:32 -04:00
maybe-create-file >r &dispose r>
[ drop ] [ handle>> f now dup (set-file-times) ] if
2008-03-28 14:37:05 -04:00
] with-destructors ;