-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathKOS.FileDir.Mod.txt
161 lines (143 loc) · 5.31 KB
/
KOS.FileDir.Mod.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
MODULE FileDir; (*NW 12.1.86 / 23.8.90 / 15.8.2013*)
IMPORT SYSTEM, Kernel;
CONST FnLength* = 32;
SecTabSize* = 64;
ExTabSize* = 12;
SectorSize* = 1024;
IndexSize* = SectorSize DIV 4;
HeaderSize* = 352;
DirRootAdr* = 29;
DirPgSize* = 24;
DirMark* = 9B1EA38DH;
HeaderMark* = 9BA71D86H;
FillerSize = 52;
TYPE DiskAdr = INTEGER;
FileName* = ARRAY FnLength OF CHAR;
SectorTable* = ARRAY SecTabSize OF DiskAdr;
ExtensionTable* = ARRAY ExTabSize OF DiskAdr;
EntryHandler* = PROCEDURE (name: FileName; sec: DiskAdr; VAR continue: BOOLEAN);
FileHeader* =
RECORD (*first page of each file on disk*)
mark*: INTEGER;
name*: FileName;
aleng*, bleng*, date*: INTEGER;
ext*: ExtensionTable;
sec*: SectorTable;
fill: ARRAY SectorSize - HeaderSize OF BYTE;
END ;
FileHd* = POINTER TO FileHeader;
IndexSector* = ARRAY IndexSize OF DiskAdr;
DataSector* = ARRAY SectorSize OF BYTE;
DirEntry* = (*B-tree node*)
RECORD
name*: FileName;
adr*: DiskAdr; (*sec no of file header*)
p*: DiskAdr (*sec no of descendant in directory*)
END ;
DirPage* =
RECORD mark*: INTEGER;
m*: INTEGER;
p0*: DiskAdr; (*sec no of left descendant in directory*)
fill: ARRAY FillerSize OF BYTE;
e*: ARRAY DirPgSize OF DirEntry
END ;
FilePar =
RECORD
fn, offset, flags, size, data, enc, path: INTEGER
END ;
FileAttr =
RECORD
attr: SET;
enc: INTEGER;
ctime, cdate, atime, adate, mtime, mdate: ARRAY 4 OF BYTE;
loSize, hiSize: INTEGER;
(*name: ARRAY 520 OF CHAR*)
END ;
VAR
FileCall: PROCEDURE (f: FilePar; VAR count: INTEGER): INTEGER;
fdir: RECORD
version: INTEGER;
nofBlocks: INTEGER;
nofFiles: INTEGER;
pad: ARRAY 20 OF BYTE;
attr: SET;
enc: INTEGER;
ctime, cdate, atime, adate, mtime, mdate: ARRAY 4 OF BYTE;
loSize, hiSize: INTEGER;
name: ARRAY 520 OF CHAR
END;
PROCEDURE Check(s: ARRAY OF CHAR): INTEGER;
VAR i, res: INTEGER; ch: CHAR;
BEGIN ch := s[0]; i := 0;
IF (ch >= "A") & (ch <= "Z") OR (ch >= "a") & (ch <= "z") THEN
REPEAT INC(i); ch := s[i]
UNTIL ~((ch >= "0") & (ch <= "9") OR (ch >= "A") & (ch <= "Z")
OR (ch >= "a") & (ch <= "z") OR (ch = ".")) OR (i = FnLength);
IF i = FnLength THEN res := 4
ELSIF ch = 0X THEN res := 0;
WHILE i < FnLength DO INC(i) END
ELSE res := 5
END
ELSIF ch = 0X THEN res := -1
ELSE res := 3
END;
RETURN res
END Check;
(*Exported procedures: Search, Insert, Delete, Enumerate, Init*)
PROCEDURE Search*(name: FileName; VAR A: DiskAdr);
VAR res, count: INTEGER; par: FilePar; info: FileAttr;
BEGIN A := 0;
IF Check(name) = 0 THEN
par.fn := 5; par.offset := 0; par.flags := 0; par.size := 0; par.data := SYSTEM.ADR(info);
par.enc := 3; par.path := SYSTEM.ADR(name);
res := FileCall(par, count);
IF (res = 0) & (info.attr * {3, 4} = {}) & (info.hiSize = 0) & (info.loSize >= 0) THEN A := -1 END
END
END Search;
PROCEDURE Insert*(name: FileName; fad: DiskAdr);
BEGIN ASSERT(FALSE)
END Insert;
PROCEDURE Delete*(name: FileName; VAR fad: DiskAdr);
VAR res, count: INTEGER; par: FilePar;
BEGIN fad := 0;
IF Check(name) = 0 THEN
par.fn := 8; par.offset := 0; par.flags := 0; par.size := 0; par.data := 0;
par.enc := 3; par.path := SYSTEM.ADR(name);
res := FileCall(par, count);
IF res = 0 THEN fad := -1 END
END
END Delete;
PROCEDURE Enumerate*(prefix: ARRAY OF CHAR; proc: EntryHandler);
VAR par: FilePar; i, j, k, max, count, res: INTEGER; ch, pfx: CHAR; name: FileName; continue: BOOLEAN;
BEGIN
IF Check(prefix) <= 0 THEN
i := 0; max := 1; res := 0; continue := TRUE;
WHILE continue & (i < max) DO (*bug: possible race condition*)
par.fn := 1; par.offset := i; par.flags := 3; par.size := 1; par.data := SYSTEM.ADR(fdir);
par.enc := 3; par.path := SYSTEM.ADR("");
res := FileCall(par, count);
IF (res = 0) OR (res = 6) THEN
max := fdir.nofFiles;
IF (count > 0) & (fdir.attr * {1, 3, 4} = {}) & (fdir.hiSize = 0) & (fdir.loSize >= 0) THEN (*not hidden, not label, not folder*)
j := 0;
REPEAT ch := fdir.name[j]; pfx := prefix[j]; name[j] := ch; INC(j)
UNTIL (ch # pfx) OR (ch = 0X) OR (j >= FnLength);
IF (pfx = 0X) & ((ch = 0X) OR (j < FnLength)) THEN
WHILE (ch # 0X) & (j < FnLength) DO ch := fdir.name[j]; name[j] := ch; INC(j) END;
IF (ch = 0X) & (Check(name) = 0) THEN
proc(name, -1, continue)
END
END;
INC(i)
END
ELSE continue := FALSE; ASSERT(FALSE)
END
END
END
END Enumerate;
(* ----- initialization ----- *)
PROCEDURE Init*;
BEGIN
SYSTEM.PUT(SYSTEM.ADR(FileCall), SYSTEM.ADR($55 89E5 B850000000 8B5D10 CD40 8B4D08 8919 5D C20C00 6690$));
END Init;
END FileDir.