PDP7-Unix/sys/s2.s

"** 01-s1.pdf page 7
" s2

	" file status (stat) system call
	" AC/ pointer to status (inode) buffer + i-num (13 words)
	"   sys status; dir_name_ptr; file_name_ptr
	"   NO_DD version: sys status; file_name_ptr
.status:
   jms arg			" fetch directory name pointer
   dac .+5
   jms arg			" fetch file name pointer
   dac .+6
   lac u.cdir			" get current working directory
   jms namei; ..		" look up source directory
      jms error			"  not found: return error to user
   jms namei; ..		" look up file
      jms error			"  not found: return error
   jms iget			" read file inode
   lac u.ac			" get user buffer pointer
   and o17777			" truncate to 13 bits
   jms betwen; o10000; o17762	" is user memory (but not last 14 wds)?
      jms error			"  no: error
   dac .+3			" save as copy destination
   jms copy; inode; ..; 12	" copy inode to user buffer
   lac d.i			" copy i-num from last dnode read ??
   dac 9 i			" save thru index 9 (pre-increment) ??
   jmp okexit

	" capture display?
.capt:
   lac u.ac			" get user AC
   dac u.dspbuf			" save as user display buffer
   jms movdsp			" switch to user display buffer
   jmp sysexit

	" release display?
.rele:
   dzm u.dspbuf			" clear user display buffer pointer
   law dspbuf			" get default display buffer
   jms movdsp			" change to it
   jmp sysexit

.chmod:
   jms isown			" check if user owns file arg
   lac u.ac			" get new permissions
   and o17			" mask to read/write bits
   lmq				" save in MQ
   lac i.flags			" get file flags
   and o777760			" clear permissions
   omq				" or in new permissions from MQ
   dac i.flags			" save in inode
   jms iput			" write inode back
   jmp okexit

.chown:
   jms isown			" check if user owns file arg
   lac u.ac			" get new owner
   dac i.uid			" save in inode
   jms iput			" write inode back
   jmp okexit

.getuid:			" getuid system call
   lac u.uid
   dac u.ac			" return u.uid in user AC
   jmp sysexit

.seek:
   jms seektell			" fetch offset & whence (return seek base)
   tad u.base			" add offset
"** 01-s1.pdf page 8
   spa				" positive?
   jms error			"  no: error
   lmq				" save position in MQ
   lac f.flags			" get file flags
   and d1			" get write bit
   sna				" open for write?
   jmp 1f			"  no
   lacq				" yes: get position
   jms betwen; d0; i.size	" between zero and size?
      jms dacisize		"  no: store new size
   jmp 2f
1:
   lacq				" reading: get position
   jms betwen; d0; i.size	" between zero and size?
      lac i.size		"  no: get current size
2:
   dac f.badd			" save as offset
   dac u.ac			" return in AC
   jms fput			" copy fnode back to user area
   jmp sysexit			" return to user

.tell:
   jms seektell			" fetch offset & whence (return seek base)
   cma
   tad d1			" negate base
   tad u.base			" add to user offset
   dac u.ac			" return in user AC
   jmp sysexit

.link:
   jms arg			" Save the argument pointers in
   dac 0f			"0f, 1f and 2f
   jms arg
   dac 1f
   jms arg
   dac 2f
   lac d4			" Search the directory at i-num 4
   jms namei; 0:0		" for the first argument
      jms error			" Didn't find it
   jms namei; 1:0		" In the i-num found by 1st namei,
      jms error			" search for 2nd argument, err not found
   dac u.base			" save in user data
   jms copy; 2:0; name; 4
   lac u.cdir			" Search the process' current directory
   jms namei; name		" for the third argument
      skp
   jms error			" Error if it already exists
   lac d1
   dac mode			" Save mode bits for access
   jms access			" check access (or return error to user)
   jms dslot			" allocate directory slot
   lac u.base			" get source file i-number
   jms iget			" read inode in
   lac ii			" get the i-num
   dac d.i			" Save the i-num in the directory entry
   jms copy; name; d.name; 4	" Copy the new link name into the directory entry
   lac i.uniq			" Copy the i-node unique number into
   dac d.uniq			" the directory entry
   -1
   tad i.nlks			" Decrement link count, i.e. one more link
   dac i.nlks
"** 01-s1.pdf page 9
   jms iput			" Save the i-node and directory entry for
   jms dput			" the new link
   jmp okexit			" and return OK

.unlink:
   jms argname			" fetch filename, inode
   dac u.base			" save i-number
   lac d1			" write mode bit
   dac mode			" save for access call
   jms access			" check access or return error (reads inode)
   dzm d.i			" clear directory i-num
   jms dput			" write directory entry back
   lac u.base			" get i-number back
   jms iget			" read inode back
   isz i.nlks			" increment link count (kept as negative count)
   jmp 1f			"  not zero
   jms itrunc			" zero links: free blocks
   dzm i.flags			" clear status (free inode)
1:
   jms iput			" write inode back to disk
   jmp sysexit

.setuid:			" setuid system call
   lac u.uid			" load current user id
   sma				" negative (super user)
   jms error			"  no: error!!
   lac u.ac			" load user AC
   dac u.uid			" save as new uid
   jmp sysexit

	" rename system call:
	"   sys rename; old_name_ptr; new_name_ptr
	" Questions:
	"   when is directory entry read??
	"   is access check on directory or src file??
	"   check for existing file with new name??
	"   when is directory entry written back??
.rename:
   jms arg			" fetch first arg (old name pointer)
   dac 0f			" save for namei
   jms arg			" fetch second arg (new name pointer)
   dac 1f			" save for copy
   lac u.cdir			" get CWD
   jms namei; 0:0		" search for (old) name
      jms error			"  not found: return error
   lac d1			" get write mode bit
   dac mode			" save for access call
   jms access			" access OK? (or return error to user)
   jms copy; 1:0; d.name; 4	" copy new name into directory entry
   jms dput			" and write it to disk
   jmp okexit

	" time system call returns line (mains) frequency ticks
	" high order bits returned in AC, low order in MQ
	" s.tim is located in "system" block (written to disk)
	" so this is a running count of uptime since first boot!
	" at 60Hz, 36 bits would last 36+ years!
.time:
   lac s.tim			" load high order bits
   dac u.ac			" return in AC
   lac s.tim+1			" load low order bits
   dac u.mq			" return in MQ
   jmp sysexit

.chdir:
   jms argname			" fetch argument as filename
   jms iget			" (re)read inode(???)
   lac i.flags			" get flags
   and o20			" get directory bit
   sna				" is a directory?
   jms error			"  no: return error to user
   lac ii			" yes: get i-number
   dac u.cdir			" save as current working directory
"** 01-s1.pdf page 10
   jmp okexit

	" open system call
	"   sys open; filename_ptr; flags (0 for read, 1 for write)
	" returns w/ "fd" in AC (or -1 if not found)
.open:
   jms arg			" get filename
   dac 0f			" save for namei
   jms arg			" get flags
   sza				" zero (read)
   lac d1			"  no: get write mode bit
   sna				" non-zero (write)?
   lac d2			"  no: get read mode bot
   dac mode			" save for access call
   lac u.cdir			" get current working directory
   jms namei; 0:0		" search for file
      jms error			" error: return -1
   jms iget			" load inode
   jms access			" check access (may return w/ error to user)
   lac i.flags			" get file flags
   and o20			" get directory bit
   sna				" is directory?
   jmp open1			"  no, join common code
   lac mode			" get access mode
   and d1			" get write bit
   sna				" write access?
   jmp open1			"  no, continue
   lac u.uid			" yes: get uid?
   sma				" negative? (-1 is superuser)
   jms error			"  no: return error
   jmp open1			" yes: join common code

.creat:
   lac d1			" mode bit 1 (write)
   dac mode			" save for access call
   jms arg			" get name pointer
   dac .+2			" save for copy
   jms copy; ..; name; 4	" copy filename to "name"
   lac u.cdir
   jms namei; name		" look up in current working directory
      jmp 1f			"  not found
   jms iget			" file exists: read inode
   jms access			" check access (or return error to user)
   lac i.flags			" get flags
   and o20			" get directory bit
   sna				" is a directory?
   jmp .+4			"  no: skip to truncate
   lac u.uid			" get user
   sma				" is super user?
   jms error			"  no: error
   jms itrunc			" yes: truncate
   cla
   jms dacisize			" clear i.size
   jmp open1
1:
   jms access			" here if not found
   lac u.ac			" get access bits from user AC (zero for lock!)
   and o17			" mask to permissions
   jms icreat
open1:				" common exit for open/creat
   jms fassign			" assign fd slot
      jms error			"  none free, return -1
   jmp sysexit

"** 01-s1.pdf page 11
.close:
   jms finac			" get fnode (open file) for fd in user AC
   dzm f.flags			" clear flags
   jms fput			" write fnode back to u.ofiles
   jmp sysexit

.read:
   jms arg			" get argument
   and o17777			" mask to address
   dac u.base			" save as I/O base
   jms arg			" get second argument
   dac u.count			" save as count
   lac u.base			" get base
   jms betwen; o10000; o17777	" end inside user memory?
      jms error			"  no: error
   tad u.count			" get end of buffer
   jms betwen; u.base; o17777	" inside buffer/user memory?
      jms error			"  no: error
   dac u.limit			" yes: save as I/O limit
1:
   jms finac			" get fnode for fd in user AC
   lac f.flags			" get open file flags
   and d1			" get write bit
   sza				" open for write?
   jms error			"  yes: error
   lac i.flags			" get inode flags
   and o40			" get special file bit
   sna				" special?
   jmp 1f			"  no
   iof				" yes: disable interrupts
   lac ii			" get i number
   tad swr			" add to base instruction
   dac .+1
   jmp .. i			" dispatch to read routine
1:
   lac u.base			" get user base
   dac 1f+1			" save as iread base
   lac u.count			" get user count
   dac 1f+2			" save as iread count
   lac f.badd			" get file offset
1:
   jms iread; ..; ..
   jmp exitrw

	" write system call:
	" AC/ fd
	"   sys write; buffer; count
	" AC/ count or -1 on error
.write:
   jms arg			" pick up buffer
   and o17777			" mask to addr
   dac u.base			" save as I/O base
   jms arg			" pick up count
   dac u.count			" save as count
   tad u.base			" add base (get limit)
   jms betwen; u.base; o17777	" check between base and end of memory
      jms error			"  no: error
   dac u.limit			" yes: save as limit
   jms finac			" get fnode with fd from user AC
   lac f.flags			" get open file table flags
   and d1			" open for write?
   sna				" if yes, skip
   jms error			"   no: error
   lac i.flags			" get inode flags
   and o40			" get device bit
"** 01-s1.pdf page 12
   sna				" special?
   jmp 1f			"  no
   iof				" yes, special: turn interrupts off
   lac ii			" get i number
   tad sww			" get write routine entry addr
   dac .+1
   jmp .. i			" dispatch to write routine
1:				" here with regular file
   lac u.base			" get base
   dac 1f+1			" save as iwrite arg 1
   lac u.count			" get count
   dac 1f+2			" save as iwrite 2
   lac f.badd			" get fd offset
1:
   jms iwrite; ..; ..		" write to file

exitrw:				" common exit for read/write system calls
   dac u.ac			" save return in user AC
   tad f.badd
   dac f.badd			" update file offset
   jms iput			" release inode
   jms fput			" release fnode
   jmp sysexit			" return to user