AUSAM/source/S/dtp.sbak

//////////////////////////////////////////////////////////////////////////
//									//
//	this is a version of 'tp' modified by ian j. AGSM		//
//									//
//	enhancements or otherwise:					//
//									//
//	1) new command 's'. this is a selective dump facility.		//
//	   the number following 's' in the key is taken as a number	//
//	   of hours -- if number absent then /etc/last-dump-time	//
//	   contains time last dump  -- any file modified within/since	//
//	   that time will be dumped.					//
//									//
//	2)  new commands  implemented, new meanings, old		//
//	    unused commands are out. see 'swtab' below			//
//									//
//	3)  tape blocksize increased to tbloksiz bytes, this allows 	//
//	    more data to be kept on tape than is possible using		//
//	    a blocksize of 512. bytes.					//
//									//
//	Yet to be done:							//
//		dumps of 65536 and more blocks				//
//		virtual blocks						//
//		links							//
//									//
//////////////////////////////////////////////////////////////////////////

/	Tunable constants

tapesize =  2400.			/ default tape length in feet.
tbloksiz = 16384.			/ blocksize on tape - must be a integer power of 2
					/ 16384. is max allowable for 800 BPI drives
					/ the silly hardware times-out before write
					/ has completed !! 32768 is fine for 1600 BPI
					/ but 16384 is positive not negative like 32768.
					/ 16384. is max possible value - too much
					/ trouble otherwise.

tbloking = tbloksiz\/512.		/ sectors per tape block.
nrzreclen = [tbloksiz+534.+799.]\/800.		/ record length in inches (800bpi)
pereclen  = [tbloksiz+1067.+1599.]\/1600.	/ record length in inches (1600bpi)

/ system calls...

smdate = 30.
mknod  = 14.
lock = 56.
	readlock = 0
	writelock = 1

/ system constants

IFMT = 60000
ISDIR = 40000
ISBLK = 20000
EEXIST = 17.
/
	iot = 4

	sys	time
	mov	r0,dumptime
	mov	r1,dumptime+2		/ note program start time
	mov	(sp),rnarg
	mov	(sp)+,narg
	mov	$cmexit,command
	tst	(sp)+
	cmp	narg,$2
	bge	1f
	mov	$2,narg
	br	3f
1:
	mov	(sp)+,r0
	mov	sp,parg

	sub	$512.,sp
	clr	-(sp)
	clr	-(sp)
	mov	$1,-(sp)		/ outfd
	mov	sp,outbp		/ tty output buffer
	mov	sp,outbp1		/ for benefit of flusher

1:
	movb	(r0)+,r1
	beq	3f
	mov	$swtab,r2
2:
	cmp	r1,(r2)+
	beq	2f
	tst	(r2)+
	bne	2b
	br	useerr
2:
	jsr	pc,*(r2)+
	br	1b
3:
	jsr	pc,opentap
	sys	signal; 2; 1
	bit	$1,r0
	bne	0f
	sys	signal; 2; intrupt		/ lets remove temp file
0:
	cmp	tfilename,$tmpdirname
	bne	0f
	sys	getpid		/ generate unique temp file name
	mov	$5,r2
1:
	mov	r0,r1
	clr	r0
	div	$10.,r0
	add	$'0,r1
	movb	r1,xxxxx-1(r2)
	sob	r2,1b
0:
	sys	indir; 0f
.data
0:	sys	creat
tfilename:	tmpdirname; 0600
.text
	bes	8f
	sys	close
	mov	tfilename,0f+2		/ get new name
	sys	indir; 0f
.data
0:	sys	open; 0; 2
.text
	bes	8f
	mov	r0,dirfd
	sys	fstat; statb		/ remember dev, inum
	mov	statb,tfdev
	mov	statb+2,tfino

	mov	tpsize,r0

	jmp	*command
8:
	jsr	r5,mesg
		< directory file create error\n\0>; .even
	jbr	done

opentap:
	cmp	command,$cmn
	beq	2f
	sys	open; magtape; 0
	br	3f
2:
	sys	open; magtape; 1
3:
	bes	1f
	mov	r0,fio
	rts	pc
1:
	jsr	r5,mesg
		<Tape open error\n\0>; .even
	jbr	done

setcom:
	cmp	command,$cmexit
	bne	useerr
	mov	(r5)+,command
	rts	r5

noflag:
	mov	(r5)+,r0
	beq	1f
	tstb	(r0)
	beq	noflag
	br	useerr
1:
	rts	r5

useerr:
	jsr	r5,mesg
		<Bad usage\n\0>; .even
	jbr	done
/
swtab:
	'0; dcof	/ d r i v e    0
	'1; dcof	/ d r i v e    1
	'm; dcm		/ d e n s i t y   800 b.p.i.
	'h; dch		/ d e n s i t y   1600 b.p.i.
	'f; dcf		/ f e e t  - size of tape
	't; dct		/ t e m p  file name
/
	'x; dcx		/ e x t r a c t  named files.
	'n; dcn		/ n e w  dump tape to be created
	'l; dcl		/ l i s t   contents of dump tape
/
	's; dcs		/ i n c r e m e n t a l l y  dump files to dump tape
	'c; dcc		/ c r e a t e   as needed directories/special-files
	'u; dcu		/ u p d a t e   last dump time in /etc/last-dump-time (new dump only)
/
	'v; dcv		/ v e r b o s e   dont be silent, give all info
	'q; dcq		/ q u e s t i o n   after each file selected for user approval(y-yes n-no x-exit)
	'i; dci		/ i g n o r e  tape read/write errors
	'.; dcd		/ d u m p  all files, even those beginning with '.'
	 0; 0

dcof:
	movb	r1,magu
	rts	pc

dcm:
	movb	r1,magt
	mov	$nrzreclen,recordln
	rts	pc

dch:
	movb	r1,magt
	mov	$pereclen,recordln
	rts	pc

dcf:
	jsr	pc,argnum		/ see if tape length specified.
	bne	0f			/ --> yes so use it.
	mov	$tapesize,r1		/ assume tapesize ft. tape.
0:
	mov	r1,tpsize		/ save length of tape.
	rts	pc

dct:					/ get a name from arg list
	cmp	rnarg,$2		/ sufficient args?
	ble	0f
	mov	*parg,tfilename		/ next arg is temp file name
	add	$2,parg
	dec	rnarg
	dec	narg
0:
	rts	pc

dci:
	incb	fli
	rts	pc

dcd:
	incb	fld
	rts	pc

dcn:
	jsr	r5,setcom; cmn
	rts	pc

dcl:
	jsr	r5,setcom; cml
	rts	pc

dcu:
	incb 	flu			/ cause start time to be written to /etc/last-dump-time
	rts	pc

dcv:
	incb	flv
	rts	pc

dcq:
	incb	flq
	rts	pc

dcx:
	jsr	r5,setcom; cmx
	rts	pc
dcc:
	inc	flc
	rts	pc

dcs:
	incb 	fls			/ use selective file dump
	jsr	pc,argnum		/ obtain number that optionally follows
	bne	4f			/ if non-zero then use hour interval specified
	mov	r0,-(sp)		/ save arg pointer
	sys	open; ldt; 0
	bec	3f
2:	jsr	r5,mesg; < Cannot open last-dump-time\n\0>; .even
	jbr	done
3:
	mov	r0,r1
	sys	read; seltim; 4		/ dump all files modded after this time
	bes	2b
	cmp	$4,r0
	bne	2b
	mov	r1,r0
	sys	close
	mov	(sp)+,r0
	rts	pc
4:
	mov	r0,-(sp)
	mov	r1,r0
	mpy	$-3600.,r0		/ get seconds(-ve) not hours.
	add	dumptime+2,r1		/ subtract
	adc	r0			/  time
	add	dumptime,r0		/   specified.
	mov	r0,seltim
	mov	r1,seltim+2		/ all files modified after this time dumped
	mov	(sp)+,r0
	rts	pc

/
argnum:
	clr	r1
0:
	movb	(r0),r2			/ pick next char from 1st argument.
	sub	$'0,r2
	blt	1f			/ not a valid digit so branch
	cmp	$9.,r2
	blt	1f			/ not a valid digit so branch
	inc	r0
	mul	$10.,r1
	add	r2,r1			/ build no. of hours.
	br	0b
1:
	tst	r1		/ set cc to indicate whether number found
	rts	pc

//////////////////////////////////////////////////////////////////////////

cmexit:
	jsr	r5,mesg
		<no function specified\n\0>; .even
	jbr	done

/
cmn:
	jsr	r5,noflag; flc; 0
	/ determine those files to be dumped
	jsr	pc,getfiles
	/ check to see if all files will fit on tape
	mov	nfiles,r0
	mul	$dirsiz,r0
	add	$tbloksiz-1,r1
	adc	r0
	div	$tbloksiz,r0
	mov	r0,-(sp)		/ big blocks occupied by tape directory
	clr	r0
	mov	tapad,r1
	add	$tbloking-1,r1
	adc	r0
	div	$tbloking,r0		/ number big blocks wanted for files
	add	(sp)+,r0		/ total number big blocks wanted
	mul	recordln,r0		/ total number inches required
	add	$11.,r1
	adc	r0
	div	$12.,r0			/ r0 = feet required
	cmp	tpsize,r0		/ compare tape sizes (in feet)
	bhis	0f			/ --> will fit on the tape
	mov	r0,-(sp)
	jsr	r5,mesg
		<tape too small to contain all files\n\0>; .even
	mov	(sp)+,r0
	jsr	r5,numb; 5
	jsr	r5,mesg
		< foot tape required\n\0>; .even
	jbr	done
	/ will fit so lets get it all on tape
0:
	jsr	pc,fflush
	jsr	pc,make
	tst	flu
	jeq	usage		/ no update of last-dump-time reqd.
	sys	creat; ldt; 0600
	bec	2f
1:
	jsr	r5,mesg
		<can't update last-dump-time\n\0>; .even
	jbr	done
2:
	mov	r0,r1
	sys	write; dumptime; 4
	bes	1b
	cmp	r0,$4
	bne	1b
	br	usage

/
.globl	_localtime,_ctime

cml:
	jsr	r5,noflag; flc; flq; 0
	jsr	pc,rddir		/ read tape directory onto disk and format it
	jsr	r5,mesg
		<\n\n this dump initiated on   \0>; .even
	mov	dumptime+2,-(sp)
	mov	dumptime,-(sp)
	jsr	pc,_ctime
	mov	r0,r1
	jsr	pc,pstr
	tstb	flv
	beq	1f
	jsr	r5,mesg
	<\n    mode     uid   tapa      size   date    time name\n\n\0>; .even
1:
	jsr	r5,gettape; taboc
	jbr	usage2

//////////////////////////////////////////////////////////////////////////

cmx:
	jsr	r5,noflag; 0
	tstb	flc
	beq	1f
	tstb	flq
	beq	1f
	jbr	useerr			/ don't allow directory create with questions
1:
	jsr	pc,rddir		/ read tape directory into core and format it
	jsr	pc,tread		/ get first tape block
	jsr	r5,gettape; xtract
	br	done

/
usage:
	mov	nused,r0
	jsr	r5,numb; 4
	jsr	r5,mesg
		< tape blocks\n\0>; .even
usage2:
	mov	nfiles,r0	/ no of files picked up
	jsr	r5,numb; 4
	jsr	r5,mesg
		< files on tape\n\0>; .even

/////////////////////////////////////////////////////////////////////////

done:
	jsr	r5,mesg
		<END\n\0>; .even
	jsr	pc,fflush
	mov	$15.,r1
0:	mov	r1,r0
	sys	close		/ close ALL files
	sob	r1,0b
intrupt:
	mov	tfilename,0f+2	/ get dir file name
	sys	indir; 0f
.data
0:	sys	unlink; 0	/ and remove it
.text
	sys	exit

/
pstr:
	movb	(r1)+,r0
	beq	1f
	jsr	pc,putch
	br	pstr
1:
	rts	pc

/////////////////////////////////////////////////////////////////////////

mesg:
	movb	(r5)+,r0
	beq	1f
	jsr	pc,putch
	br	mesg
1:
	inc	r5
	bic	$1,r5
	rts	r5

/////////////////////////////////////////////////////////////////////////

	.data
	.globl	putc
putch:
	jsr	r5,putc
outbp:	.=.+2
	rts	pc

/////////////////////////////////////////////////////////////////////////

	.globl	flush
fflush:
	jsr	r5,flush
outbp1:	.=.+2
	rts	pc
	.text

/////////////////////////////////////////////////////////////////////////

getc:
	clr	r0
	sys	read; ch; 1
	movb	ch,r0
	rts	pc

/
rddir:
	mov	dirfd,r0
	sys	seek; 0; 0		/ position at start of disk dir.
	jsr	pc,tread		/ read first tape block
	mov	$tapeb,r0		/ 'from'
	mov	$tapeheader,r1		/ 'to'
	mov	$dirsiz\/2,r2		/ number of words to copy
0:
	mov	(r0)+,(r1)+
	sob	r2,0b			/ copy tape header.
	mov	ndirblks,r2		/ a zero means old format
	br	2f			/ write this block to disk.
1:
	jsr	pc,tread		/ read next tape block.
	bne	2f			/ a tape mark. Is it expected?
	tst	ndirblks		/ old format?
	beq	3f			/ ok
	jsr	r5,mesg
		<Unexpected tape mark in directory\n\0>; .even
	jbr	done
2:	jsr	pc,dwrite		/ write to disk for later use.
	sob	r2,1b			/ more to do?
3:
	rts	pc

/
wrdir:
	mov	dirfd,r0
	sys	seek; 0; 0		/ position at start of disk dir.
	jsr	pc,dread		/ read first disk block
	mov	dirfd,r0
	sys	fstat; statb		/ get info on directory file
	jes	drderr
	movb	statb+9.,r0		/ get high order size
	mov	statb+10.,r1		/ get low order size
	div	$tbloksiz,r0		/ calculate number of tape blocks
	tst	r1			/ any remainder ??
	beq	0f			/ --> no.
	inc	r0			/ round
0:
	mov	r0,ndirblks		/ no of dir blocks !!
	mov	$tapeheader,r0		/ 'from'
	mov	$tapeb,r1		/ 'to'
	mov	$dirsiz\/2,r2		/ number of bytes to copy
0:
	mov	(r0)+,(r1)+
	sob	r2,0b			/ copy tape header.
	br	2f
1:
	jsr	pc,dread		/ read next directory block.
	beq	3f			/ --> end of directory file.
2:	jsr	pc,twrite		/ write to tape
	br	1b			/ continue.
3:
	rts	pc

/
tread:
	mov	fio,r0
	sys	read; tapeb; tbloksiz
	bes	trderr
	tst	r0		/ set cc for eof test on return
	beq	0f
	cmp	r0,$tbloksiz
	bne	trderr
	tst	r0		/ set cc for eof test on return
0:
	rts	pc

trderr:
	jsr	r5,mesg
		<Tape read error\n\0>; .even
	tstb	fli
	jeq 	done		/ don't ignore the error, stop
	mov	$tapeb,r0
2:
	clr	(r0)+
	cmp	r0,$tapeb+tbloksiz
	blo	2b
	rts	pc

/////////////////////////////////////////////////////////////////////////

dread:
	mov	dirfd,r0
	sys	read; tapeb; tbloksiz
	bes	drderr
	bit	$dirsiz-1,r0
	bne	drderr
	tst	r0
	rts	pc

drderr:
	jsr	r5,mesg
		<Directory file read error\n\0>; .even
	jbr	done

eread:
	mov	dirfd,r0
	sys	read; cde; dirsiz
	bes	drderr
	bit	$!dirsiz,r0
	bne	drderr
	tst	r0
	rts	pc

/
twrite:
	inc	nused		/ keep track of number blocks written to tape
	mov	fio,r0
	sys	write; tapeb; tbloksiz
	bes	twrerr
	cmp	r0,$tbloksiz
	bne	twrerr
	rts	pc

twrerr:
	jsr	r5,mesg
		<Tape write error\n\0>; .even
	jbr	done

/////////////////////////////////////////////////////////////////////////

dwrite:
	mov	dirfd,r0
	sys	write; tapeb; tbloksiz
	bes	dwrerr
	cmp	r0,$tbloksiz
	bne	dwrerr
	rts	pc

dwrerr:
	jsr	r5,mesg
		<Directory file write error\n\0>; .even
	jbr	done

ewrite:
	clr	dirlast
ewrited:
	mov	ebufpt,r0
	cmp	r0,$tapeb+tbloksiz
	blo	0f
	mov	dirfd,r0
	sys	write; tapeb; tbloksiz
	bes	dwrerr
	cmp	r0,$tbloksiz
	bne	dwrerr
	mov	$tapeb,r0
0:
	mov	$cde,r1
	mov	$dirsiz\/2,r2
0:
	mov	(r1)+,(r0)+
	sob	r2,0b
	mov	r0,ebufpt
	rts	pc

/
verify:
	movb	(r5)+,0f
	inc	r5
	tstb	flq
	bne	1f
	tstb	flv
	beq	2f
1:
	jsr	pc,9f
.data
9:
	jsr	r5,mesg
		0:<x \0>; .even
	rts	pc
.text
	mov	r1,-(sp)
	mov	$cpathname,r1
	jsr	pc,pstr
	mov	(sp)+,r1
	tstb	flq
	beq	1f
	jsr	r5,mesg
		< \0>
	jsr	pc,fflush
	jsr	pc,getc
	cmp	r0,$'x
	bne	3f
	jsr	pc,getc
	jbr	done
3:
	cmp	r0,$'\n
	beq	3f
	cmp	r0,$'y
	bne	4f
	jsr	pc,getc
	cmp	r0,$'\n
	beq	2f
4:
	jsr	pc,getc
	cmp	r0,$'\n
	bne	4b
	br	3f
1:
	jsr	r5,mesg
		<\n\0>
2:
	tst	(r5)+
3:
	rts	r5

/
getfiles:
	cmp	narg,$2
	bne	1f
	mov	$".\0,cpathname
	jsr	pc,callout
1:
	cmp	narg,$2
	ble	1f
	dec	narg
	mov	*parg,r1
	add	$2,parg
	mov	$cpathname,r2
2:
	movb	(r1)+,(r2)+
	bne	2b
	jsr	pc,callout
	mov	$-1,dirlast
	br	1b
1:
	mov	ebufpt,r0
	sub	$tapeb,r0
	beq	1f
	mov	r0,2f+4
	mov	dirfd,r0
	sys	0; 2f
.data
2:	sys	write; tapeb; 0
.text
	bes	0f
	cmp	r0,2b+4
	beq	1f
0:
	jmp	dwrerr
1:
	rts	pc

/
expand:
	sys	open; cpathname; 0
	bes	fserr
	mov	r0,-(sp)
1:
	mov	(sp),r0
	sys	read; catlb; 16.
	bec	4f
	tst	(sp)+
	jbr	fserr
4:
	tst	r0
	beq	1f
	tst	catlb
	beq	1b
	mov	$catlb+2,r1
	tstb	fld			/ dump files starting with '.'?
	bne	2f
	cmpb	(r1),$'.
	beq	1b
	br	3f
2:
	cmp	(r1),$'.
	beq	1b
	cmp	(r1),$"..
	bne	3f
	tstb	2(r1)
	beq	1b
3:
	mov	$cpathname,r0
	mov	$catlb+2,r1
2:
	tstb	(r0)+
	bne	2b
	dec	r0
	mov	r0,-(sp)
	cmpb	-1(r0),$'/
	beq	2f
	movb	$'/,(r0)+
2:
	movb	(r1)+,(r0)+
	bne	2b
	jsr	pc,callout
	clrb	*(sp)+
	br	1b
1:
	mov	(sp)+,r0
	sys	close
	rts	pc
/
callout:
	sys	stat; cpathname; statb
	bec	0f
fserr:
	mov	$cpathname,r1
	jsr	pc,pstr
	jsr	r5,mesg
		< -- Can't access file\n\0>; .even
	rts	pc
0:
	cmp	statb,tfdev	/ check for temp file
	bne	0f
	cmp	statb+2,tfino
	bne	0f
	rts	pc		/ don't dump it
0:
	tstb	fls		/ selective file dump ??
	beq	0f		/ --> no.
	cmp	seltim,statb+32.
	blo	0f		/ will dump
	bhi	1f		/ dont dump
	cmp	seltim+2,statb+34.
	blo	0f		/ will dump
1:
	mov	statb+4,r0
	bic	$!IFMT,r0
	cmp	$ISDIR,r0
	jne	3f
0:
	jsr	r5,verify; 'a
		rts pc
	inc	nfiles
	clr	csize
	clr	csize+2
	movb	statb+7,cuid
	movb	statb+8,cuid+1
	mov	statb+32.,ctime
	mov	statb+34.,ctime+2
	mov	tapad,ctapea	/ store tape address in tape dir entry
	mov	statb+4,r0
	mov	r0,cmode
	bic	$!IFMT,r0
	bne	1f		/ --> not a plain file
	movb	statb+9.,csize	/ only 24 bits for the moment
	mov	csize,r2
	mov	statb+10.,r3
	mov	r3,csize+2
	add	$511.,r3
	adc	r2
	ashc	$-9,r2		/ file size (next highest multiple of 512 bytes)
	add	r3,tapad	/ increment by size of file - ready for next file
	jsr	pc,ewrite	/ add to disk dir file
	rts	pc
1:
	cmp	r0,$ISDIR
	jeq	2f		/ directory so see whats in it
	mov	statb+12.,cmajmin	/ identify the special file
	jsr	pc,ewrite	/ add to disk dir file
	rts	pc
2:
/ check directory for files to dump
/ add directory entry to disk directory
/ but delete it if no files dumped from the directory
	tst	dirlast		/if last thing put in was directory
	bgt	1f
	cmp	ebufpt,$tapeb+diruplim
	blos	1f
	mov	ebufpt,r0
	sub	$tapeb,r0
	mov	r0,2f+4
	mov	dirfd,r0
	sys	0;2f
	.data
2:	sys	write; tapeb; 0
	.text
	jes	dwrerr
	cmp	r0,2b+4
	jne	dwrerr
	mov	$tapeb,ebufpt
1:
	jsr	pc,ewrited	/ add to disk dir file
	inc	dirlast
	jsr	pc,expand
	tst	dirlast		/ any file dumped in this dir?
	beq	3f		/ --> yes.
	dec	nfiles		/     no. delete reference to directory
	dec	dirlast		/ remember how many
	sub	$dirsiz,ebufpt
	mov	flq,-(sp)
	clr	flq		/ no questions !!
	jsr	r5,verify; 'd
		0		/ won't happen ever
	mov	(sp)+,flq
3:
	rts	pc
/
gettape:
	clr	exta			/ clr top 16 bits of tape addr
	clr	ctapea			/ clr bottom 16 bits of tape addr
	mov	nfiles,r4
	bne	0f
	jsr	r5,mesg
		<Tape empty?\n\0>; .even
	jbr	done
0:
	mov	dirfd,r0
	sys	seek; dirsiz; 0		/ skip tape header
	sub	$2,narg			/ full extract or list?
	bgt	0f
	mov	$1,narg
	mov	$1f,parg		/ dummy arg list
	.data
1:	1f
1:	0
	.text
0:
	mov	narg,r0
0:
	clr	-(sp)
	sob	r0,0b			/ table to record argument matches
0:
	mov	ctapea,r3		/ save address last file
	jsr	pc,eread		/ get next dir entry
	jeq	drderr
	cmp	r3,ctapea		/ overflow into next 16bits ??
	blos	1f			/ if not ignore
	inc	exta			/ full 32bit address
1:
	mov	parg,-(sp)
	mov	narg,-(sp)
1:					/ search for it amongst args
	mov	*2(sp),r3
	cmp	rnarg,$2		/ global?
	beq	3f
	mov	$cpathname,r2
2:	tstb	(r3)			/ end of arg?
	beq	2f			/ a match!
	cmpb	(r2)+,(r3)+
	beq	2b
	br	4f			/ no match
2:
	tstb	(r2)			/ end of entry name?
	beq	3f
	cmpb	(r2),$'/		/ or path segment?
	bne	4f
3:
	mov	r5,-(sp)
	jsr	pc,*(r5)		/ call passed routine to do work
	mov	(sp)+,r5
	mov	2(sp),r0
	sub	parg,r0
	add	sp,r0
	inc	4(r0)			/ record a match
	br	2f
4:
	add	$2,2(sp)
	dec	(sp)
	bne	1b
2:
	cmp	(sp)+,(sp)+		/ pop off junk
	sob	r4,0b
					/ search complete. now check for fails
	mov	narg,r2
	mov	parg,r3
0:
	mov	(r3)+,r1
	mov	(sp)+,r0		/ count of references
	bne	1f			/ it was matched
	jsr	pc,pstr
	jsr	r5,mesg
		<: not found\n\0>; .even
	br	2f
1:
	add	r0,r4
2:
	sob	r2,0b
	cmp	command,$cmx
	bne	0f
	mov	r4,r0
	jsr	r5,numb; 6
	jsr	r5,mesg
		< files extracted\n\0>; .even
0:
	tst	(r5)+			/ chuck away arg
	rts	r5

/
numb:
	mov	r1,-(sp)
	mov	r0,-(sp)
	mov	r0,r1
	clr	r0	/ 32bit number in r0,r1
	br	1f

numbx:
	mov	r1,-(sp)
	mov	r0,-(sp)
	mov	6(sp),r0
	mov	8(sp),r1
1:
	mov	$catlb,r2
1:
	mov	$"  ,(r2)+
	cmp	r2,$catlb+12.
	blo	1b
	cmp	(r5),$2
	bne	1f
	mov	$"00,-2(r2)
1:
	jsr	pc,numb2
	clrb	(r2)
	sub	(r5)+,r2
	mov	r2,r1
	jsr	pc,pstr
	mov	(sp)+,r0
	mov	(sp)+,r1
	rts	r5

numb1:
	clr	r0
	div	$10.,r0
	mov	r1,-(sp)
	mov	r0,r1
	beq	1f
	jsr	pc,numb1
1:
	mov	(sp)+,r0
	add	$'0,r0
	movb	r0,(r2)+
	rts	pc

numb2:
	div	$10000.,r0
	beq	numb1		/ --> if zero quotient
	mov	r1,-(sp)
	mov	r0,r1
	jsr	pc,numb1
	mov	(sp)+,r1
	clr	r0		/ remainder is always 4 digits !!
	div	$1000.,r0
	add	$'0,r0
	movb	r0,(r2)+
	clr 	r0
	div	$100.,r0
	add	$'0,r0
	movb	r0,(r2)+
	clr 	r0
	div	$10.,r0
	add	$'0,r0
	movb	r0,(r2)+
	add	$'0,r1
	movb	r1,(r2)+	/ greg rose responsible for this code
	rts	pc		/ ian j responsible for this comment

/
make:
	jsr	pc,wrdir

make1:
	mov	dirfd,r0
	sys	seek; dirsiz; 0	/ start at first dir entry.
1:
	jsr	pc,eread	/ read next entry.
	beq	1f		/ --> end of directory
	bit	$IFMT,cmode
	bne	1b		/ --> not a plain file.
	mov	csize,r2
	mov	csize+2,r3
	add	$511.,r3
	adc	r2
	ashc	$-9,r2		/ file size (next highest multiple of 512 bytes)
	sys	open; cpathname; 0	/ open it for reading.
	bes	phserro
	mov	r0,r2		/ save file descriptor for reads

.if	lock
FLOCKED = 02000
	bit	$FLOCKED,cmode	/ is file one of those special locking types?
	beq	6f
	sys	lock; readlock
.endif

6:
	mov	r2,r0
	jsr	pc,0f
.data
0:
	sys	read;  7: tapeb  ;  8:  tbloksiz
	rts	pc
.text
	bes	phserrr
	add	r0,7b		/ point next available location in tape buffer
	mov	r0,r5		/ save count of bytes read
	cmp	$tapeb+tbloksiz,7b	/ file finished ??
	bhi	5f		/ --> yes.
	mov	8b,r0		/ bytes to be read last read.
	ash	$-9,r0		/ get as block count
	sub	r0,r3		/ adjust file size counter
	bmi	phserrb		/ file has got bigger
	beq	3f		/ file has not changed
	mov	$tapeb,7b
	mov	$tbloksiz,8b
	jsr	pc,twrite
	br	6b
5:
	add	$511.,r0
	ash	$-9,r0		/ blocks just read
	sub	r0,r3		/ adjust file size
	bmi	phserrb		/ file is now bigger?
	bgt	phserrs		/ file is now smaller?
	cmpb	r5,csize+2	/ check that file same length now
	bne	phserrs
	sub	$tapeb,7b	/ make relative
	add	$511.,7b
	bic	$511.,7b	/ round up next read start address.
	add	$tapeb,7b	/ make absolute.
	mov	$tapeb+tbloksiz,8b
	sub	7b,8b		/ max length next record
	cmp	7b,$tapeb+tbloksiz	/ any room left ??
	bne	4f		/ --> yes, so continue
3:
	jsr	pc,twrite
	mov	$tapeb,7b	/ re-init
	mov	$tbloksiz,8b	/ re-init
4:
	mov	r2,r0
	sys	close
2:
	br	1b		/ next file
1:
	cmp	7b,$tapeb
	beq	0f		/ only write last block if have to
	jsr	pc,twrite
	mov	$tapeb,7b	/ re-init
	mov	$tbloksiz,8b	/ re-init
0:
	rts	pc

/ //
//	Recover from phase errors.
//
//	O - Open error.
//	R - Read error.
//	B - File is now bigger.
//	S - File is now smaller.
//

phserro:
	movb	$'O,phsedes
	br	phserr
phserrr:
	movb	$'R,phsedes
	br	phserr
phserrb:
	movb	$'B,phsedes
	mov	7b,r1
	mov	r5,r0
	bic	$!511.,r0
	beq	3f
	add	$-512.,r0
	sub	r0,r1		/ r1 rounded up to next block
3:
	mov	r3,r0
	ash	$9.,r0
	add	r0,r1
	br	5f

phserrs:
	movb	$'S,phsedes
	mov	r5,r0		/ recover length really read
	mov	7b,r1		/ next address
	bic	$!511.,r0
	beq	3f		/ already at a block address
0:
	clrb	(r1)+
	inc	r0
	bit	$512.,r0	/ end of this block?
	beq	0b
	cmp	r1,$tapeb+tbloksiz
	blo	3f
	jsr	pc,twrite
	mov	$tapeb,r1
	br	3f

phserr:
	mov	7b,r1
3:
	tst	r3		/ all done ??
	ble	5f		/ --> yes !!
	mov	$256.,r0	/ clear next block
0:	clr	(r1)+
	sob	r0,0b
	cmp	r1,$tapeb+tbloksiz
	blo	1f
	jsr	pc,twrite
	mov	$tapeb,r1
1:	dec	r3
	br	3b		/ go for next block
5:
	mov	r1,7b
	neg	r1
	add	$tapeb+tbloksiz,r1
	mov	r1,8b

	/ the phase error file has been sortof dumped
	/ now recover...

	mov	$cpathname,r1
	jsr	pc,pstr
	mov	$3f,r1
	jsr	pc,pstr
.data
3:
		< -- Phase error >
phsedes:	< \n\0>; .even
.text
	cmp	phsedes,$'O
	beq	2b
	mov	r2,r0
	sys	close
	br	2b

/
/	called from 'gettape' to list a directory entry.

taboc:
	tstb	flv
	jeq	4f
	mov	cmode,r0
	mov	r0,-(sp)
	movb	$'-,r5
	mov	$tabpf,mss
	bic	$!IFMT,r0	/ look at file type bits
	beq	0f		/ --> plain file
	movb	$'d,r5
	mov	$tabdf,mss
	cmp	$ISDIR,r0
	beq	0f		/ --> directory
	movb	$'c,r5
	mov	$tabsf,mss
	cmp	$ISBLK,r0
	beq	0f		/ --> character special
	movb	$'b,r5		/     block special
0:	mov	r5,r0
	jsr	pc,putch
	mov	(sp),r0
	ash	$-6,r0
	bit	$40,r0
	jsr	pc,pmod		/ print access bits for owner
	mov	(sp),r0
	ash	$-3,r0
	bit	$200,r0
	jsr	pc,pmod		/ print access bits for group
	mov	(sp)+,r0
	bit	$1000,r0
	jsr	pc,pmod		/ print access bits for others
	mov	cuid,r0
	jsr	r5,numb; 6	/ user id.
	mov	ctapea,-(sp)	/ tape address
	mov	exta,-(sp)	/ tape address
	jsr	r5,numbx; 7
	cmp	(sp)+,(sp)+
	jmp	*mss		/ jump on file type
tabpf:	mov	csize+2,-(sp)	/ file size
	mov	csize,-(sp)	/ file size
	jsr	r5,numbx; 10.
	cmp	(sp)+,(sp)+
	br 	0f
tabdf:	jsr	r5,mesg
		<          \0>; .even
	br	0f
tabsf:	movb	cmajmin+1,r0			/ major dev no
	bic	$177400,r0			/ lo byte only
	jsr	r5,numb; 6
	movb	$',,r0
	jsr	pc,putch
	movb	cmajmin,r0			/ minor dev no
	bic	$177400,r0			/ lo byte only
	jsr	r5,numb; 3
0:	mov	ctime+2,-(sp)
	mov	ctime,-(sp)
	jsr	pc,_localtime
	tst	(sp)+
	mov	r0,(sp)
	mov	6(r0),r0		/ day of the month(1-31)
	jsr	r5,numb; 3
	mov	$'/,r0
	jsr	pc,putch
	mov	(sp),r0
	mov	8.(r0),r0		/  month(0-11)
	inc	r0
	jsr	r5,numb; 2
	mov	$'/,r0
	jsr	pc,putch
	mov	(sp),r0
	mov	10.(r0),r0		/ year - 1900
	jsr	r5,numb; 2
	mov	(sp),r0
	mov	4(r0),r0		/ hours(0-23)
	jsr	r5,numb; 3
	mov	$':,r0
	jsr	pc,putch
	mov	(sp)+,r0
	mov	2(r0),r0		/ minutes(0-59)
	jsr	r5,numb; 2
	mov	$' ,r0
	jsr	pc,putch
4:
	mov	$cpathname,r1
	jsr	pc,pstr
	jsr	r5,mesg
		<\n\0>
	rts	pc

pmod:
	beq	1f
	mov	$'s,-(sp)
	br	2f
1:
	bit	$1,r0
	beq	1f
	mov	$'x,-(sp)
	br	2f
1:
	mov	$'-,-(sp)
2:
	bit	$2,r0
	beq	1f
	mov	$'w,-(sp)
	br	2f
1:
	mov	$'-,-(sp)
2:
	bit	$4,r0
	beq	1f
	mov	$'r,r0
	br	2f
1:
	mov	$'-,r0
2:
	jsr	pc,putch
	mov	(sp)+,r0
	jsr	pc,putch
	mov	(sp)+,r0
	jsr	pc,putch
	rts	pc

/
/	if the file exists delete it iff not a directory.
/	this is necessary otherwise a filesys mess will result

xunlnk:
	sys	stat; cpathname; statb	/ get info on the file.
	bes	0f			/ --> file don't exist
	bic	$!IFMT,statb+4		/ isolate file type bits
	cmp	$ISDIR,statb+4		/ directory ??
	beq	0f
	sys	unlink; cpathname		/ remove it
0:
	rts	pc

/////////////////////////////////////////////////////////////////////////

/	called from 'gettape' to process a directory entry

xtract:
	tstb	flc		/ create directory mode ??
	beq	0f		/ --> no.
	mov	cmode,r1
	mov	r1,9f
	bic	$!IFMT,r1
	beq	0f		/ --> plain file
	clr	8f		/ assume directory.
	cmp	r1,$ISDIR
	beq	4f		/ --> directory.
	mov	cmajmin,8f	/ special file.
4:
	jsr	pc,xunlnk
	jsr	r5,verify; 'c
		rts	pc
	bic	$!60777,9f
	sys	0; 7f
.data
7:
	sys	mknod; cpathname; 9: 0; 8: 0	/ create directory or special file
.text
	bec	3f
	cmp	r0,$EEXIST			/ file already exists?
	jne	crterr
	cmp	r1,$ISDIR
	jne	crterr
	/ if directory already exists then ok
	/ dont clutter up terminal with crap about create errors

	sys	stat; cpathname; statb
	bic	$!IFMT,statb+4
	cmp	$ISDIR,statb+4
	jne	crterr
	jbr	5f

3:
	cmp	r1,$ISDIR
	jne	5f
	mov	$cpathname,r0
	mov	$cpathname+1,r5
	mov	$namewk,r1
3:
	movb	(r0),(r1)+
	beq	3f
	cmpb	(r0)+,$'/
	bne	3b
	mov	r0,r5
	br	3b
3:
	movb	$'/,-1(r1)
	movb	$'.,(r1)+
	clrb	(r1)
	sys	link; cpathname; namewk
	movb	$'.,(r1)+
	clrb	(r1)
	movb	-(r5),r1
	clrb	(r5)			/name of parent directory
	sys	link; cpathname; namewk
	movb	r1,(r5)
	br	5f
0:
	bit	$IFMT,cmode
	bne	1f		/ --> not a plain file(ignore since flc=0)
	jsr	r5,verify; 'x
		rts pc
	mov	r4,-(sp)
	mov	exta,r4			/ position of file
	mov	ctapea,r5		/ position of file
	bic	$tbloking-1,r5		/ block address
	sub	tapad,r5		/ seek distance
	sbc	r4			/ seek distance
	sub	tapad+2,r4		/ seek distance
	ashc	$0,r4			/ test seek distance (32-bits)
	beq	0f			/ tape position correct
	bgt	4f			/ move tape forward
	iot				/ this cannot happen.
					/ directory is searched in order
					/ It must be mangled to get here
4:
	div	$tbloking,r4		/ convert to tape blocks
	mov	r4,r5			/ the number of tape blocks.
4:
	jsr	pc,tread		/ read a record
	add	$tbloking,tapad		/ update tape address
	adc	tapad+2			/ update tape address
	sob	r5,4b
0:
	mov	(sp)+,r4
	jsr	pc,xunlnk
	mov	cmode,0f
	sys	0; 9f
.data
9:
	sys	creat; cpathname; 0:..
.text
	bes	crterr1		/ unable to create the file ??

	mov	r0,r2		/ save file descriptor
	mov	ctapea,r5	/ tape address of the file

.if	lock
	bit	$FLOCKED,cmode
	beq	2f
	sys	lock; writelock
.endif

2:
	bic	$![tbloking-1],r5		/ get block displacement in tape buffer
	ash	$9,r5		/ get as byte displacement
	mov	r5,9f
	add	$tapeb,9f	/ start writing from here.
	add	$-tbloksiz,r5
	neg	r5		/ bytes left in buffer
	mov	r5,8f
	sub	r5,csize+2
	sbc	csize	/ is this all the file ??
	bge	0f		/ --> no.
	add	csize+2,r5
	mov	r5,8f
	beq	2f		/ --> if null file/multiple of ....
	clr	r5
0:
	mov	r2,r0
	sys	0; 7f
.data
7:
	sys	write; 9: 0; 8: 0
.text
	bes	crterr1		/ write error
	cmp	r0,8b
	bne	crterr1		/ write error (out of space probably)
	tst	r5
	ble	2f		/ all done
	jsr	pc,tread
	add	$tbloking,tapad	/ update tape address
	adc	tapad+2		/ update tape address
	mov	tapad,r5
	br	2b		/ go again
2:
	mov	r2,r0
	sys	close
5:
	mov	cuid,0f
	sys	0; 9f
.data
9:
	sys	chown; cpathname; 0:..
.text
	mov	ctime,r0
	mov	r1,-(sp)
	mov	ctime+2,r1
	sys	0; 9f
.data
9:
	sys	smdate; cpathname
.text
	mov	(sp)+,r1
1:
	rts	pc

crterr1:
	clr	r0
	mov	r1,-(sp)
	clr	r1
	sys	smdate; cpathname
	mov	(sp)+,r1
	mov	r2,r0
	sys	close

crterr:
	mov	$cpathname,r1
	jsr	pc,pstr
	jsr	r5,mesg
		< -- create error\n\0>; .even
	rts	pc


/
.data
tapad:		0;0		/ first address in second file.
				/ 32-bits for xtract, 16-bits otherwise
				/ second 16 are the most significant.
tpsize:		tapesize	/ number of feet on tape.
recordln:	pereclen		/ size of a single record in inches.
ebufpt:		tapeb + dirsiz
dirlast:	-1		/ count of level of empty directories
ldt:
		</etc/last-dump-time\0>
dotname:
		<.\0>
tmpdirname:
		</tmp/temp.dtp.>
xxxxx:		<xxxxx\0>
magtape:
		</dev/r>
magt:
		<mt>
magu:
		<0\0>
.even
.bss
tapeb: . = . +tbloksiz
tapebend = .
dirfd: . = .+2
ch:	.=.+1
fli:	.=.+1
flu:	.=.+1
fls:	.=.+1
flc:	.=.+1
flv:	.=.+1
flq:	.=.+1
fld:	.=.+1
.even

seltim: .=.+4	/ all files modified after this time dumped
tfdev:	.=.+2	/ dev of temp file
tfino:	.=.+2	/ inode number of temp file
command:.=.+2
size:	.=.+2
nused:	.=.+2		/ no. of blocks used on tape
nfree:	.=.+2
catlb:	.=.+20.
narg:	.=.+2
rnarg:	.=.+2
parg:	.=.+2
fio:	.=.+2
exta:	.=.+2	/ used by gettape, xtract, taboc to simulate 32-bit
		/ tape addresses - used as an extension of ctapea
mss:	.=.+2
statb:	.=.+40.

/	incore directory structure

cde:
cpathname:	.=.+114.		/ file pathname (null terminated)
cmode:		.=.+2.		/ file access bits
cuid:		.=.+2.		/ the owner
csize:		.=.+4.		/ file size (bytes)
cmajmin = 	csize+2		/ for special files is maj/min number
ctime:		.=.+4.		/ last modified time (secs since 1970)
ctapea:		.=.+2.		/ multiple by 512 to get byte address on tape of file

/	tape directory structure

tpathname = 0		/ file pathname (null terminated)
pathnaml = 114.		/ pathname max length. must be even length.
tmode = 114.		/ file access bits
tuid =116.		/ the owner
tsize = 118.		/ file size (bytes)
ttime = 122.		/ last modified time (secs since 1970)
ttapea = 126.		/ multiple by 512 to get byte address on tape of file
dirsiz = 128.		/ must be a power of 2 and a factor of 512.
dirresvd = 15. * dirsiz
diruplim = tbloksiz - dirresvd

/	tape header entry -- ( DUMMY directory entry )

tapeheader:
nfiles:		.=.+2		/ files dumped this tape
dumptime:	.=.+4		/ dump commenced at this time
ndirblks:	.=.+2		/ number of directory blocks
		. = tapeheader + dirsiz

/	Name scratch area

namewk:	.=.+pathnaml