]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/m2/gm2-libs-log/FileSystem.mod
Update copyright years.
[thirdparty/gcc.git] / gcc / m2 / gm2-libs-log / FileSystem.mod
1 (* FileSystem.mod provides a PIM [234] FileSystem module.
2
3 Copyright (C) 2004-2024 Free Software Foundation, Inc.
4 Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
5
6 This file is part of GNU Modula-2.
7
8 GNU Modula-2 is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
13 GNU Modula-2 is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
21
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. *)
26
27 IMPLEMENTATION MODULE FileSystem ;
28
29 FROM M2RTS IMPORT InstallTerminationProcedure ;
30 FROM Storage IMPORT ALLOCATE ;
31 FROM SYSTEM IMPORT ADR ;
32 IMPORT SFIO, libc, wrapc ;
33 FROM DynamicStrings IMPORT InitString, ConCat, ConCatChar, KillString, string ;
34 FROM FormatStrings IMPORT Sprintf2 ;
35
36 CONST
37 TMPDIR = '/tmp' ;
38 DIRSEP = '/' ;
39 SEEK_SET = 0 ; (* seek relative to from beginning of the file *)
40
41 TYPE
42 FileList = POINTER TO RECORD
43 next : FileList ;
44 n : String ;
45 stillTemp: BOOLEAN ;
46 END ;
47
48 VAR
49 HeadOfTemp: FileList ;
50 tempNo : CARDINAL ;
51
52
53 (*
54 Create - creates a temporary file. To make the file perminant
55 the file must be renamed.
56 *)
57
58 PROCEDURE Create (VAR f: File) ;
59 BEGIN
60 WITH f DO
61 flags := FlagSet{write, temporary} ;
62 eof := FALSE ;
63 lastWord := WORD(0) ;
64 lastByte := CHAR(0) ;
65 name := MakeTemporary() ;
66 fio := SFIO.OpenToWrite(name) ;
67 IF FIO.IsNoError(fio)
68 THEN
69 res := done
70 ELSE
71 res := notdone
72 END ;
73 highpos := 0 ;
74 lowpos := 0
75 END
76 END Create ;
77
78
79 (*
80 Close - closes an open file.
81 *)
82
83 PROCEDURE Close (f: File) ;
84 BEGIN
85 WITH f DO
86 eof := TRUE ;
87 FIO.Close(fio) ;
88 IF FIO.IsNoError(fio)
89 THEN
90 res := done
91 ELSE
92 res := notdone
93 END ;
94 IF temporary IN flags
95 THEN
96 deleteFile(name, f)
97 END ;
98 name := KillString(name)
99 END
100 END Close ;
101
102
103 (*
104 Lookup - looks for a file, filename. If the file is found
105 then, f, is opened. If it is not found and, newFile,
106 is TRUE then a new file is created and attached to, f.
107 If, newFile, is FALSE and no file was found then f.res
108 is set to notdone.
109 *)
110
111 PROCEDURE Lookup (VAR f: File; filename: ARRAY OF CHAR; newFile: BOOLEAN) ;
112 BEGIN
113 WITH f DO
114 flags := FlagSet{} ;
115 IF FIO.Exists(filename)
116 THEN
117 fio := FIO.OpenToRead(filename) ;
118 INCL(flags, read) ;
119 res := done
120 ELSIF newFile
121 THEN
122 fio := FIO.OpenToWrite(filename) ;
123 INCL(flags, write) ;
124 res := done
125 ELSE
126 res := notdone
127 END ;
128 name := InitString(filename) ;
129 eof := FALSE ;
130 highpos := 0 ;
131 lowpos := 0
132 END
133 END Lookup ;
134
135
136 (*
137 Rename - rename a file and change a temporary file to a permanent
138 file. f.res is set appropriately.
139 *)
140
141 PROCEDURE Rename (VAR f: File; newname: ARRAY OF CHAR) ;
142 VAR
143 s: String ;
144 r: INTEGER ;
145 BEGIN
146 s := InitString(newname) ;
147 WITH f DO
148 r := libc.rename(string(name), string(s)) ;
149 IF r=0
150 THEN
151 res := done
152 ELSE
153 res := notdone
154 END ;
155 EXCL(flags, temporary) ;
156 name := KillString(name) ;
157 name := s
158 END
159 END Rename ;
160
161
162 (*
163 deleteFile - deletes file, name. It also kills the string, name.
164 *)
165
166 PROCEDURE deleteFile (VAR name: String; VAR f: File) ;
167 VAR
168 r: INTEGER ;
169 BEGIN
170 r := libc.unlink(string(name)) ;
171 IF r=0
172 THEN
173 f.res := done
174 ELSE
175 f.res := notdone
176 END ;
177 name := KillString(name) ;
178 name := NIL
179 END deleteFile ;
180
181
182 (*
183 Delete - deletes a file, name, and sets the f.res field.
184 f.res is set appropriately.
185 *)
186
187 PROCEDURE Delete (name: ARRAY OF CHAR; VAR f: File) ;
188 VAR
189 s: String ;
190 BEGIN
191 s := InitString(name) ;
192 deleteFile(s, f) ;
193 s := KillString(s)
194 END Delete ;
195
196
197 (*
198 ReadWord - reads a WORD, w, from file, f.
199 f.res is set appropriately.
200 *)
201
202 PROCEDURE ReadWord (VAR f: File; VAR w: WORD) ;
203 VAR
204 n: CARDINAL ;
205 BEGIN
206 WITH f DO
207 IF again IN flags
208 THEN
209 w := lastWord ;
210 EXCL(flags, again)
211 ELSE
212 ReadNBytes(f, ADR(w), SIZE(w), n) ;
213 IF n=SIZE(w)
214 THEN
215 res := done
216 ELSE
217 res := notdone ;
218 eof := TRUE
219 END
220 END
221 END
222 END ReadWord ;
223
224
225 (*
226 WriteWord - writes one word to a file, f.
227 f.res is set appropriately.
228 *)
229
230 PROCEDURE WriteWord (VAR f: File; w: WORD) ;
231 VAR
232 n: CARDINAL ;
233 BEGIN
234 WriteNBytes(f, ADR(w), SIZE(w), n) ;
235 WITH f DO
236 IF n=SIZE(w)
237 THEN
238 res := done
239 ELSE
240 res := notdone
241 END
242 END
243 END WriteWord ;
244
245
246 (*
247 ReadChar - reads one character from a file, f.
248 *)
249
250 PROCEDURE ReadChar (VAR f: File; VAR ch: CHAR) ;
251 VAR
252 n: CARDINAL ;
253 BEGIN
254 WITH f DO
255 IF again IN flags
256 THEN
257 ch := CHAR(lastByte) ;
258 EXCL(flags, again)
259 ELSE
260 ReadNBytes(f, ADR(ch), SIZE(ch), n) ;
261 IF n=SIZE(ch)
262 THEN
263 res := done ;
264 lastByte := BYTE(ch)
265 ELSE
266 res := notdone ;
267 eof := TRUE
268 END
269 END
270 END
271 END ReadChar ;
272
273
274 (*
275 WriteChar - writes a character, ch, to a file, f.
276 f.res is set appropriately.
277 *)
278
279 PROCEDURE WriteChar (VAR f: File; ch: CHAR) ;
280 VAR
281 n: CARDINAL ;
282 BEGIN
283 WriteNBytes(f, ADR(ch), SIZE(ch), n) ;
284 WITH f DO
285 IF n=SIZE(ch)
286 THEN
287 res := done
288 ELSE
289 res := notdone
290 END
291 END
292 END WriteChar ;
293
294
295 (*
296 ReadByte - reads a BYTE, b, from file, f.
297 f.res is set appropriately.
298 *)
299
300 PROCEDURE ReadByte (VAR f: File; VAR b: BYTE) ;
301 VAR
302 n: CARDINAL ;
303 BEGIN
304 WITH f DO
305 IF again IN flags
306 THEN
307 b := lastByte ;
308 EXCL(flags, again)
309 ELSE
310 ReadNBytes(f, ADR(b), SIZE(b), n) ;
311 IF n=SIZE(b)
312 THEN
313 res := done ;
314 lastByte := b
315 ELSE
316 res := notdone ;
317 eof := TRUE
318 END
319 END
320 END
321 END ReadByte ;
322
323
324 (*
325 WriteByte - writes one BYTE, b, to a file, f.
326 f.res is set appropriately.
327 *)
328
329 PROCEDURE WriteByte (VAR f: File; b: BYTE) ;
330 VAR
331 n: CARDINAL ;
332 BEGIN
333 WriteNBytes(f, ADR(b), SIZE(b), n) ;
334 WITH f DO
335 IF n=SIZE(b)
336 THEN
337 res := done
338 ELSE
339 res := notdone
340 END
341 END
342 END WriteByte ;
343
344
345 (*
346 ReadNBytes - reads a sequence of bytes from a file, f.
347 *)
348
349 PROCEDURE ReadNBytes (VAR f: File; a: ADDRESS; amount: CARDINAL;
350 VAR actuallyRead: CARDINAL) ;
351 BEGIN
352 WITH f DO
353 IF amount>0
354 THEN
355 actuallyRead := FIO.ReadNBytes(fio, amount, a) ;
356 IF FIO.IsNoError(fio)
357 THEN
358 res := done ;
359 IF MAX(CARDINAL)-lowpos<actuallyRead
360 THEN
361 INC(highpos)
362 END ;
363 INC(lowpos, actuallyRead)
364 ELSE
365 res := notdone ;
366 eof := TRUE
367 END
368 END
369 END
370 END ReadNBytes ;
371
372
373 (*
374 WriteNBytes - writes a sequence of bytes to file, f.
375 *)
376
377 PROCEDURE WriteNBytes (VAR f: File; a: ADDRESS; amount: CARDINAL;
378 VAR actuallyWritten: CARDINAL) ;
379 BEGIN
380 actuallyWritten := 0 ;
381 WITH f DO
382 IF amount>0
383 THEN
384 actuallyWritten := FIO.WriteNBytes(fio, amount, a) ;
385 IF FIO.IsNoError(fio)
386 THEN
387 res := done ;
388 IF MAX(CARDINAL)-lowpos<actuallyWritten
389 THEN
390 INC(highpos)
391 END ;
392 INC(lowpos, actuallyWritten)
393 ELSE
394 res := notdone
395 END
396 END
397 END
398 END WriteNBytes ;
399
400
401 (*
402 Again - returns the last character read to the internal buffer
403 so that it can be read again.
404 *)
405
406 PROCEDURE Again (VAR f: File) ;
407 BEGIN
408 INCL(f.flags, again)
409 END Again ;
410
411
412 (*
413 doModeChange -
414 *)
415
416 PROCEDURE doModeChange (VAR f: File; mode: Flag) ;
417 VAR
418 r: INTEGER ;
419 BEGIN
420 WITH f DO
421 IF NOT (mode IN flags)
422 THEN
423 INCL(flags, mode) ;
424 IF mode=read
425 THEN
426 EXCL(flags, write)
427 ELSIF mode=write
428 THEN
429 EXCL(flags, read)
430 END ;
431 IF opened IN flags
432 THEN
433 FIO.Close(fio)
434 END ;
435 IF read IN flags
436 THEN
437 fio := SFIO.OpenToRead(name)
438 ELSIF write IN flags
439 THEN
440 fio := SFIO.OpenToWrite(name)
441 END ;
442 INCL (flags, opened) ;
443 r := libc.lseek (fio,
444 VAL (LONGINT, lowpos) + VAL (LONGINT, highpos) * VAL (LONGINT, MAX (CARDINAL)),
445 SEEK_SET)
446 END
447 END
448 END doModeChange ;
449
450
451 (*
452 SetRead - puts the file, f, into the read state.
453 The file position is unchanged.
454 *)
455
456 PROCEDURE SetRead (VAR f: File) ;
457 BEGIN
458 doModeChange(f, read)
459 END SetRead ;
460
461
462 (*
463 SetWrite - puts the file, f, into the write state.
464 The file position is unchanged.
465 *)
466
467 PROCEDURE SetWrite (VAR f: File) ;
468 BEGIN
469 doModeChange(f, write)
470 END SetWrite ;
471
472
473 (*
474 SetModify - puts the file, f, into the modify state.
475 The file position is unchanged but the file can be
476 read and written.
477 *)
478
479 PROCEDURE SetModify (VAR f: File) ;
480 BEGIN
481 doModeChange(f, modify)
482 END SetModify ;
483
484
485 (*
486 SetOpen - places a file, f, into the open state. The file may
487 have been in the read/write/modify state before and
488 in which case the previous buffer contents are flushed
489 and the file state is reset to open. The position is
490 unaltered.
491 *)
492
493 PROCEDURE SetOpen (VAR f: File) ;
494 BEGIN
495 doModeChange(f, opened)
496 END SetOpen ;
497
498
499 (*
500 Reset - places a file, f, into the open state and reset the
501 position to the start of the file.
502 *)
503
504 PROCEDURE Reset (VAR f: File) ;
505 BEGIN
506 SetOpen(f) ;
507 SetPos(f, 0, 0)
508 END Reset ;
509
510
511 (*
512 SetPos - lseek to a position within a file.
513 *)
514
515 PROCEDURE SetPos (VAR f: File; high, low: CARDINAL) ;
516 VAR
517 r: INTEGER ;
518 BEGIN
519 WITH f DO
520 r := libc.lseek(fio, VAL(LONGCARD, low) +
521 (VAL(LONGCARD, MAX(CARDINAL)) * VAL(LONGCARD, high)),
522 SEEK_SET) ;
523 highpos := high ;
524 lowpos := low ;
525 END
526 END SetPos ;
527
528
529 (*
530 GetPos - return the position within a file.
531 *)
532
533 PROCEDURE GetPos (VAR f: File; VAR high, low: CARDINAL) ;
534 BEGIN
535 WITH f DO
536 high := highpos ;
537 low := lowpos
538 END
539 END GetPos ;
540
541
542 (*
543 Length - returns the length of file, in, high, and, low.
544 *)
545
546 PROCEDURE Length (VAR f: File; VAR high, low: CARDINAL) ;
547 VAR
548 i: INTEGER ;
549 BEGIN
550 WITH f DO
551 i := wrapc.filesize(FIO.GetUnixFileDescriptor(fio), high, low)
552 END
553 END Length ;
554
555
556 (*
557 Doio - effectively flushes a file in write mode, rereads the
558 current buffer from disk if in read mode and writes
559 and rereads the buffer if in modify mode.
560 *)
561
562 PROCEDURE Doio (VAR f: File) ;
563 BEGIN
564 WITH f DO
565 IF opened IN flags
566 THEN
567 FIO.Close(fio) ;
568 EXCL(flags, opened)
569 END ;
570 IF read IN flags
571 THEN
572 fio := SFIO.OpenToRead(name) ;
573 INCL(flags, opened) ;
574 SetPos(f, lowpos, highpos)
575 ELSIF write IN flags
576 THEN
577 fio := SFIO.OpenToWrite(name) ;
578 INCL(flags, opened) ;
579 SetPos(f, lowpos, highpos)
580 END
581 END
582 END Doio ;
583
584
585 (*
586 FileNameChar - checks to see whether the character, ch, is
587 legal in a filename. nul is returned if the
588 character was illegal.
589 *)
590
591 PROCEDURE FileNameChar (ch: CHAR) : CHAR ;
592 BEGIN
593 RETURN ch
594 END FileNameChar ;
595
596
597 (*
598 MakeTemporary - creates a temporary file and returns its name.
599 *)
600
601 PROCEDURE MakeTemporary () : String ;
602 VAR
603 p: FileList ;
604 i: INTEGER ;
605 BEGIN
606 NEW(p) ;
607 INC(tempNo) ;
608 i := libc.getpid() ;
609 WITH p^ DO
610 next := HeadOfTemp ;
611 n := Sprintf2(InitString('fs-%d-%d'), i, tempNo) ;
612 n := ConCat(ConCatChar(InitString(TMPDIR), DIRSEP), n) ;
613 RETURN n
614 END
615 END MakeTemporary ;
616
617
618 (*
619 CleanUp - deletes all temporary files.
620 *)
621
622 PROCEDURE CleanUp ;
623 VAR
624 p: FileList ;
625 r: INTEGER ;
626 BEGIN
627 p := HeadOfTemp ;
628 WHILE p#NIL DO
629 WITH p^ DO
630 IF stillTemp
631 THEN
632 stillTemp := FALSE ;
633 r := libc.unlink(string(n))
634 END
635 END ;
636 p := p^.next
637 END
638 END CleanUp ;
639
640
641 (*
642 Init - installs the termination procedure to tidy up any temporary files.
643 *)
644
645 PROCEDURE Init ;
646 BEGIN
647 tempNo := 0 ;
648 HeadOfTemp := NIL ;
649 IF NOT InstallTerminationProcedure(CleanUp)
650 THEN
651 HALT
652 END
653 END Init ;
654
655
656 BEGIN
657 Init
658 END FileSystem.