home *** CD-ROM | disk | FTP | other *** search
- ; title 'dupusr - duplicate a directory entry under a new user'
- ; by Bruce R. Ratoff - first version 5/17/80
- ; modified 5/17/80 for wildcard processing
- ; modified 5/18/80 to zero drive number before making file.
- ; modified 5/18/80 to operate from originating user #
- ; modified 6/3/80 to fix problem w/ multi-extent files
- ;
- ; The purpose of this program is to create extra entries in a CP/M 2.x
- ; directory that "point to" files which were actually created in a
- ; different directory. This way, you have access to the file from
- ; both user numbers without having to keep multiple copies of the
- ; actual file itself. To create duplicate entries on drive "d" for
- ; user "x" from files which currently reside at user "y", type:
- ; A>USER y ;log in to originating user y
- ; A>DUPUSR d:filename.typ x ;create files at destination user x
- ; Note that this program will totally duplicate the directory entry in
- ; all respects (except the user number, of course). This means that
- ; both entries will show the file with the same attributes, such as
- ; "read-only" or "system". The filename.typ may contain "?" and "*".
- ;
- ; The only known hazard in the use of this program occurs when erasing
- ; one of the duplicate entries. You must type control-c immediately
- ; after erasing the entry, so that cp/m is forced to rebuild the allocation
- ; vector for that drive. This is because the erase command frees the
- ; blocks shown for the erased file without checking if they are in use
- ; elsewhere. If you didn't type control-c, the next disk write would
- ; clobber these blocks, voiding all other pointers to the file.
- ; Unfortunately this would only be apparent the next time you tried
- ; to read the file from another user number, at which time you would
- ; read garbage.
- ;
- ; Please forward all comments, suggestions and improvements to:
- ; Bruce R. Ratoff
- ; 80 Gill Lane, Apt 1B
- ; Iselin, New Jersey 08830
- ;
- ;
- ;
- bdos equ 5 ;cp/m entry point
- exit equ 0 ;cp/m exit point
- dfcb equ 5ch ;cp/m default fcb
- dbuff equ 80h ;default disk buffer
- ;
- pmessg equ 9 ;print message function
- seldsk equ 14 ;select drive function
- open equ 15 ;open file function
- close equ 16 ;close file function
- srchfst equ 17 ;search for first file match
- srchnxt equ 18 ;search for next file match
- delete equ 19 ;delete file function
- make equ 22 ;make file function
- attrib equ 30 ;set file attributes function
- gsuser equ 32 ;get/set user function
- ;
- ;
- org 100h
- begin:
- lhld bdos+1 ;set up a stack
- sphl ;at top of tpa
- mvi c,gsuser ;get our user #
- mvi e,0ffh
- call bdos
- sta ourusr ;save for later
- lda dfcb ;check for specific drive
- dcr a
- mov e,a ;set up for select disk call
- mvi c,seldsk
- inr a ;if no specified drive, skip call
- cnz bdos
- sub a ;now zap out drive spec
- sta dfcb
- mvi a,'?' ;force extent number wild
- sta dfcb+12
- lxi h,dfcb+17 ;point to originating user # in cmd line
- mvi e,0
- numlup:
- mov a,m ;get numeric (i hope) character
- inx h ;bump char pointer
- sui '0' ;remove ascii bias
- jc numdone
- cpi 10 ;check if past 9
- jnc numdone ;any invalid char ends number
- mov d,a
- mov a,e ;get accumulated number
- add a ;times two
- add a ;times four
- add e ;times five
- add a ;times ten
- add d ;plus new digit
- mov e,a ;save accumulation
- jmp numlup ;loop back for next char
- numdone:
- lda ourusr ;make sure not same as us
- cmp e
- jz badusr
- mov a,e ;get destination user number
- sta dstusr ;save it
- cpi 16 ;legal?
- jc userok
- badusr:
- lxi d,ilgusr
- mvi c,pmessg ;bitch about illegal user #
- call bdos
- jmp exit
- ilgusr:
- db 'Invalid destination user #$'
- userok:
- sub a ;zero out file count
- sta filcnt
- lxi d,dfcb ;find the first file and get its block map
- mvi c,srchfst
- call bdos
- inr a ;search successful?
- jnz gotfile ;yes, go process rest
- lxi d,nofile
- mvi c,pmessg ;say "no file"
- call bdos
- jmp exit
- nofile:
- db 'Originating file not found$'
- gotfile:
- dcr a ;compensate for inr above
- rrc ;file offset to bits 5 and 6
- rrc
- rrc
- ani 60h
- lxi h,dbuff ;point to base of buffer
- mov c,a
- mvi b,0
- dad b ;index by file offset
- push h ;save for the moment
- lxi b,filetable
- call filepoint ;get table pointer to hl
- xchg ;de now points to place in table
- lda filcnt
- inr a
- sta filcnt ;bump file count
- pop h ;hl points to directory entry
- mvi b,32
- call blkmov ;copy entry into table
- mvi c,srchnxt ;search for another entry
- lxi d,dfcb
- call bdos
- inr a ;returns 0ffh at end of search
- jnz gotfile ;got another one...go save it
- ;
- ; end of directory encountered, now process them
- ;
- lda dstusr ;set to dest user
- mov e,a
- mvi c,gsuser
- call bdos
- ;
- ; main loop to set up one duplicate entry
- ;
- makefile:
- lxi b,filetable-32 ;allow for filcnt one greater than desired
- call filepoint
- push h ;save pointer
- lxi d,dfcb ;copy next name to default fcb
- mvi b,32
- call blkmov
- sub a
- sta dfcb ;clear drive number
- lxi d,-20 ;point back to extent field
- dad d
- mvi m,'$' ;tag end of print here
- pop d ;get back pointer to start of entry
- inx d ;bump fwd to name
- mvi c,pmessg
- call bdos ;say what we're working on
- lxi h,dfcb
- lxi d,ourfcb ;copy name data to work fcb
- mvi b,14
- call blkmov
- lxi h,0
- shld ourfcb+14 ;zap frebyt, extlen
- lda ourfcb+9
- ani 7fh ;clear r/o flag for create
- sta ourfcb+9
- sub a
- sta ourfcb ;clear drive number
- lxi d,ourfcb
- mvi c,open
- call bdos ;check for existing file of same name
- inr a
- jnz makeok ;skip create if already there
- lxi d,ourfcb
- mvi c,make ;create the file
- call bdos
- inr a ;check for errors
- jnz makeok
- lxi d,makerr
- mvi c,pmessg ;say can't make file
- call bdos
- jmp exit
- makerr:
- db ', Cannot create file$'
- makeok:
- lxi h,dfcb+12 ;copy bookkeeping stuff from orig file
- lxi d,ourfcb+12
- mvi b,20
- call blkmov
- lda ourfcb+14 ;set update flag so that altered fcb
- ani 1fh ;gets written by close function
- sta ourfcb+14 ;(retain module # in low 5 bits)
- lxi d,ourfcb
- mvi c,close ;do a close to set size and block map
- call bdos
- inr a
- jnz closok ;check for errors
- lxi d,closerr
- mvi c,pmessg
- call bdos ;say close error
- jmp exit
- closerr:
- db ', Cannot close file$'
- closok:
- lda dfcb+9 ;was original file r/o?
- ora a ;set sign bit if yes
- jp nextfile ;done if no
- sta ourfcb+9 ;make our new file r/o to match
- lxi d,ourfcb
- mvi c,attrib ;do set attributes call
- call bdos
- nextfile:
- lxi h,filcnt ;point to file counter
- dcr m ;count it down
- jz exit ;exit if done
- lxi d,crlf
- mvi c,pmessg ;else do a crlf
- call bdos
- jmp makefile ;and go work on next one
- crlf:
- db 13,10,'$'
- ;
- ;
- ; subroutine to do block moves
- blkmov:
- mov a,m ;copy byte from m(hl) to m(de)
- stax d
- inx h ;bump pointers
- inx d
- dcr b ;loop for count in b
- jnz blkmov
- ret
- ;
- ;
- ; subroutine to index bc by file counter
- filepoint:
- lhld filcnt ;get file counter
- mvi h,0 ;force hi ord to 0
- dad h ;multiply by 32
- dad h
- dad h
- dad h
- dad h
- dad b ;use as index to file table
- ret
- ;
- ;
- ;
- ;
- filcnt: ds 1 ;count of files in filetable
- ourusr: ds 1 ;storage for our user number
- dstusr: ds 1 ;storage for destination user number
- ourfcb: ds 32 ;file control block for create function
- ;
- filetable equ $ ;start table here, take all avail memory
- ;
- end