-
Notifications
You must be signed in to change notification settings - Fork 0
/
LINUX386.FileDir.Mod.txt
147 lines (131 loc) · 4.99 KB
/
LINUX386.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
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 ;
VAR fd: INTEGER;
syscall2: PROCEDURE (eax, ebx: INTEGER): INTEGER;
syscall3: PROCEDURE (eax, ebx, ecx: INTEGER): INTEGER;
syscall4: PROCEDURE (eax, ebx, ecx, edx: INTEGER): INTEGER;
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: INTEGER;
BEGIN A := 0;
IF Check(name) = 0 THEN (* access(name, R_OK|W_OK) *)
REPEAT res := syscall3(33, SYSTEM.ADR(name), 6) UNTIL res # -4;
IF res = 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: INTEGER;
BEGIN fad := 0;
IF Check(name) = 0 THEN
REPEAT res := syscall2(10, SYSTEM.ADR(name)) UNTIL res # -4; (*unlink*)
IF res = 0 THEN fad := -1 END
END
END Delete;
PROCEDURE Enumerate*(prefix: ARRAY OF CHAR; proc: EntryHandler);
CONST MaxEnt = 1024;
VAR res, i, j: INTEGER; pfx, nmx: CHAR;
buf: ARRAY MaxEnt OF CHAR;
continue: BOOLEAN;
name: FileName;
BEGIN
IF fd > 0 THEN (*close*)
REPEAT res := syscall2(6, fd) UNTIL res # -4;
fd := -1
END;
IF Check(prefix) <= 0 THEN (* open(".", O_DIRECTORY | O_RDONLY, 0) *)
REPEAT fd := syscall4(5, SYSTEM.ADR("."), 10000H, 0) UNTIL fd # -4;
IF fd >= 0 THEN
continue := TRUE;
REPEAT
REPEAT res := syscall4(220, fd, SYSTEM.ADR(buf), MaxEnt) UNTIL res # -4; (*getdents64*)
IF res > 0 THEN (*ok*)
j := 0;
REPEAT
IF buf[j+18] = 8X THEN (*regular file*)
i := 0;
REPEAT nmx := buf[j+i+19]; name[i] := nmx; pfx := prefix[i]; INC(i)
UNTIL (pfx # nmx) OR (nmx = 0X) OR (i >= FnLength);
IF (pfx = 0X) & ((nmx = 0X) OR (i < FnLength)) THEN (*match prefix, fit into buffer*)
WHILE (nmx # 0X) & (i < FnLength) DO nmx := buf[j+i+19]; name[i] := nmx; INC(i) END;
IF (nmx = 0X) & (Check(name) = 0) THEN (*name copied and valid*)
proc(name, -1, continue)
END
END
END;
INC(j, ORD(buf[j+17])*100H + ORD(buf[j+16]))
UNTIL j >= res
END
UNTIL ~continue OR (res <= 0);
REPEAT res := syscall2(6, fd) UNTIL res # -4; fd := -1 (*close*)
END
END
END Enumerate;
(* ----- initialization ----- *)
PROCEDURE Init*;
BEGIN fd := -1;
SYSTEM.PUT(SYSTEM.ADR(syscall2), SYSTEM.ADR($8B442408 8B5C2404 CD80 C20800 6690 90$));
SYSTEM.PUT(SYSTEM.ADR(syscall3), SYSTEM.ADR($8B44240C 8B5C2408 8B4C2404 CD80 C20C00 6690 90$));
SYSTEM.PUT(SYSTEM.ADR(syscall4), SYSTEM.ADR($8B442410 8B5C240C 8B4C2408 8B542404 CD80 C21000 6690 90$));
END Init;
END FileDir.