MS-DOS/v2.0/source/DIRCALL.ASM

507 lines
14 KiB
NASM
Raw Normal View History

1983-08-13 00:53:34 +00:00
TITLE DIRCALL - Directory manipulation internal calls
NAME DIRCALL
; $MKDIR
; $CHDIR
; $RMDIR
.xlist
INCLUDE DOSSEG.ASM
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list
ifndef Kanji
Kanji equ 0
endif
i_need AUXSTACK,BYTE
i_need NoSetDir,BYTE
i_need CURBUF, DWORD
i_need DIRSTART,WORD
i_need THISDPB,DWORD
i_need NAME1,BYTE
i_need LASTENT,WORD
i_need ATTRIB,BYTE
i_need THISFCB,DWORD
i_need AUXSTACK,BYTE
i_need CREATING,BYTE
i_need DRIVESPEC,BYTE
i_need ROOTSTART,BYTE
i_need SWITCH_CHARACTER,BYTE
extrn sys_ret_ok:near,sys_ret_err:near
; XENIX CALLS
BREAK <$MkDir - Make a directory entry>
MKNERRJ: JMP MKNERR
NODEEXISTSJ: JMP NODEEXISTS
procedure $MKDIR,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX Points to asciz name
; Function:
; Make a new directory
; Returns:
; STD XENIX Return
; AX = mkdir_path_not_found if path bad
; AX = mkdir_access_denied If
; Directory cannot be created
; Node already exists
; Device name given
; Disk or directory(root) full
invoke validate_path
JC MKNERRJ
MOV SI,DX
MOV WORD PTR [THISFCB+2],SS
MOV WORD PTR [THISFCB],OFFSET DOSGROUP:AUXSTACK-40 ; Scratch space
MOV AL,attr_directory
MOV WORD PTR [CREATING],0E500h
invoke MAKENODE
ASSUME DS:DOSGROUP
MOV AL,mkdir_path_not_found
JC MKNERRJ
JNZ NODEEXISTSJ
LDS DI,[CURBUF]
ASSUME DS:NOTHING
SUB SI,DI
PUSH SI ; Pointer to fcb_FIRCLUS
PUSH [DI.BUFSECNO] ; Sector of new node
PUSH SS
POP DS
ASSUME DS:DOSGROUP
PUSH [DIRSTART] ; Parent for .. entry
XOR AX,AX
MOV [DIRSTART],AX ; Null directory
invoke NEWDIR
JC NODEEXISTSPOPDEL ; No room
invoke GETENT ; First entry
LES DI,[CURBUF]
MOV ES:[DI.BUFDIRTY],1
ADD DI,BUFINSIZ ; Point at buffer
MOV AX,202EH ; ". "
STOSW
MOV DX,[DIRSTART] ; Point at itself
invoke SETDOTENT
MOV AX,2E2EH ; ".."
STOSW
POP DX ; Parent
invoke SETDOTENT
LES BP,[THISDPB]
POP DX ; Entry sector
XOR AL,AL ; Pre read
invoke GETBUFFR
MOV DX,[DIRSTART]
LDS DI,[CURBUF]
ASSUME DS:NOTHING
ZAPENT:
POP SI ; fcb_Firclus pointer
ADD SI,DI
MOV [SI],DX
XOR DX,DX
MOV [SI+2],DX
MOV [SI+4],DX
DIRUP:
MOV [DI.BUFDIRTY],1
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV AL,ES:[BP.dpb_drive]
invoke FLUSHBUF
SYS_RET_OKJ:
JMP SYS_RET_OK
NODEEXISTSPOPDEL:
POP DX ; Parent
POP DX ; Entry sector
LES BP,[THISDPB]
XOR AL,AL ; Pre read
invoke GETBUFFR
LDS DI,[CURBUF]
ASSUME DS:NOTHING
POP SI ; dir_first pointer
ADD SI,DI
SUB SI,dir_first ; Point back to start of dir entry
MOV BYTE PTR [SI],0E5H ; Free the entry
CALL DIRUP
NODEEXISTS:
MOV AL,mkdir_access_denied
MKNERR:
JMP SYS_RET_ERR
$MKDIR ENDP
BREAK <$ChDir -- Change current directory on a drive>
procedure $CHDIR,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX Points to asciz name
; Function:
; Change current directory
; Returns:
; STD XENIX Return
; AX = chdir_path_not_found if error
invoke validate_path
JC PathTooLong
PUSH DS
PUSH DX
MOV SI,DX
invoke GETPATH
JC PATHNOGOOD
JNZ PATHNOGOOD
ASSUME DS:DOSGROUP
MOV AX,[DIRSTART]
MOV BX,AX
XCHG BX,ES:[BP.dpb_current_dir]
OR AX,AX
POP SI
POP DS
ASSUME DS:NOTHING
JZ SYS_RET_OKJ
MOV DI,BP
ADD DI,dpb_dir_text
MOV DX,DI
CMP [DRIVESPEC],0
JZ NODRIVESPEC
INC SI
INC SI
NODRIVESPEC:
MOV CX,SI
CMP [ROOTSTART],0
JZ NOTROOTPATH
INC SI
INC CX
JMP SHORT COPYTHESTRINGBXZ
NOTROOTPATH:
OR BX,BX ; Previous path root?
JZ COPYTHESTRING ; Yes
XOR BX,BX
ENDLOOP:
CMP BYTE PTR ES:[DI],0
JZ PATHEND
INC DI
INC BX
JMP SHORT ENDLOOP
PATHEND:
MOV AL,'/'
CMP AL,[switch_character]
JNZ SLASHOK
MOV AL,'\' ; Use the alternate character
SLASHOK:
STOSB
INC BX
JMP SHORT CHECK_LEN
PATHNOGOOD:
POP AX
POP AX
PATHTOOLONG:
error error_path_not_found
ASSUME DS:NOTHING
INCBXCHK:
INC BX
BXCHK:
CMP BX,DIRSTRLEN
return
COPYTHESTRINGBXZ:
XOR BX,BX
COPYTHESTRING:
LODSB
OR AL,AL
JNZ FOOB
JMP CPSTDONE
FOOB:
CMP AL,'.'
JZ SEEDOT
CALL COPYELEM
CHECK_LEN:
CMP BX,DIRSTRLEN
JB COPYTHESTRING
MOV AL,ES:[DI-1]
invoke PATHCHRCMP
JNZ OK_DI
DEC DI
OK_DI:
XOR AL,AL
STOSB ; Correctly terminate the path
MOV ES:[BP.dpb_current_dir],-1 ; Force re-validation
JMP SHORT PATHTOOLONG
SEEDOT:
LODSB
OR AL,AL ; Check for null
JZ CPSTDONEDEC
CMP AL,'.'
JNZ COPYTHESTRING ; eat ./
CALL DELELMES ; have ..
LODSB ; eat the /
OR AL,AL ; Check for null
JZ CPSTDONEDEC
JMP SHORT COPYTHESTRING
; Copy one element from DS:SI to ES:DI include trailing / not trailing null
; LODSB has already been done
COPYELEM:
PUSH DI ; Save in case too long
PUSH CX
MOV CX,800h ; length of filename
MOV AH,'.' ; char to stop on
CALL CopyPiece ; go for it!
CALL BXCHK ; did we go over?
JAE POPCXDI ; yep, go home
CMP AH,AL ; did we stop on .?
JZ CopyExt ; yes, go copy ext
OR AL,AL ; did we end on nul?
JZ DECSIRet ; yes, bye
CopyPathEnd:
STOSB ; save the path char
CALL INCBXCHK ; was there room for it?
JAE POPCXDI ; Nope
INC SI ; guard against following dec
DECSIRET:
DEC SI ; point back at null
POP CX
POP AX ; toss away saved DI
return
POPCXDI:
POP CX ; restore
POP DI ; point back...
return
CopyExt:
STOSB ; save the dot
CALL INCBXCHK ; room?
JAE POPCXDI ; nope.
LODSB ; get next char
XOR AH,AH ; NUL here
MOV CX,300h ; at most 3 chars
CALL CopyPiece ; go copy it
CALL BXCHK ; did we go over
JAE POPCXDI ; yep
OR AL,AL ; sucessful end?
JZ DECSIRET ; yes
JMP CopyPathEnd ; go stash path char
DELELMES:
; Delete one path element from ES:DI
DEC DI ; the '/'
DEC BX
IF KANJI
PUSH AX
PUSH CX
PUSH DI
PUSH DX
MOV CX,DI
MOV DI,DX
DELLOOP:
CMP DI,CX
JZ GOTDELE
MOV AL,ES:[DI]
INC DI
invoke TESTKANJ
JZ NOTKANJ11
INC DI
JMP DELLOOP
NOTKANJ11:
invoke PATHCHRCMP
JNZ DELLOOP
MOV DX,DI ; Point to char after '/'
JMP DELLOOP
GOTDELE:
MOV DI,DX
POP DX
POP AX ; Initial DI
SUB AX,DI ; Distance moved
SUB BX,AX ; Set correct BX
POP CX
POP AX
return
ELSE
DELLOOP:
CMP DI,DX
retz
PUSH AX
MOV AL,ES:[DI-1]
invoke PATHCHRCMP
POP AX
retz
DEC DI
DEC BX
JMP SHORT DELLOOP
ENDIF
CPSTDONEDEC:
DEC DI ; Back up over trailing /
CPSTDONE:
STOSB ; The NUL
JMP SYS_RET_OK
; copy a piece CH chars max until the char in AH (or path or NUL)
CopyPiece:
STOSB ; store the character
INC CL ; moved a byte
CALL INCBXCHK ; room enough?
JAE CopyPieceRet ; no, pop CX and DI
OR AL,AL ; end of string?
JZ CopyPieceRet ; yes, dec si and return
IF KANJI
CALL TestKanj ; was it kanji?
JZ NotKanj ; nope
MOVSB ; move the next byte
CALL INCBXCHK ; room for it?
JAE CopyPieceRet ; nope
INC CL ; moved a byte
NotKanj:
ENDIF
CMP CL,CH ; move too many?
JBE CopyPieceNext ; nope
IF KANJI
CALL TestKanj ; was the last byte kanji
JZ NotKanj2 ; no only single byte backup
DEC DI ; back up a char
DEC BX
NotKanj2:
ENDIF
DEC DI ; back up a char
DEC BX
CopyPieceNext:
LODSB ; get next character
invoke PathChrCmp ; end of road?
JZ CopyPieceRet ; yep, return and don't dec SI
CMP AL,AH ; end of filename?
JNZ CopyPiece ; go do name
CopyPieceRet:
return ; bye!
$CHDIR ENDP
BREAK <$RmDir -- Remove a directory>
NOPATHJ: JMP NOPATH
procedure $RMDIR,NEAR ; System call 47
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX Points to asciz name
; Function:
; Delete directory if empty
; Returns:
; STD XENIX Return
; AX = rmdir_path_not_found If path bad
; AX = rmdir_access_denied If
; Directory not empty
; Path not directory
; Root directory specified
; Directory malformed (. and .. not first two entries)
; AX = rmdir_current_directory
invoke Validate_path
JC NoPathJ
MOV SI,DX
invoke GETPATH
JC NOPATHJ
ASSUME DS:DOSGROUP
JNZ NOTDIRPATH
MOV DI,[DIRSTART]
OR DI,DI
JZ NOTDIRPATH
MOV CX,ES:[BP.dpb_current_dir]
CMP CX,-1
JNZ rmdir_current_dir_check
invoke GetCurrDir
invoke Get_user_stack
MOV DX,[SI.user_DX]
MOV DS,[SI.user_DS]
JMP $RMDIR
NOTDIRPATHPOP:
POP AX
POP AX
NOTDIRPATH:
error error_access_denied
rmdir_current_dir_check:
CMP DI,CX
JNZ rmdir_get_buf
error error_current_directory
rmdir_get_buf:
LDS DI,[CURBUF]
ASSUME DS:NOTHING
SUB BX,DI
PUSH BX ; Save entry pointer
PUSH [DI.BUFSECNO] ; Save sector number
PUSH SS
POP DS
ASSUME DS:DOSGROUP
PUSH SS
POP ES
MOV DI,OFFSET DOSGROUP:NAME1
MOV AL,'?'
MOV CX,11
REP STOSB
XOR AL,AL
STOSB
invoke STARTSRCH
invoke GETENTRY
MOV DS,WORD PTR [CURBUF+2]
ASSUME DS:NOTHING
MOV SI,BX
LODSW
CMP AX,(' ' SHL 8) OR '.'
JNZ NOTDIRPATHPOP
ADD SI,32-2
LODSW
CMP AX,('.' SHL 8) OR '.'
JNZ NOTDIRPATHPOP
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV [LASTENT],2 ; Skip . and ..
invoke GETENTRY
MOV [ATTRIB],attr_directory+attr_hidden+attr_system
invoke SRCH
JNC NOTDIRPATHPOP
LES BP,[THISDPB]
MOV BX,[DIRSTART]
invoke RELEASE
POP DX
XOR AL,AL
invoke GETBUFFR
LDS DI,[CURBUF]
ASSUME DS:NOTHING
POP BX
ADD BX,DI
MOV BYTE PTR [BX],0E5H ; Free the entry
JMP DIRUP
NOPATH:
error error_path_not_found
$RMDIR ENDP
do_ext
CODE ENDS
END