1 ! Copyright (C) 2008 Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors kernel system math math.bitwise strings arrays
4 sequences combinators combinators.short-circuit alien.c-types
5 vocabs.loader calendar calendar.unix io.files.info
6 io.files.types io.backend unix unix.stat unix.time unix.users
10 TUPLE: unix-file-system-info < file-system-info
11 block-size preferred-block-size
12 blocks blocks-free blocks-available
13 files files-free files-available
16 HOOK: new-file-system-info os ( -- file-system-info )
18 M: unix new-file-system-info ( -- ) unix-file-system-info new ;
20 HOOK: file-system-statfs os ( path -- statfs )
22 M: unix file-system-statfs drop f ;
24 HOOK: file-system-statvfs os ( path -- statvfs )
26 M: unix file-system-statvfs drop f ;
28 HOOK: statfs>file-system-info os ( file-system-info statfs -- file-system-info' )
30 M: unix statfs>file-system-info drop ;
32 HOOK: statvfs>file-system-info os ( file-system-info statvfs -- file-system-info' )
34 M: unix statvfs>file-system-info drop ;
36 : file-system-calculations ( file-system-info -- file-system-info' )
37 dup [ blocks-available>> ] [ block-size>> ] bi * >>available-space
38 dup [ blocks-free>> ] [ block-size>> ] bi * >>free-space
39 dup [ blocks>> ] [ block-size>> ] bi * >>total-space
40 dup [ total-space>> ] [ free-space>> ] bi - >>used-space ;
42 M: unix file-system-info
44 [ new-file-system-info ] dip
45 [ file-system-statfs statfs>file-system-info ]
46 [ file-system-statvfs statvfs>file-system-info ] bi
47 file-system-calculations ;
49 TUPLE: unix-file-info < file-info uid gid dev ino
50 nlink rdev blocks blocksize ;
52 HOOK: new-file-info os ( -- file-info )
54 HOOK: stat>file-info os ( stat -- file-info )
56 HOOK: stat>type os ( stat -- file-info )
58 M: unix file-info ( path -- info )
59 normalize-path file-status stat>file-info ;
61 M: unix link-info ( path -- info )
62 normalize-path link-status stat>file-info ;
64 M: unix new-file-info ( -- class ) unix-file-info new ;
66 M: unix stat>file-info ( stat -- file-info )
70 [ stat-st_size >>size ]
71 [ stat-st_mode >>permissions ]
72 [ stat-st_ctimespec timespec>unix-time >>created ]
73 [ stat-st_mtimespec timespec>unix-time >>modified ]
74 [ stat-st_atimespec timespec>unix-time >>accessed ]
79 [ stat-st_nlink >>nlink ]
80 [ stat-st_rdev >>rdev ]
81 [ stat-st_blocks >>blocks ]
82 [ stat-st_blksize >>blocksize ]
83 [ drop blocks>> blocksize>> * >>size-on-disk ]
86 : n>file-type ( n -- type )
88 { S_IFREG [ +regular-file+ ] }
89 { S_IFDIR [ +directory+ ] }
90 { S_IFCHR [ +character-device+ ] }
91 { S_IFBLK [ +block-device+ ] }
92 { S_IFIFO [ +fifo+ ] }
93 { S_IFLNK [ +symbolic-link+ ] }
94 { S_IFSOCK [ +socket+ ] }
98 M: unix stat>type ( stat -- type )
99 stat-st_mode n>file-type ;
103 : stat-mode ( path -- mode )
104 normalize-path file-status stat-st_mode ;
106 : chmod-set-bit ( path mask ? -- )
107 [ dup stat-mode ] 2dip
108 [ bitor ] [ unmask ] if chmod io-error ;
110 GENERIC# file-mode? 1 ( obj mask -- ? )
112 M: integer file-mode? mask? ;
113 M: string file-mode? [ stat-mode ] dip mask? ;
114 M: file-info file-mode? [ permissions>> ] dip mask? ;
118 CONSTANT: UID OCT: 0004000
119 CONSTANT: GID OCT: 0002000
120 CONSTANT: STICKY OCT: 0001000
121 CONSTANT: USER-ALL OCT: 0000700
122 CONSTANT: USER-READ OCT: 0000400
123 CONSTANT: USER-WRITE OCT: 0000200
124 CONSTANT: USER-EXECUTE OCT: 0000100
125 CONSTANT: GROUP-ALL OCT: 0000070
126 CONSTANT: GROUP-READ OCT: 0000040
127 CONSTANT: GROUP-WRITE OCT: 0000020
128 CONSTANT: GROUP-EXECUTE OCT: 0000010
129 CONSTANT: OTHER-ALL OCT: 0000007
130 CONSTANT: OTHER-READ OCT: 0000004
131 CONSTANT: OTHER-WRITE OCT: 0000002
132 CONSTANT: OTHER-EXECUTE OCT: 0000001
134 : uid? ( obj -- ? ) UID file-mode? ;
135 : gid? ( obj -- ? ) GID file-mode? ;
136 : sticky? ( obj -- ? ) STICKY file-mode? ;
137 : user-read? ( obj -- ? ) USER-READ file-mode? ;
138 : user-write? ( obj -- ? ) USER-WRITE file-mode? ;
139 : user-execute? ( obj -- ? ) USER-EXECUTE file-mode? ;
140 : group-read? ( obj -- ? ) GROUP-READ file-mode? ;
141 : group-write? ( obj -- ? ) GROUP-WRITE file-mode? ;
142 : group-execute? ( obj -- ? ) GROUP-EXECUTE file-mode? ;
143 : other-read? ( obj -- ? ) OTHER-READ file-mode? ;
144 : other-write? ( obj -- ? ) OTHER-WRITE file-mode? ;
145 : other-execute? ( obj -- ? ) OTHER-EXECUTE file-mode? ;
147 : any-read? ( obj -- ? )
148 { [ user-read? ] [ group-read? ] [ other-read? ] } 1|| ;
150 : any-write? ( obj -- ? )
151 { [ user-write? ] [ group-write? ] [ other-write? ] } 1|| ;
153 : any-execute? ( obj -- ? )
154 { [ user-execute? ] [ group-execute? ] [ other-execute? ] } 1|| ;
156 : set-uid ( path ? -- ) UID swap chmod-set-bit ;
157 : set-gid ( path ? -- ) GID swap chmod-set-bit ;
158 : set-sticky ( path ? -- ) STICKY swap chmod-set-bit ;
159 : set-user-read ( path ? -- ) USER-READ swap chmod-set-bit ;
160 : set-user-write ( path ? -- ) USER-WRITE swap chmod-set-bit ;
161 : set-user-execute ( path ? -- ) USER-EXECUTE swap chmod-set-bit ;
162 : set-group-read ( path ? -- ) GROUP-READ swap chmod-set-bit ;
163 : set-group-write ( path ? -- ) GROUP-WRITE swap chmod-set-bit ;
164 : set-group-execute ( path ? -- ) GROUP-EXECUTE swap chmod-set-bit ;
165 : set-other-read ( path ? -- ) OTHER-READ swap chmod-set-bit ;
166 : set-other-write ( path ? -- ) OTHER-WRITE swap chmod-set-bit ;
167 : set-other-execute ( path ? -- ) OTHER-EXECUTE swap chmod-set-bit ;
169 : set-file-permissions ( path n -- )
170 [ normalize-path ] dip chmod io-error ;
172 : file-permissions ( path -- n )
173 normalize-path file-info permissions>> ;
177 : make-timeval-array ( array -- byte-array )
178 [ [ "timeval" <c-object> ] unless* ] map concat ;
180 : timestamp>timeval ( timestamp -- timeval )
181 unix-1970 time- duration>microseconds make-timeval ;
183 : timestamps>byte-array ( timestamps -- byte-array )
184 [ dup [ timestamp>timeval ] when ] map make-timeval-array ;
188 : set-file-times ( path timestamps -- )
190 [ normalize-path ] dip
191 timestamps>byte-array utimes io-error ;
193 : set-file-access-time ( path timestamp -- )
194 f 2array set-file-times ;
196 : set-file-modified-time ( path timestamp -- )
197 f swap 2array set-file-times ;
199 : set-file-ids ( path uid gid -- )
200 [ normalize-path ] 2dip
201 [ [ -1 ] unless* ] bi@ chown io-error ;
203 GENERIC: set-file-user ( path string/id -- )
205 GENERIC: set-file-group ( path string/id -- )
207 M: integer set-file-user ( path uid -- )
210 M: string set-file-user ( path string -- )
211 user-id f set-file-ids ;
213 M: integer set-file-group ( path gid -- )
214 f swap set-file-ids ;
216 M: string set-file-group ( path string -- )
218 f swap set-file-ids ;
220 : file-user-id ( path -- uid )
221 normalize-path file-info uid>> ;
223 : file-user-name ( path -- string )
224 file-user-id user-name ;
226 : file-group-id ( path -- gid )
227 normalize-path file-info gid>> ;
229 : file-group-name ( path -- string )
230 file-group-id group-name ;
232 : ch>file-type ( ch -- type )
234 { CHAR: b [ +block-device+ ] }
235 { CHAR: c [ +character-device+ ] }
236 { CHAR: d [ +directory+ ] }
237 { CHAR: l [ +symbolic-link+ ] }
238 { CHAR: s [ +socket+ ] }
239 { CHAR: p [ +fifo+ ] }
240 { CHAR: - [ +regular-file+ ] }
244 : file-type>ch ( type -- ch )
246 { +block-device+ [ CHAR: b ] }
247 { +character-device+ [ CHAR: c ] }
248 { +directory+ [ CHAR: d ] }
249 { +symbolic-link+ [ CHAR: l ] }
250 { +socket+ [ CHAR: s ] }
251 { +fifo+ [ CHAR: p ] }
252 { +regular-file+ [ CHAR: - ] }
258 : file-type>executable ( directory-entry -- string )
259 name>> any-execute? "*" "" ? ;
263 : file-type>trailing ( directory-entry -- string )
266 { +directory+ [ drop "/" ] }
267 { +symbolic-link+ [ drop "@" ] }
268 { +fifo+ [ drop "|" ] }
269 { +socket+ [ drop "=" ] }
270 { +whiteout+ [ drop "%" ] }
271 { +unknown+ [ file-type>executable ] }
272 { +regular-file+ [ file-type>executable ] }
273 [ drop file-type>executable ]