! Filestore copier -- writer program ! Listens for commands from the reader (create user, create file, write data). ! If the incoming partition no. is invalid for the destination filestore ! (e.g. copying C -> A) the user is placed on the highest partition available. %include "SYSTEM:Config.Inc" %include "System:DisqIO.Inc" %include "Formats.Inc" %include "Utility.Inc" %include "Inc:Util.Imp" %include "Inc:FS.Imp" %constinteger port = 15 %constinteger mask = 1 << port ! Bad block list format (from System:FSys) %constinteger bad limit = 512 - 3 %recordformat bad fm((%integer stamp, %integerarray bad(1 : bad limit), %integer last bad, checksum) %c %or %integerarray x(1 : 512)) %ownrecord(bad fm) bad list = 0 %routine read bad list %integername x %integer i, c printstring("Get bad block list from ") write(sy2 start + bad area(1), 0) newline x == transfer(d read, 2048, (sy2 start + bad area(1)) << 9, integer(addr(bad list))) %cycle; %repeat %until x # 0 %if x # 2048 %start printstring("Failed to read bad block list") newline %stop %finish c = 0 c <- c + bad list_x(i) %for i = 1, 1, 512 %unless c = 0 %start printstring("Bad block list checksum error") newline %stop %finish %if bad list_last bad = 0 %start printstring("No bad blocks") newline %else printstring("Bad blocks:"); newline %for i = 1, 1, bad list_last bad %cycle write(bad list_bad(i), 8) newline %if i & 7 = 0 %repeat newline %if bad list_last bad & 7 # 0 %finish %end %predicate bad block(%integer block) %integer i %false %if bad list_last bad = 0 %for i = 1, 1, bad list_last bad %cycle %true %if block = bad list_bad(i) %false %if block > bad list_bad(i) %repeat %false %end %begin %record(message fm) m %record(directory fm) directory %record(header fm)%name h %record(entry fm)%name f %record(extent fm)%name e %integer partition, slot %integerarray slots used(0 : last partition) %integerarray blocks used(0 : last partition) %integer i, n, next sequence = 0 %integer current user = 0, current extent, current file, block, next block %integername x set terminal mode(no page) slots used(i) = -1 %for i = 0, 1, last partition blocks used(i) = 0 %for i = 0, 1, last partition h == directory_header read bad list prompt("Reader: "); rhex(i) ether open(port, i << 8 ! port) %cycle next sequence = next sequence + 1 n = ether read(port, byteinteger(addr(m)), message size) %if m_sequence # next sequence %start printstring("Bad sequence "); write(m_sequence, 0) newline next sequence = next sequence - 1; ! re-increment next time %else %if m_code = create user %exit %if m_new user_owner = 0; ! Null create to finish directory = 0 partition = m_partition partition = last partition %unless 0 <= partition <= last partition slot = slots used(partition) %cycle slot = slot + 1 %if slot > u per p %start printstring("Partition register full") newline current user = 0 %exit %finish %if bad block(pd start(partition) + 4 * slot) %c %or bad block(pd start(partition) + 4 * slot + 1) %c %or bad block(pd start(partition) + 4 * slot + 2) %c %or bad block(pd start(partition) + 4 * slot + 3) %start printstring("Potential bad directory: ") write(partition, 0); write(slot, 1) newline %else h = m_new user h_perms = h_perms & permissions mask; ! Lose file count x == transfer(d write ! d verify, 2048, (pd start(partition) + 4 * slot) << 9, integer(addr(directory))) %cycle; %repeat %until x # 0 %if x # 2048 %start printstring("Error writing directory ") printstring(unpack(h_owner, 0)); newline %else current user = h_owner current file = 1 current extent = extent limit + 1 slots used(partition) = slot printstring(unpack(current user, 0)) printstring(" ("); write(partition, 0) print symbol('.'); write(slot, 0) printstring(") created") newline %exit %finish %finish %repeat %else %if m_code = create file %if current user = 0 %start printstring("Ignoring file ") printstring(unpack(m_new file_name 1, m_new file_name 2)) newline current file = 0 %else f == directory_file(current file) write(partition, 1); write(slot, 1) printstring(" Create ") printstring(unpack(current user, 0)) print symbol(':') printstring(unpack(m_new file_name 1, m_new file_name 2)) newline f = m_new file f_status = f_status & (\ dud file) f_extents = -1; ! Meantime next block = -1 %finish %else %if m_code = write block %if current file = 0 %start printstring("Ignoring block"); newline %else %if m_bytes < 0 ! End of file (N.B. can have ZERO as valid byte count!) h_files = h_files + 1 current file = current file + 1 x == transfer(d write ! d verify, 2048, (pd start(partition) + 4 * slot) << 9, integer(addr(directory))) %cycle; %repeat %until x # 0 %if x # 2048 %start printstring("Error writing directory ") printstring(unpack(h_owner, 0)); newline %finish next block = -1 %else %cycle block = blocks used(partition) blocks used(partition) = block + 1 %exit %unless bad block(block + p start(partition)) printstring("Ignoring bad block ") write(block + p start(partition), 0) newline %repeat %if block # next block %start current extent = current extent - 1 e == directory_extent(current extent) e_start <- block; e_size = 0 f_extents = current extent %finish e_size = e_size + 1 x == transfer(d write ! d verify, 512, (block + p start(partition)) << 9, integer(addr(m_data(0)))) %cycle; %repeat %until x # 0 %if x # 512 %start printstring("Dud block in file ") printstring(unpack(current user, 0)) print symbol(':') printstring(unpack(f_name 1, f_name 2)) newline %finish next block = block + 1 f_bytes = (f_bytes & permissions mask) ! m_bytes %finish %else printstring("Unknown request code ") write(m_code, 0) printstring(", mesage "); write(m_sequence, 0) newline m_code = -1 %finish %cycle NAK = 0 ether write(port, byteinteger(addr(m)), 8) %cycle; %repeat %until ACK & mask # 0 %exit %if NAK & mask = 0 printstring("NAK"); newline %repeat %repeat printstring("All done."); newline %end %of %program