PDP7-Unix/sys/s6.s

"** 01-s1.pdf page 34
" s6

itrunc: 0
   -7					" loop 7 times
   dac 9f+t				" in t0
   lac idskpp				" pointer to inode block numbers
   dac 9f+t+1				" save in t1
1:			" top of loop for inode blocks
   lac 9f+t+1 i				" fetch next block number
   sna					" allocated?
   jmp 4f				"  no
   lac i.flags				" check flags
   and o200000				
   sna					" large file?
   jmp 3f				"  no
   -64					" loop 64 times
   dac 9f+t+2				" save count in t2
   lac dskbufp				" get pointer to dskbuf
   dac 9f+t+3				" in t3
2:			" inner loop for indirect blocks
   lac 9f+t+1 i				" get indirect block number
   jms dskrd				" read it
   lac 9f+t+3 i				" read block number from indirect
   sza					" free?
   jms free				"  no: free it
   isz 9f+t+3				" increment pointer into indirect block
   isz 9f+t+2				" increment loop counter, skip if done
   jmp 2b				"  not done: loop
3:			" here with small file
   lac 9f+t+1 i				" load block number
   jms free				" free it
   dzm 9f+t+1 i				" clear block number
4:			" bottom of loop for inode block ptrs
   isz 9f+t+1				" increment block pointer
   isz 9f+t				" increment count, skip if done
   jmp 1b				"  not done
   lac i.flags
   and o577777				" clear large file flag
   dac i.flags
   jmp itrunc i
t = t+4
			" Given a pointer to a 4-word filename after
			" the jms to namei, and with AC holding the
			" i-num of the directory it is in, return the
			" i-number of the filename (and skip)
			" return zero in AC if not found (no skip)
namei: 0
   jms iget		" Get the inode from the i-num in the AC
   -1
   tad namei i		" get argptr-1
   dac 9f+t+1		" save in t1
   isz namei		" skip over argument
   lac i.flags
   and o20		" get directory bit
   sna			" Is this a directory?
   jmp namei i		"  no: return without skip
   -8
   tad i.size		" Subtract 8 from the file's size
   cma
   lrss 3
   dac 9f+t		" negative count of directory entries in t0
   sna			" any?
   jmp namei i		"  no: return without skip
   dzm di		" Store zero in di
1:
   lac di

"** 01-s1.pdf page 35

   jms dget		" Get a directory entry from the dirblock
   lac d.i		" get i-num
   sna			" in use?
   jmp 2f		"  no
   lac 9f+t+1		" get argptr-1
   dac 8
   lac d.name		" Compare the four words of the filename in the
   sad 8 i		" directory entry with the argument to namei
   skp
   jmp 2f		" No match
   lac d.name+1
   sad 8 i
   skp
   jmp 2f		" No match
   lac d.name+2
   sad 8 i
   skp
   jmp 2f		" No match
   lac d.name+3
   sad 8 i
   skp
   jmp 2f		" No match
   lac d.i		" A match. Get the i-number into AC
   isz namei		" give skip return
   jmp namei i
2:
   isz di		" No match, move up to the next direntry
   isz 9f+t		" any left?
   jmp 1b		"  yes: keep going
   jmp namei i		" Didn't find it, return zero in AC (without skip)
t = t+2
                        " Given an i-number in AC, fetch that i-node
                        " from disk and store it in the inode buffer
iget: 0
   dac ii		" Store the i-number in ii
   cll; idiv; 5		" Divide by 5: 5 inodes in a block
   dac 9f+t		" Store the remainder in 9f+t: the i-node
   lacq			" number within the block
   tad d2		" Add 2 to the quotient to get the block number
   dac 9f+t+1		" and store in 9f+t+1
   jms dskrd		" Get the block
   lac 9f+t
   cll; mul; 12		" Multiply the i-num within the block by 12
   lacq			" to get the offset into the block
   tad dskbufp		" Add on the base of the disk buffer
   dac 9f+t
   dac .+2
   jms copy; ..; inode; 12	" Copy 12 words from buffer to inode
   jmp iget i		" and return

iput: 0
   lac 9f+t+1
   jms dskrd
   law inode-1
   dac 8
   -1
   tad 9f+t
   dac 9
   -12
   dac 9f+t+2
1:
   lac 8 i

"** 01-s1.pdf page 36

   sad 9 i
   skp
   jmp 2f
   isz 9f+t+2
   jmp 1b
   jmp iput i
2:
   -1
   tad 8
   dac 8
   -1
   tad 9
   dac 9
1:
   lac 8 i
   dac 9 i
   isz 9f+t+2
   jmp 1b
   lac 9f+t+1
   jms dskwr
   jmp iput i
t = t+3

	" allocate directory entry
	" AC/ entry number
dget: 0
   dac di			" save entry number
   alss 3			" get word number
   dac 9f+t			" save in t0
   jms pget			" get free disk block
   dac 9f+t+1			" save in t1
   jms dskrd
   lac 9f+t
   and o77
   tad dskbufp
   dac 9f+t+2
   dac .+2
   jms copy; ..; dnode; 8
   lac 9f+t
   tad d8
   jms betwen; d0; i.size
      skp
   jmp dget i
   jms dacisize
   dzm d.i
   jmp dget i

dput: 0
   lac 9f+t+1
   jms dskrd
   lac 9f+t+2
   dac .+3
   jms copy; dnode; ..; 8
   lac 9f+t+1
   jms dskwr
   jmp dput i

t = t+3

	" get a block number for a file, returns disk block number
	" allocates block if not allocated
	" AC/ file offset
	"   jms pget
	" AC/ disk block number
pget: 0
   lrss 6				" convert offset to block
   dac 9f+t				" save as t0
   lac i.flags

"** 01-s1.pdf page 37

   and o200000
   sza					" large file bit set?
   jmp 2f				"  yes
   lac 9f+t				" no: small file
   jms betwen; d0; d6			" block 0..6?
      jmp 1f				"  no
   tad idskpp				" make into block number pointer
   dac 9f+t				" save in t0
   lac 9f+t i				" get disk block number
   sna					" allocated?
   jms alloc				"  no: allocate now
   dac 9f+t i				" save (new) disk block number
   jmp pget i				" return disk block number
1:					" here when file block>=7, not "large"
   jms alloc				" allocate indirect block
   dac 9f+t+1				" save as t1
   jms copy; i.dskps; dskbuf; 7		" copy all the disk block numbers
   jms copyz; dskbuf+7; 64-7		" zero rest of indirect block
   lac 9f+t+1				" get indirect block number back
   jms dskwr				" write indirect block to disk
   lac 9f+t+1
   dac i.dskps				" save indirect as new first block
   jms copyz; i.dskps+1; 6		" zero rest of block pointers
   lac i.flags
   xor o200000				" set "large file"
   dac i.flags
2:					" here with "large file"
   lac 9f+t				" get file block number
   lrss 6				" divide by 64 (indirects/block)
   jms betwen; d0; d6			" ok now?
      jms halt " file too big		"  no, you lose!
   tad idskpp				" yes: get indirect block pointer
   dac 9f+t+1				" save in t1
   lac 9f+t+1 i				" get indirect block number
   sna					" allocated?
   jms alloc				"  no, get it now
   dac 9f+t+1 i				" save (new) indirect block
   dac 9f+t+2				" save as t2
   jms dskrd				" read indirect block
   lac 9f+t				" get original block number
   and o77				" mod by 64
   tad dskbufp				" get pointer to disk block number
   dac 9f+t+1				" save as t1
   lac 9f+t+1 i				" fetch disk block number
   sza					" allocated?
   jmp pget i				"  yes: return
   jms alloc				" no: allocate data block
   dac 9f+t				" save as t0
   lac 9f+t+2				" get indirect block number
   jms dskrd				" read it in
   lac 9f+t				" get data block number
   dac 9f+t+1 i				" save data block number
   lac 9f+t+2
   jms dskwr				" write indirect block back
   lac 9f+t				" get data block back
   jmp pget i				" return it
t = t+3

iwrite: 0
   dac 9f+t				" save arg in t0
   lac iwrite				" load return address

"** 01-s1.pdf page 38

   dac iread				" save as iread return addr
   lac cskp				" load skip instruction
   dac iwrite				" save as iwrite instruction
   jmp 1f

	" iread from file referenced by loaded inode
	" AC/ file offset
	"    jms iread; addr; count
iread: 0
   dac 9f+t				" save offset in t0
   lac cnop				" get nop
   dac iwrite				" save as iwrite instruction
1:
   -1
   tad iread i				" get word before return addr
   dac 10				" store in index 10 & 11
   dac 11
   isz iread				" increment return addr
   lac iread i				" load addr
   dac 9f+t+1				" save in t1
   isz iread				" increment return addr
   lac o70000
   xct iwrite				" skip if write
   lac i.size				"  read: get file size
   cma
   tad 9f+t				" add offset
   cma
   jms betwen; d0; 9f+t+1
      lac 9f+t+1
   dac 9f+t+2
   cma
   tad d1
   sna
   jmp iread i
   dac 9f+t+1
1:
   lac 9f+t
   jms pget
   dac 9f+t+3
   jms dskrd
   lac 9f+t
   and o77
   tad dskbufp
   tad dm1
   xct iwrite
   jmp .+3
   dac 10
cskp:
   skp
   dac 11
2:
   lac 11 i
   dac 10 i
   isz 9f+t
   isz 9f+t+1
   jmp 3f
      xct iwrite
      jmp 4f
      lac 9f+t
      jms betwen; d0; i.size
         dac i.size
      lac 9f+t+3
      jms dskwr
   4:
"** 01-s1.pdf page 38
      lac 9f+t+2
      jmp iread i
3:
   lac 9f+t
   and o77
   sza
   jmp 2b
   xct iwrite
   jmp 1b
   lac 9f+t+3
   jms dskwr
   jmp 1b
t = t+4

	" system call helper
	" AC/ fd
	"   jms finac
	" return with: fnode and inode loaded
	"	or makes error return to user
finac: 0
   lac u.ac
   jms fget
      jms error
   lac f.flags
   sma
   jms error
   lac f.i
   jms iget
   jmp finac i

	" update inode file size with value in AC
dacisize: 0
   dac i.size
   jms iput
   lac i.size
   jmp dacisize i