mirror of https://github.com/microsoft/MS-DOS.git
507 lines
14 KiB
NASM
507 lines
14 KiB
NASM
|
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
|
|||
|
|