]> gitweb.factorcode.org Git - factor.git/blob - basis/io/files/info/unix/unix.factor
Specialized array overhaul
[factor.git] / basis / io / files / info / unix / unix.factor
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 io.directories unix unix.stat
7 unix.time unix.users unix.groups classes.struct
8 specialized-arrays ;
9 SPECIALIZED-ARRAY: timeval
10 IN: io.files.info.unix
11
12 TUPLE: unix-file-system-info < file-system-info
13 block-size preferred-block-size
14 blocks blocks-free blocks-available
15 files files-free files-available
16 name-max flags id ;
17
18 HOOK: new-file-system-info os ( --  file-system-info )
19
20 M: unix new-file-system-info ( -- ) unix-file-system-info new ;
21
22 HOOK: file-system-statfs os ( path -- statfs )
23
24 M: unix file-system-statfs drop f ;
25
26 HOOK: file-system-statvfs os ( path -- statvfs )
27
28 M: unix file-system-statvfs drop f ;
29
30 HOOK: statfs>file-system-info os ( file-system-info statfs -- file-system-info' )
31
32 M: unix statfs>file-system-info drop ;
33
34 HOOK: statvfs>file-system-info os ( file-system-info statvfs -- file-system-info' )
35
36 M: unix statvfs>file-system-info drop ;
37
38 : file-system-calculations ( file-system-info -- file-system-info' )
39     dup [ blocks-available>> ] [ block-size>> ] bi * >>available-space
40     dup [ blocks-free>> ] [ block-size>> ] bi * >>free-space
41     dup [ blocks>> ] [ block-size>> ] bi * >>total-space
42     dup [ total-space>> ] [ free-space>> ] bi - >>used-space ;
43
44 M: unix file-system-info
45     normalize-path
46     [ new-file-system-info ] dip
47     [ file-system-statfs statfs>file-system-info ]
48     [ file-system-statvfs statvfs>file-system-info ] bi
49     file-system-calculations ;
50
51 TUPLE: unix-file-info < file-info uid gid dev ino
52 nlink rdev blocks blocksize ;
53
54 HOOK: new-file-info os ( -- file-info )
55
56 HOOK: stat>file-info os ( stat -- file-info )
57
58 HOOK: stat>type os ( stat -- file-info )
59
60 M: unix file-info ( path -- info )
61     normalize-path file-status stat>file-info ;
62
63 M: unix link-info ( path -- info )
64     normalize-path link-status stat>file-info ;
65
66 M: unix new-file-info ( -- class ) unix-file-info new ;
67
68 CONSTANT: standard-unix-block-size 512
69
70 M: unix stat>file-info ( stat -- file-info )
71     [ new-file-info ] dip
72     {
73         [ stat>type >>type ]
74         [ st_size>> >>size ]
75         [ st_mode>> >>permissions ]
76         [ st_ctimespec>> timespec>unix-time >>created ]
77         [ st_mtimespec>> timespec>unix-time >>modified ]
78         [ st_atimespec>> timespec>unix-time >>accessed ]
79         [ st_uid>> >>uid ]
80         [ st_gid>> >>gid ]
81         [ st_dev>> >>dev ]
82         [ st_ino>> >>ino ]
83         [ st_nlink>> >>nlink ]
84         [ st_rdev>> >>rdev ]
85         [ st_blocks>> >>blocks ]
86         [ st_blksize>> >>blocksize ]
87         [ drop dup blocks>> standard-unix-block-size * >>size-on-disk ]
88     } cleave ;
89
90 : n>file-type ( n -- type )
91     S_IFMT bitand {
92         { S_IFREG [ +regular-file+ ] }
93         { S_IFDIR [ +directory+ ] }
94         { S_IFCHR [ +character-device+ ] }
95         { S_IFBLK [ +block-device+ ] }
96         { S_IFIFO [ +fifo+ ] }
97         { S_IFLNK [ +symbolic-link+ ] }
98         { S_IFSOCK [ +socket+ ] }
99         [ drop +unknown+ ]
100     } case ;
101
102 M: unix stat>type ( stat -- type )
103     st_mode>> n>file-type ;
104
105 <PRIVATE
106
107 : stat-mode ( path -- mode )
108     normalize-path file-status st_mode>> ;
109
110 : chmod-set-bit ( path mask ? -- )
111     [ dup stat-mode ] 2dip
112     [ bitor ] [ unmask ] if chmod io-error ;
113
114 GENERIC# file-mode? 1 ( obj mask -- ? )
115
116 M: integer file-mode? mask? ;
117 M: string file-mode? [ stat-mode ] dip mask? ;
118 M: file-info file-mode? [ permissions>> ] dip mask? ;
119
120 PRIVATE>
121
122 CONSTANT: UID           OCT: 0004000
123 CONSTANT: GID           OCT: 0002000
124 CONSTANT: STICKY        OCT: 0001000
125 CONSTANT: USER-ALL      OCT: 0000700
126 CONSTANT: USER-READ     OCT: 0000400
127 CONSTANT: USER-WRITE    OCT: 0000200
128 CONSTANT: USER-EXECUTE  OCT: 0000100
129 CONSTANT: GROUP-ALL     OCT: 0000070
130 CONSTANT: GROUP-READ    OCT: 0000040
131 CONSTANT: GROUP-WRITE   OCT: 0000020
132 CONSTANT: GROUP-EXECUTE OCT: 0000010
133 CONSTANT: OTHER-ALL     OCT: 0000007
134 CONSTANT: OTHER-READ    OCT: 0000004
135 CONSTANT: OTHER-WRITE   OCT: 0000002
136 CONSTANT: OTHER-EXECUTE OCT: 0000001
137
138 : uid? ( obj -- ? ) UID file-mode? ;
139 : gid? ( obj -- ? ) GID file-mode? ;
140 : sticky? ( obj -- ? ) STICKY file-mode? ;
141 : user-read? ( obj -- ? ) USER-READ file-mode? ;
142 : user-write? ( obj -- ? ) USER-WRITE file-mode? ;
143 : user-execute? ( obj -- ? ) USER-EXECUTE file-mode? ;
144 : group-read? ( obj -- ? ) GROUP-READ file-mode? ;
145 : group-write? ( obj -- ? ) GROUP-WRITE file-mode? ;
146 : group-execute? ( obj -- ? ) GROUP-EXECUTE file-mode? ;
147 : other-read? ( obj -- ? ) OTHER-READ file-mode? ;
148 : other-write? ( obj -- ? ) OTHER-WRITE file-mode? ;
149 : other-execute? ( obj -- ? ) OTHER-EXECUTE file-mode? ;
150
151 : any-read? ( obj -- ? )
152     { [ user-read? ] [ group-read? ] [ other-read? ] } 1|| ;
153
154 : any-write? ( obj -- ? )
155     { [ user-write? ] [ group-write? ] [ other-write? ] } 1|| ;
156
157 : any-execute? ( obj -- ? )
158     { [ user-execute? ] [ group-execute? ] [ other-execute? ] } 1|| ;
159
160 : set-uid ( path ? -- ) UID swap chmod-set-bit ;
161 : set-gid ( path ? -- ) GID swap chmod-set-bit ;
162 : set-sticky ( path ? -- ) STICKY swap chmod-set-bit ;
163 : set-user-read ( path ? -- ) USER-READ swap chmod-set-bit ;
164 : set-user-write ( path ? -- ) USER-WRITE swap chmod-set-bit ;
165 : set-user-execute ( path ? -- ) USER-EXECUTE swap chmod-set-bit ;
166 : set-group-read ( path ? -- ) GROUP-READ swap chmod-set-bit ;
167 : set-group-write ( path ? -- ) GROUP-WRITE swap chmod-set-bit ;
168 : set-group-execute ( path ? -- ) GROUP-EXECUTE swap chmod-set-bit ;
169 : set-other-read ( path ? -- ) OTHER-READ swap chmod-set-bit ;
170 : set-other-write ( path ? -- ) OTHER-WRITE swap chmod-set-bit ;
171 : set-other-execute ( path ? -- ) OTHER-EXECUTE swap chmod-set-bit ;
172
173 : set-file-permissions ( path n -- )
174     [ normalize-path ] dip chmod io-error ;
175
176 : file-permissions ( path -- n )
177     normalize-path file-info permissions>> ;
178
179 M: unix copy-file-and-info ( from to -- )
180     [ copy-file ] [ swap file-permissions set-file-permissions ] 2bi ;
181
182 <PRIVATE
183
184 : timestamp>timeval ( timestamp -- timeval )
185     unix-1970 time- duration>microseconds make-timeval ;
186
187 : timestamps>byte-array ( timestamps -- byte-array )
188     [ [ timestamp>timeval ] [ \ timeval <struct> ] if* ] map
189     >timeval-array ;
190
191 PRIVATE>
192
193 : set-file-times ( path timestamps -- )
194     #! set access, write
195     [ normalize-path ] dip
196     timestamps>byte-array utimes io-error ;
197
198 : set-file-access-time ( path timestamp -- )
199     f 2array set-file-times ;
200
201 : set-file-modified-time ( path timestamp -- )
202     f swap 2array set-file-times ;
203
204 : set-file-ids ( path uid gid -- )
205     [ normalize-path ] 2dip [ -1 or ] bi@ chown io-error ;
206
207 GENERIC: set-file-user ( path string/id -- )
208
209 GENERIC: set-file-group ( path string/id -- )
210
211 M: integer set-file-user ( path uid -- )
212     f set-file-ids ;
213
214 M: string set-file-user ( path string -- )
215     user-id f set-file-ids ;
216
217 M: integer set-file-group ( path gid -- )
218     f swap set-file-ids ;
219
220 M: string set-file-group ( path string -- )
221     group-id
222     f swap set-file-ids ;
223
224 : file-user-id ( path -- uid )
225     normalize-path file-info uid>> ;
226
227 : file-user-name ( path -- string )
228     file-user-id user-name ;
229
230 : file-group-id ( path -- gid )
231     normalize-path file-info gid>> ;
232
233 : file-group-name ( path -- string )
234     file-group-id group-name ;
235
236 : ch>file-type ( ch -- type )
237     {
238         { CHAR: b [ +block-device+ ] }
239         { CHAR: c [ +character-device+ ] }
240         { CHAR: d [ +directory+ ] }
241         { CHAR: l [ +symbolic-link+ ] }
242         { CHAR: s [ +socket+ ] }
243         { CHAR: p [ +fifo+ ] }
244         { CHAR: - [ +regular-file+ ] }
245         [ drop +unknown+ ]
246     } case ;
247
248 : file-type>ch ( type -- ch )
249     {
250         { +block-device+ [ CHAR: b ] }
251         { +character-device+ [ CHAR: c ] }
252         { +directory+ [ CHAR: d ] }
253         { +symbolic-link+ [ CHAR: l ] }
254         { +socket+ [ CHAR: s ] }
255         { +fifo+ [ CHAR: p ] }
256         { +regular-file+ [ CHAR: - ] }
257         [ drop CHAR: - ]
258     } case ;
259
260 <PRIVATE
261
262 : file-type>executable ( directory-entry -- string )
263     name>> any-execute? "*" "" ? ;
264
265 PRIVATE>
266
267 : file-type>trailing ( directory-entry -- string )
268     dup type>>
269     {
270         { +directory+ [ drop "/" ] }
271         { +symbolic-link+ [ drop "@" ] }
272         { +fifo+ [ drop "|" ] }
273         { +socket+ [ drop "=" ] }
274         { +whiteout+ [ drop "%" ] }
275         { +unknown+ [ file-type>executable ] }
276         { +regular-file+ [ file-type>executable ] }
277         [ drop file-type>executable ]
278     } case ;