/[eiffelstudio]/FreeELKS/trunk/library/kernel/directory.e
ViewVC logotype

Contents of /FreeELKS/trunk/library/kernel/directory.e

Parent Directory Parent Directory | Revision Log Revision Log


Revision 91424 - (show annotations)
Tue Oct 26 18:39:32 2004 UTC (15 years, 2 months ago) by manus_eiffel
File size: 12940 byte(s)
Initial revision

1 indexing
2
3 description:
4 "Directories, in the Unix sense, with creation and exploration features"
5 status: "See notice at end of class"
6 date: "$Date$"
7 revision: "$Revision$"
8
9 class DIRECTORY
10
11 inherit
12 DISPOSABLE
13 export
14 {DIRECTORY} all
15 end
16
17 create
18 make, make_open_read
19
20 feature -- Initialization
21
22 make (dn: STRING) is
23 -- Create directory object for the directory
24 -- of name `dn'.
25 require
26 string_exists: dn /= Void
27 do
28 name := dn
29 mode := Close_directory
30 end
31
32 make_open_read (dn: STRING) is
33 -- Create directory object for the directory
34 -- of name `dn' and open it for reading.
35 require
36 string_exists: dn /= Void
37 do
38 make (dn)
39 open_read
40 end
41
42 create_dir is
43 -- Create a physical directory.
44 require
45 physical_not_exists: not exists
46 local
47 external_name: ANY
48 do
49 external_name := name.to_c
50 file_mkdir ($external_name)
51 end
52
53 feature -- Access
54
55 readentry is
56 -- Read next directory entry
57 -- make result available in `lastentry'.
58 -- Make result void if all entries have been read.
59 require
60 is_opened: not is_closed
61 do
62 lastentry := dir_next (directory_pointer)
63 end
64
65 name: STRING
66 -- Directory name
67
68 has_entry (entry_name: STRING): BOOLEAN is
69 -- Has directory the entry `entry_name'?
70 -- The use of `dir_temp' is required not
71 -- to change the position in the current
72 -- directory entries list.
73 require
74 string_exists: entry_name /= Void
75 local
76 ext_entry_name: ANY
77 dir_temp: DIRECTORY
78 do
79 create dir_temp.make_open_read (name)
80 ext_entry_name := entry_name.to_c
81 Result := dir_temp.dir_search (dir_temp.directory_pointer,
82 $ext_entry_name) /= default_pointer
83 dir_temp.close
84 end
85
86 open_read is
87 -- Open directory `name' for reading.
88 local
89 external_name: ANY
90 do
91 external_name := name.to_c
92 directory_pointer := dir_open ($external_name)
93 mode := Read_directory
94 end
95
96 close is
97 -- Close directory.
98 require
99 is_open: not is_closed
100 do
101 dir_close (directory_pointer)
102 mode := Close_directory
103 end
104
105 start is
106 -- Go to first entry of directory.
107 require
108 is_opened: not is_closed
109 do
110 dir_rewind (directory_pointer)
111 end
112
113 change_name (new_name: STRING) is
114 -- Change file name to `new_name'
115 require
116 new_name_not_void: new_name /= Void
117 file_exists: exists
118 local
119 ext_old_name, ext_new_name: ANY
120 do
121 ext_old_name := name.to_c
122 ext_new_name := new_name.to_c
123 eif_dir_rename ($ext_old_name, $ext_new_name)
124 name := new_name
125 ensure
126 name_changed: name.is_equal (new_name)
127 end
128
129 feature -- Measurement
130
131 count: INTEGER is
132 -- Number of entries in directory.
133 require
134 directory_exists: exists
135 local
136 dir_temp: DIRECTORY
137 counter: INTEGER
138 do
139 create dir_temp.make_open_read (name)
140 from
141 dir_temp.start
142 dir_temp.readentry
143 until
144 dir_temp.lastentry = Void
145 loop
146 counter := counter + 1
147 dir_temp.readentry
148 end
149 Result := counter
150 dir_temp.close
151 end
152
153 feature -- Conversion
154
155 linear_representation: ARRAYED_LIST [STRING] is
156 -- The entries, in sequential format.
157 local
158 dir_temp: DIRECTORY
159 do
160 create dir_temp.make_open_read (name)
161 -- Arbitrary size for arrayed_list creation to avoid
162 -- querying `count' which traverses list of entries
163 -- in current directory as we do here, making current
164 -- less efficient if Current has a lot of entries.
165 create Result.make (16)
166 from
167 dir_temp.start
168 dir_temp.readentry
169 until
170 dir_temp.lastentry = Void
171 loop
172 Result.extend (dir_temp.lastentry)
173 dir_temp.readentry
174 end
175 dir_temp.close
176 end
177
178 feature -- Status report
179
180 lastentry: STRING
181 -- Last entry read by `readentry'
182
183 is_closed: BOOLEAN is
184 -- Is current directory closed?
185 do
186 Result := mode = Close_directory
187 end
188
189 is_empty: BOOLEAN is
190 -- Is directory empty?
191 require
192 directory_exists: exists
193 do
194 -- count = 2, since there are "." and ".." which
195 -- are symbolic representations but not effective directories.
196 Result := (count = 2)
197 end
198
199 empty: BOOLEAN is
200 -- Is directory empty?
201 obsolete
202 "Use `is_empty' instead"
203 do
204 Result := is_empty
205 end
206
207 exists: BOOLEAN is
208 -- Does the directory exist?
209 local
210 external_name: ANY
211 do
212 external_name := name.to_c
213 Result := eif_dir_exists ($external_name)
214 end
215
216 is_readable: BOOLEAN is
217 -- Is the directory readable?
218 require
219 directory_exists: exists
220 local
221 external_name: ANY
222 do
223 external_name := name.to_c
224 Result := eif_dir_is_readable ($external_name)
225 end
226
227 is_executable: BOOLEAN is
228 -- Is the directory executable?
229 require
230 directory_exists: exists
231 local
232 external_name: ANY
233 do
234 external_name := name.to_c
235 Result := eif_dir_is_executable ($external_name)
236 end
237
238 is_writable: BOOLEAN is
239 -- Is the directory writable?
240 require
241 directory_exists: exists
242 local
243 external_name: ANY
244 do
245 external_name := name.to_c
246 Result := eif_dir_is_writable ($external_name)
247 end
248
249 feature -- Removal
250
251 delete is
252 -- Delete directory if empty
253 require
254 directory_exists: exists
255 empty_directory: is_empty
256 local
257 external_name: ANY
258 do
259 external_name := name.to_c
260 eif_dir_delete ($external_name)
261 end
262
263 delete_content is
264 -- Delete all files located in current directory and its
265 -- subdirectories.
266 require
267 directory_exists: exists
268 local
269 l: LINEAR [STRING]
270 file_name: FILE_NAME
271 file: RAW_FILE
272 dir: DIRECTORY
273 do
274 l := linear_representation
275 from
276 l.start
277 until
278 l.after
279 loop
280 if
281 not l.item.is_equal (".") and
282 not l.item.is_equal ("..")
283 then
284 create file_name.make_from_string (name)
285 file_name.set_file_name (l.item)
286 create file.make (file_name)
287 if
288 file.exists and then
289 not file.is_symlink and then
290 file.is_directory
291 then
292 -- Start the recursion
293 create dir.make (file_name)
294 dir.recursive_delete
295 else
296 if file.exists and then file.is_writable then
297 file.delete
298 end
299 end
300 end
301 l.forth
302 end
303 end
304
305 recursive_delete is
306 -- Delete directory, its files and its subdirectories.
307 require
308 directory_exists: exists
309 do
310 delete_content
311 if is_empty then
312 delete
313 end
314 end
315
316 delete_content_with_action (
317 action: PROCEDURE [ANY, TUPLE]
318 is_cancel_requested: FUNCTION [ANY, TUPLE, BOOLEAN]
319 file_number: INTEGER)
320 is
321 -- Delete all files located in current directory and its
322 -- subdirectories.
323 --
324 -- `action' is called each time `file_number' files has
325 -- been deleted and before the function exits.
326 -- `action' may be set to Void if you don't need it.
327 --
328 -- Same for `is_cancel_requested'.
329 -- Make it return `True' to cancel the operation.
330 -- `is_cancel_requested' may be set to Void if you don't need it.
331 require
332 directory_exists: exists
333 valid_file_number: file_number > 0
334 local
335 l: LINEAR [STRING]
336 file_name: FILE_NAME
337 file: RAW_FILE
338 dir: DIRECTORY
339 file_count: INTEGER
340 deleted_files: ARRAYED_LIST [STRING]
341 deleted_files_tuple: TUPLE [ARRAYED_LIST [STRING]]
342 current_directory: STRING
343 parent_directory: STRING
344 requested_cancel: BOOLEAN
345 do
346 file_count := 1
347 create deleted_files.make (file_number)
348 create deleted_files_tuple
349
350 l := linear_representation
351 current_directory := "."
352 parent_directory := ".."
353 from
354 l.start
355 until
356 l.after or requested_cancel
357 loop
358 if
359 not l.item.is_equal (current_directory) and
360 not l.item.is_equal (parent_directory)
361 then
362 create file_name.make_from_string (name)
363 file_name.set_file_name (l.item)
364 create file.make (file_name)
365 if
366 file.exists and then
367 not file.is_symlink and then
368 file.is_directory
369 then
370 -- Start the recursion
371 create dir.make (file_name)
372 dir.recursive_delete_with_action (action, is_cancel_requested, file_number)
373 else
374 if file.exists and then file.is_writable then
375 file.delete
376 end
377 end
378 -- Add the name of the deleted file to our array
379 -- of deleted files.
380 deleted_files.extend (file_name)
381 file_count := file_count + 1
382
383 -- If `file_number' has been reached, call `action'.
384 if file_count > file_number then
385 if action /= Void then
386 deleted_files_tuple.put (deleted_files, 1)
387 action.call (deleted_files_tuple)
388 end
389 if is_cancel_requested /= Void then
390 requested_cancel := is_cancel_requested.item (Void)
391 end
392 deleted_files.wipe_out
393 file_count := 1
394 end
395 end
396 l.forth
397 end
398 -- If there is more than one deleted file and no
399 -- agent has been called, call one now.
400 if file_count > 1 then
401 if action /= Void then
402 deleted_files_tuple.put (deleted_files, 1)
403 action.call (deleted_files_tuple)
404 end
405 deleted_files.wipe_out
406 file_count := 1
407 end
408 end
409
410 recursive_delete_with_action (
411 action: PROCEDURE [ANY, TUPLE]
412 is_cancel_requested: FUNCTION [ANY, TUPLE, BOOLEAN]
413 file_number: INTEGER)
414 is
415 -- Delete directory, its files and its subdirectories.
416 --
417 -- `action' is called each time `file_number' files has
418 -- been deleted and before the function exits.
419 require
420 directory_exists: exists
421 local
422 deleted_files: ARRAYED_LIST [STRING]
423 do
424 delete_content_with_action (action, is_cancel_requested, file_number)
425 if (is_cancel_requested = Void) or else (not is_cancel_requested.item (Void)) then
426 delete
427
428 -- Call the agent with the name of the directory
429 if action /= Void then
430 create deleted_files.make (1)
431 deleted_files.extend (name)
432 action.call ([deleted_files])
433 end
434 end
435 end
436
437 dispose is
438 -- Ensure this medium is closed when garbage collected.
439 do
440 if not is_closed then
441 close
442 end
443 end
444
445 feature {DIRECTORY} -- Implementation
446
447 directory_pointer: POINTER
448 -- Directory pointer as required in C
449
450 dir_search (dir_ptr: POINTER; entry: POINTER): POINTER is
451 -- Return the `DIRENTRY' structure corresponding
452 -- to the name `entry' of directory `dir_ptr'.
453 external
454 "C signature (EIF_POINTER, char *): EIF_POINTER use %"eif_dir.h%""
455 end
456
457 feature {NONE} -- Implementation
458
459 mode: INTEGER
460 -- Status mode of the directory.
461 -- Possible values are the following:
462
463 Close_directory: INTEGER is unique
464
465 Read_directory: INTEGER is unique
466
467 file_mkdir (dir_name: POINTER) is
468 -- Make directory `dir_name'.
469 external
470 "C signature (char *) use %"eif_file.h%""
471 end
472
473 dir_open (dir_name: POINTER): POINTER is
474 -- Open the directory `dir_name'.
475 external
476 "C signature (char *): EIF_POINTER use %"eif_dir.h%""
477 end
478
479 dir_rewind (dir_ptr: POINTER) is
480 -- Rewind the directory `dir_ptr'.
481 external
482 "C use %"eif_dir.h%""
483 end
484
485 dir_close (dir_ptr: POINTER) is
486 -- Close the directory `dir_ptr'.
487 external
488 "C use %"eif_dir.h%""
489 end
490
491 dir_next (dir_ptr: POINTER): STRING is
492 -- Return the next entry for directory 'dir_ptr'.
493 external
494 "C use %"eif_dir.h%""
495 end
496
497 eif_dir_delete (dir_name: POINTER) is
498 -- Delete the directory `dir_name'.
499 external
500 "C signature (char *) use %"eif_dir.h%""
501 end
502
503 eif_dir_exists (dir_name: POINTER): BOOLEAN is
504 -- Does the directory `dir_name' exist?
505 external
506 "C signature (char *): EIF_BOOLEAN use %"eif_dir.h%""
507 end
508
509 eif_dir_is_readable (dir_name: POINTER): BOOLEAN is
510 -- Is `dir_name' readable?
511 external
512 "C signature (char *): EIF_BOOLEAN use %"eif_dir.h%""
513 end
514
515 eif_dir_is_executable (dir_name: POINTER): BOOLEAN is
516 -- Is `dir_name' executable?
517 external
518 "C signature (char *): EIF_BOOLEAN use %"eif_dir.h%""
519 end
520
521 eif_dir_is_writable (dir_name: POINTER): BOOLEAN is
522 -- Is `dir_name' writable?
523 external
524 "C signature (char *): EIF_BOOLEAN use %"eif_dir.h%""
525 end
526
527 eif_dir_rename (old_name, new_name: POINTER) is
528 -- Change directory name from `old_name' to `new_name'.
529 external
530 "C signature (char *, char *) use %"eif_file.h%""
531 alias
532 "file_rename"
533 end
534
535 indexing
536
537 library: "[
538 EiffelBase: Library of reusable components for Eiffel.
539 ]"
540
541 status: "[
542 Copyright 1986-2001 Interactive Software Engineering (ISE).
543 For ISE customers the original versions are an ISE product
544 covered by the ISE Eiffel license and support agreements.
545 ]"
546
547 license: "[
548 EiffelBase may now be used by anyone as FREE SOFTWARE to
549 develop any product, public-domain or commercial, without
550 payment to ISE, under the terms of the ISE Free Eiffel Library
551 License (IFELL) at http://eiffel.com/products/base/license.html.
552 ]"
553
554 source: "[
555 Interactive Software Engineering Inc.
556 ISE Building
557 360 Storke Road, Goleta, CA 93117 USA
558 Telephone 805-685-1006, Fax 805-685-6869
559 Electronic mail <info@eiffel.com>
560 Customer support http://support.eiffel.com
561 ]"
562
563 info: "[
564 For latest info see award-winning pages: http://eiffel.com
565 ]"
566
567 end -- class DIRECTORY
568
569
570

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.23