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
��������������������������������������������������������������������������������
����������������������������