3 external get_dev_block_size : unit -> int = "get_dev_block_size"
5 external read_block_ext : string -> int -> bool = "read_block_ext"
7 let sector_size = get_dev_block_size ()
9 exception Overflow of string
27 mutable r_sector : int;
28 mutable r_offset : int;
29 mutable r_length : int;
30 mutable f_rec : dir_rec;
35 let block_cache_rr = ref 0 (* round robin replacement strategy *)
36 let block_cache_i = Array.make 16 (-1)
37 let block_cache_s = Array.make 16 (String.create sector_size)
41 while (!i < 16 && block_cache_i.(!i) != n) do i := !i + 1 done;
42 if !i < 16 then block_cache_s.(!i)
44 let i = !block_cache_rr in
45 let ok = read_block_ext block_cache_s.(!block_cache_rr) n in
46 if (not ok) then failwith ("read_block "^(string_of_int n)^" failed") else ();
47 block_cache_i.(!block_cache_rr) <- n;
48 block_cache_rr := (!block_cache_rr + 1) mod 16;
54 let read_byte s i = int_of_char s.[i]
56 let read1 s i = read_byte s i
59 let ch1 = read_byte s i in
60 let ch2 = read_byte s (i+1) in
64 let ch1 = read_byte s i in
65 let ch2 = read_byte s (i+1) in
66 let ch3 = read_byte s (i+2) in
67 let ch4 = read_byte s (i+3) in
68 if ch4 land 128 <> 0 then begin
69 if ch4 land 64 = 0 then raise (Overflow "read4");
70 ch1 lor (ch2 lsl 8) lor (ch3 lsl 16) lor ((ch4 land 127) lsl 24)
72 if ch4 land 64 <> 0 then raise (Overflow "read4");
73 ch1 lor (ch2 lsl 8) lor (ch3 lsl 16) lor (ch4 lsl 24)
77 let r1 j = read1 s (i+j) in
78 let r4 j = read4 s (i+j) in
92 name = if strlen != 1 then String.sub s (i+33) strlen else if (r1 33) = 0 then "." else (assert ((r1 33)=1);"..")
95 (* searches pvd, returns sector number of root record *)
96 let read_primary_volume_descriptor () =
97 let rec read_vol_desc n =
98 let data = read_block n in
99 let t = read1 data 0 in
100 if (t = 255) then failwith "primary volume descriptor not found" else
101 if (t != 1) then read_vol_desc (n+1) else
103 if ((read2 data 128) != sector_size) then failwith "logical blocksize != 2048, not supported" else
104 let root = read_record data 156 in (* copy of directory root record *)
105 assert (root.size = 34);
110 (* (string, next index or -1) *)
112 let (j,k) = if String.contains_from s i '/'
113 then let j = String.index_from s i '/' in (j-i,j+1)
114 else (String.length s - i,-1) (* -1 : leaf, no more parts *)
115 in (String.sub s i j, k)
117 (* path: must start with '/'; returns None or Some rec *)
118 let path_to_record path =
119 if (path.[0] != '/') then begin eprintf "path_to_sector: path.[0] != '/'\n"; None end else
120 if String.length path = 1 then Some (read_record (read_block !root_sec) 0) (* opendir '/' *) else
123 let rec search sector path_index =
124 let (name,i) = next_name path path_index in
125 if String.length name = 0 then None else begin
126 data := read_block sector;
127 let r = read_record !data 0 in
128 (* iterates through dir record list at one level, step down via calling 'search' *)
129 let rec scan sector index length =
130 if (read1 !data index = 0) then (* no more records in this sector *)
131 if (length < sector_size) then begin (* no more records at all *)
132 eprintf "path_to_sector: end of record list, but file '%s' not found\n" name; None
133 end else begin (* read next sector, continue search *)
134 let next_sector = sector + 1 in
135 data := read_block next_sector;
136 scan next_sector 0 (length-sector_size)
139 let r = read_record !data index in
140 if String.compare name r.name = 0 then
141 if i = -1 then Some r else search r.sector i
143 scan sector (index + r.size) length
147 if (r.flags land 2 == 0) then None else scan sector 0 r.length
152 let lookup_file path =
153 match path_to_record path with
155 | Some r -> (r.sector,r.length)
158 match path_to_record path with
161 let data = read_block r.sector in
162 let f_r = read_record data 0 in
163 Some { r_sector = r.sector; r_offset = 0; r_length = r.length; f_rec = f_r }
166 let data = read_block r.r_sector in
167 r.r_offset <- r.r_offset + r.f_rec.size;
168 if (read1 data r.r_offset = 0) then begin
169 if (r.r_length = sector_size) then false else begin
170 r.r_sector <- r.r_sector + 1;
172 r.r_length <- r.r_length - sector_size;
173 r.f_rec <- read_record (read_block r.r_sector) 0;
177 r.f_rec <- read_record data r.r_offset;
182 root_sec := read_primary_volume_descriptor ();
184 Callback.register "lookup_file" lookup_file;
185 Callback.register "opendir" opendir;
186 Callback.register "readdir" readdir