mirror of
https://github.com/microsoft/MS-DOS.git
synced 2024-12-11 06:55:48 +00:00
907 lines
25 KiB
NASM
907 lines
25 KiB
NASM
|
;
|
|||
|
; xenix file calls for MSDOS
|
|||
|
;
|
|||
|
|
|||
|
INCLUDE DOSSEG.ASM
|
|||
|
|
|||
|
IFNDEF KANJI
|
|||
|
KANJI EQU 0 ;FALSE
|
|||
|
ENDIF
|
|||
|
|
|||
|
CODE SEGMENT BYTE PUBLIC 'CODE'
|
|||
|
ASSUME SS:DOSGROUP,CS:DOSGROUP
|
|||
|
|
|||
|
.xlist
|
|||
|
.xcref
|
|||
|
INCLUDE DOSSYM.ASM
|
|||
|
INCLUDE DEVSYM.ASM
|
|||
|
.cref
|
|||
|
.list
|
|||
|
|
|||
|
TITLE XENIX - IO system to mimic UNIX
|
|||
|
NAME XENIX
|
|||
|
|
|||
|
i_need NoSetDir,BYTE
|
|||
|
i_need CURDRV,BYTE
|
|||
|
i_need IOCALL,BYTE
|
|||
|
i_need IOMED,BYTE
|
|||
|
i_need IOSCNT,WORD
|
|||
|
i_need IOXAD,DWORD
|
|||
|
i_need DIRSTART,WORD
|
|||
|
i_need ATTRIB,BYTE
|
|||
|
i_need THISFCB,DWORD
|
|||
|
i_need AuxStack,BYTE
|
|||
|
i_need Creating,BYTE
|
|||
|
i_need ThisDRV,BYTE
|
|||
|
i_need NAME1,BYTE
|
|||
|
i_need LastEnt,WORD
|
|||
|
i_need ThisDPB,DWORD
|
|||
|
i_need EntLast,WORD
|
|||
|
i_need CurrentPDB,WORD
|
|||
|
i_need sft_addr,DWORD ; pointer to head of table
|
|||
|
i_need CURBUF,DWORD ; pointer to current buffer
|
|||
|
i_need DMAADD,DWORD ; pointer to current dma address
|
|||
|
|
|||
|
BREAK <Local data>
|
|||
|
|
|||
|
CODE ENDS
|
|||
|
DATA SEGMENT BYTE PUBLIC 'DATA'
|
|||
|
|
|||
|
open_name DW ?
|
|||
|
DW ?
|
|||
|
open_access DB ?
|
|||
|
open_jfn DW ? ; accessed as DD
|
|||
|
open_jfn_b DW ? ; accessed as DD with above
|
|||
|
open_sfn DW ?
|
|||
|
open_sfoff DW ? ; accessed as DD
|
|||
|
open_sfn_b DW ? ; accessed as DD with above
|
|||
|
open_devid DB ?
|
|||
|
Cr_read_only DB ?
|
|||
|
rename_source DD ?
|
|||
|
rename_dest DD ?
|
|||
|
|
|||
|
DATA ENDS
|
|||
|
CODE SEGMENT BYTE PUBLIC 'CODE'
|
|||
|
|
|||
|
BREAK <Validate_path - check to see if there are meta characters in path>
|
|||
|
|
|||
|
;
|
|||
|
; Input: DS:DX is an ASCIZ path
|
|||
|
; Output: Carry set if meta-characters present or path malformed and
|
|||
|
; Zero is set if the only problem is that meta-characters
|
|||
|
; are present in the last element of the path
|
|||
|
procedure Validate_path,near
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
PUSH AX
|
|||
|
PUSH CX
|
|||
|
PUSH SI
|
|||
|
MOV SI,DX
|
|||
|
MOV CX,0FFH ;No path seps yet
|
|||
|
MOV AX,[SI] ; Get first two bytes
|
|||
|
OR AL,AL
|
|||
|
JZ validate_malformed ; NUL path
|
|||
|
CMP AH,':'
|
|||
|
JNZ validate_loop ; OK so far
|
|||
|
CMP BYTE PTR [SI+2],0
|
|||
|
JZ validate_malformed ; NUL path (just d:)
|
|||
|
validate_loop:
|
|||
|
LODSB
|
|||
|
validate_loop1:
|
|||
|
|
|||
|
IF KANJI
|
|||
|
invoke TESTKANJ
|
|||
|
JZ NOTKANJ6
|
|||
|
INC SI
|
|||
|
JMP validate_loop
|
|||
|
|
|||
|
NOTKANJ6:
|
|||
|
ENDIF
|
|||
|
|
|||
|
OR AL,AL
|
|||
|
JZ validate_end
|
|||
|
CMP AL,"?"
|
|||
|
JZ validate_error
|
|||
|
CMP AL,"*"
|
|||
|
JZ validate_error
|
|||
|
invoke PathChrCmp
|
|||
|
JNZ validate_loop
|
|||
|
JCXZ validate_malformed ;If path sep, cannot have meta yet
|
|||
|
LODSB ;Look ahead one char
|
|||
|
OR AL,AL
|
|||
|
JZ validate_checktslsh ;Trailing path sep
|
|||
|
invoke PathChrCmp
|
|||
|
JNZ validate_loop1 ;Double path sep?
|
|||
|
validate_malformed:
|
|||
|
INC CX
|
|||
|
OR CX,CX ;Reset zero
|
|||
|
JMP SHORT validate_set_carry
|
|||
|
|
|||
|
validate_error:
|
|||
|
XOR CX,CX ;Flag metas found
|
|||
|
JMP validate_loop
|
|||
|
|
|||
|
validate_checktslsh:
|
|||
|
;A bizarre case, "/" is OK, "d:/" is OK, anything else is an error
|
|||
|
SUB SI,DX
|
|||
|
CMP SI,2
|
|||
|
JZ validate_end ;Two chars, the '/' and the NUL
|
|||
|
CMP SI,4
|
|||
|
JNZ validate_malformed ;Four chars, "D:/<NUL>"
|
|||
|
MOV SI,DX
|
|||
|
CMP BYTE PTR [SI+1],':'
|
|||
|
JNZ validate_malformed ;Second char must be a ':'
|
|||
|
|
|||
|
validate_end:
|
|||
|
OR CX,CX ;Clears carry
|
|||
|
JNZ validate_ok ;No metas found, leave carry clear
|
|||
|
validate_set_carry:
|
|||
|
STC
|
|||
|
validate_ok:
|
|||
|
POP SI
|
|||
|
POP CX
|
|||
|
POP AX
|
|||
|
return
|
|||
|
validate_path ENDP
|
|||
|
|
|||
|
BREAK <Access_path - determine if file found>
|
|||
|
|
|||
|
;
|
|||
|
; Input: DS:DX point to a path
|
|||
|
; Output: Carry reset - outputs of GetPath
|
|||
|
; carry set - AL has error code
|
|||
|
;
|
|||
|
procedure Access_path,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
CALL Validate_path
|
|||
|
JC access_no_path
|
|||
|
MOV SI,DX
|
|||
|
invoke GetPath
|
|||
|
retnc
|
|||
|
MOV AL,error_file_not_found
|
|||
|
OR CL,CL
|
|||
|
JNZ access_ret
|
|||
|
access_no_path:
|
|||
|
MOV AL,error_path_not_found
|
|||
|
access_ret:
|
|||
|
STC
|
|||
|
return
|
|||
|
access_path ENDP
|
|||
|
|
|||
|
BREAK <Find_free_jfn - return a free jfn in users PDB>
|
|||
|
;
|
|||
|
; system file table data
|
|||
|
;
|
|||
|
|
|||
|
;
|
|||
|
; The system file table is two linear tables. The first table is the
|
|||
|
; DOS initialization table containing a default number of FCBs. The
|
|||
|
; first word in the table is a link to the second table, which
|
|||
|
; SYSINIT sets up, the second word is the number of FCBs in the table.
|
|||
|
;
|
|||
|
|
|||
|
;
|
|||
|
; find_free_jfn
|
|||
|
; input: none
|
|||
|
; output: JNC <found>
|
|||
|
; ES:DI is pointer to free JFN
|
|||
|
; JC <no free jfns>
|
|||
|
; ES,DI indeterminate
|
|||
|
;
|
|||
|
procedure Find_free_jfn,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
PUSH AX
|
|||
|
PUSH CX
|
|||
|
MOV AL,0FFh
|
|||
|
MOV ES,[CurrentPDB]
|
|||
|
MOV DI,PDB_JFN_Table
|
|||
|
MOV CX,FilPerProc
|
|||
|
REPNE SCASB
|
|||
|
STC
|
|||
|
JNZ Find_jfn_ret
|
|||
|
DEC DI
|
|||
|
CLC
|
|||
|
Find_jfn_ret:
|
|||
|
POP CX
|
|||
|
POP AX
|
|||
|
return
|
|||
|
Find_free_jfn ENDP
|
|||
|
|
|||
|
BREAK <find_free_sfn - return a free sfn and sf pointer>
|
|||
|
;
|
|||
|
; find_free_sfn
|
|||
|
; input: none
|
|||
|
; output: JNC <found>
|
|||
|
; ES:DI is free sf entry
|
|||
|
; SI is sfn
|
|||
|
; JC <not found>
|
|||
|
; ES,DI,SI indeterminate
|
|||
|
;
|
|||
|
; sft_addr --> (link) count (fcbs)
|
|||
|
; links = -1 means end of list
|
|||
|
;
|
|||
|
procedure Find_free_sfn,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
PUSH BX
|
|||
|
PUSH CX
|
|||
|
LES BX,sft_addr ; head of chain of tables
|
|||
|
XOR SI,SI ; count of sfn
|
|||
|
|
|||
|
; ES:BX points to table... search through table
|
|||
|
Find_sfn_in_table:
|
|||
|
CMP BX,-1 ; end of chain
|
|||
|
JZ Find_no_free_sfns
|
|||
|
MOV DI,sft_table ; offset to sf entry
|
|||
|
MOV CX,ES:[BX].sft_count ; count of fcbs in table
|
|||
|
|
|||
|
Find_sfn:
|
|||
|
CMP ES:BYTE PTR [BX+DI].sf_ref_count,0h
|
|||
|
JZ Find_got_sfn ; ref count is 0 -> free entry
|
|||
|
ADD DI,SIZE sf_entry ; look to next entry
|
|||
|
INC SI ; bump sfn
|
|||
|
LOOP Find_sfn
|
|||
|
LES BX,ES:[BX].sft_link ; link to next
|
|||
|
JMP SHORT Find_sfn_in_table ; look for more
|
|||
|
|
|||
|
Find_no_free_sfns:
|
|||
|
STC
|
|||
|
JMP SHORT find_ret
|
|||
|
Find_got_sfn:
|
|||
|
ADD DI,BX
|
|||
|
CLC
|
|||
|
Find_ret:
|
|||
|
POP CX
|
|||
|
POP BX
|
|||
|
RET
|
|||
|
Find_free_sfn ENDP
|
|||
|
|
|||
|
BREAK <$Open - open a file handle>
|
|||
|
;
|
|||
|
; Assembler usage:
|
|||
|
; LDS DX, Name
|
|||
|
; MOV AH, Open
|
|||
|
; MOV AL, access
|
|||
|
; INT int_command
|
|||
|
;
|
|||
|
; ACCESS Function
|
|||
|
; ------ --------
|
|||
|
; open_for_read file is opened for reading
|
|||
|
; open_for_write file is opened for writing
|
|||
|
; open_for_both file is opened for both reading and writing.
|
|||
|
;
|
|||
|
; Error returns:
|
|||
|
; AX = error_invalid_access
|
|||
|
; = error_file_not_found
|
|||
|
; = error_access_denied
|
|||
|
; = error_too_many_open_files
|
|||
|
;
|
|||
|
|
|||
|
procedure $Open,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
MOV [Cr_read_only],0
|
|||
|
Open_create:
|
|||
|
CMP AL,open_for_both ; validate access
|
|||
|
JBE OPEN_get_jfn
|
|||
|
error error_invalid_access
|
|||
|
|
|||
|
OPEN_get_jfn:
|
|||
|
MOV [open_name+2],DS
|
|||
|
context DS
|
|||
|
MOV open_name,DX
|
|||
|
MOV open_access,AL
|
|||
|
|
|||
|
invoke Find_free_jfn ; scan through user's area
|
|||
|
; ES:DI is the jfn entry
|
|||
|
JNC OPEN_get_sfn
|
|||
|
OPEN_too_many:
|
|||
|
error error_too_many_open_files
|
|||
|
|
|||
|
OPEN_get_sfn:
|
|||
|
MOV OPEN_jfn_b,ES
|
|||
|
MOV OPEN_jfn,DI
|
|||
|
invoke Find_free_sfn ; get a free sft entry
|
|||
|
; ES:DI is the SFT entry that's free, SI is the sfn
|
|||
|
JC OPEN_too_many
|
|||
|
|
|||
|
OPEN_file:
|
|||
|
MOV OPEN_sfn,SI
|
|||
|
MOV OPEN_sfoff,DI
|
|||
|
MOV OPEN_sfn_b,ES
|
|||
|
;
|
|||
|
; open the file
|
|||
|
;
|
|||
|
PUSH DS
|
|||
|
LDS DX,DWORD PTR [open_name]
|
|||
|
ASSUME DS:NOTHING
|
|||
|
CALL access_path
|
|||
|
POP DS
|
|||
|
ASSUME DS:DOSGROUP
|
|||
|
JNC open_check_access ; carry set -> error
|
|||
|
transfer SYS_RET_ERR
|
|||
|
|
|||
|
open_check_access:
|
|||
|
MOV ES,WORD PTR [CURBUF+2] ; get buffer location
|
|||
|
MOV open_devid,AH
|
|||
|
TEST AH,080h
|
|||
|
JNZ open_set_FCB_dev ;is a device
|
|||
|
MOV AL,ES:[BX].dir_attr
|
|||
|
TEST AL,attr_directory ; can't open directories
|
|||
|
JZ open_try_volid
|
|||
|
|
|||
|
open_bad_access:
|
|||
|
error error_access_denied
|
|||
|
|
|||
|
open_try_volid:
|
|||
|
TEST AL,attr_volume_id ; can't open volume ids
|
|||
|
JNZ open_bad_access
|
|||
|
TEST AL,attr_read_only ; check write on read only
|
|||
|
JZ open_set_FCB
|
|||
|
CMP [Cr_read_only],0
|
|||
|
JNZ open_set_FCB ; ok if creating read only file
|
|||
|
CMP open_access, open_for_read
|
|||
|
JNZ open_bad_access ; writing on a read only file
|
|||
|
JMP SHORT open_set_FCB
|
|||
|
|
|||
|
open_set_FCB_dev:
|
|||
|
PUSH SS
|
|||
|
POP ES ;Device opens are DOSGROUP relative
|
|||
|
|
|||
|
open_set_FCB:
|
|||
|
MOV CX,11 ; copy name into FCB...
|
|||
|
PUSH SI ; ES:BX is source, must change
|
|||
|
MOV SI,BX ; ES:SI is source
|
|||
|
MOV DI,open_sfoff ; ??:DI is dest
|
|||
|
PUSH DS
|
|||
|
PUSH ES
|
|||
|
MOV ES,open_sfn_b ; ES:DI is dest
|
|||
|
POP DS ; DS:SI is source
|
|||
|
ASSUME DS:NOTHING
|
|||
|
;
|
|||
|
; need to save attribute for the close operation
|
|||
|
;
|
|||
|
MOV AH,DS:[BX.dir_attr] ; save attribute for close
|
|||
|
MOV ES:[DI.sf_attr],AH
|
|||
|
|
|||
|
ADD DI,sf_fcb+1 ; point to name
|
|||
|
|
|||
|
IF KANJI
|
|||
|
MOVSB
|
|||
|
CMP BYTE PTR ES:[DI-1],5
|
|||
|
JNZ NOTKTRAN
|
|||
|
MOV BYTE PTR ES:[DI-1],0E5H
|
|||
|
NOTKTRAN:
|
|||
|
DEC CX
|
|||
|
ENDIF
|
|||
|
|
|||
|
REP MOVSB ; move in parsed name
|
|||
|
POP DS
|
|||
|
ASSUME DS:DOSGROUP
|
|||
|
POP SI
|
|||
|
LES DI,DWORD PTR [open_sfoff]
|
|||
|
ADD DI,sf_fcb ; offset on fcb in sf entry
|
|||
|
MOV AH,open_devid
|
|||
|
invoke DOOPEN ; let open code fill in blanks
|
|||
|
context DS
|
|||
|
LES DI,DWORD PTR [open_sfoff]
|
|||
|
INC ES:[DI].sf_ref_count ; reference this FCB
|
|||
|
MOV AL,open_access ; stash the access
|
|||
|
MOV ES:BYTE PTR [DI].sf_mode,AL
|
|||
|
XOR AX,AX
|
|||
|
MOV ES:WORD PTR [DI.sf_FCB.fcb_RR],AX ; beginning of file
|
|||
|
MOV ES:WORD PTR [DI.sf_FCB.fcb_RR+2],AX
|
|||
|
INC AX
|
|||
|
MOV ES:WORD PTR [DI.sf_FCB.fcb_RECSIZ],AX ; byte io only
|
|||
|
LES DI,DWORD PTR [open_jfn]
|
|||
|
MOV AX,open_sfn
|
|||
|
MOV ES:BYTE PTR [DI],AL ; stash sfn in PDB
|
|||
|
SUB DI,PDB_jfn_table ; get jfn for user
|
|||
|
MOV AX,DI
|
|||
|
transfer SYS_RET_OK
|
|||
|
$Open ENDP
|
|||
|
|
|||
|
|
|||
|
BREAK <$UNLINK - delete a file entry>
|
|||
|
;
|
|||
|
; Assembler usage:
|
|||
|
; LDS DX, name
|
|||
|
; MOV AH, Unlink
|
|||
|
; INT 21h
|
|||
|
;
|
|||
|
; Error returns:
|
|||
|
; AX = error_file_not_found
|
|||
|
; = error_access_denied
|
|||
|
;
|
|||
|
procedure $UNLINK,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
CALL access_path
|
|||
|
JNC unlink_check_attr
|
|||
|
transfer SYS_RET_ERR
|
|||
|
|
|||
|
unlink_check_attr:
|
|||
|
JZ unlink_dir
|
|||
|
LDS DI,DWORD PTR [CURBUF] ; get directory entry
|
|||
|
TEST DS:[BX.dir_attr],attr_read_only
|
|||
|
JZ unlink_doit
|
|||
|
|
|||
|
unlink_dir:
|
|||
|
error error_access_denied
|
|||
|
|
|||
|
unlink_doit:
|
|||
|
MOV BYTE PTR DS:[BX.dir_name],0E5h ; delete dir entry
|
|||
|
MOV BYTE PTR DS:[DI.BUFDIRTY],1 ; dirty the buffer
|
|||
|
LODSW
|
|||
|
MOV BX,AX
|
|||
|
AND BX,0FFFh
|
|||
|
context DS
|
|||
|
JZ unlink_flush
|
|||
|
invoke RELEASE
|
|||
|
unlink_flush:
|
|||
|
MOV AL,BYTE PTR ES:[BP.DPB_drive]
|
|||
|
invoke FLUSHBUF
|
|||
|
transfer SYS_RET_OK
|
|||
|
$UNLINK ENDP
|
|||
|
|
|||
|
BREAK <$CREAT - creat a new file and open him for input>
|
|||
|
;
|
|||
|
; Assembler usage:
|
|||
|
; LDS DX, name
|
|||
|
; MOV AH, Creat
|
|||
|
; MOV CX, access
|
|||
|
; INT 21h
|
|||
|
; ; AX now has the handle
|
|||
|
;
|
|||
|
; Error returns:
|
|||
|
; AX = error_access_denied
|
|||
|
; = error_path_not_found
|
|||
|
; = error_too_many_open_files
|
|||
|
;
|
|||
|
|
|||
|
|
|||
|
procedure $CREAT,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
CALL Validate_path
|
|||
|
JNC unlink_do_make
|
|||
|
error error_path_not_found
|
|||
|
unlink_do_make:
|
|||
|
PUSH DX
|
|||
|
PUSH DS
|
|||
|
context DS
|
|||
|
MOV WORD PTR [CREATING],0E5FFh
|
|||
|
MOV WORD PTR [ThisFCB+2],SS
|
|||
|
MOV WORD PTR [ThisFCB],OFFSET DOSGROUP:AUXSTACK-40
|
|||
|
MOV SI,DX
|
|||
|
MOV AL,CL
|
|||
|
AND CL,attr_read_only
|
|||
|
MOV [Cr_read_only],CL
|
|||
|
POP DS
|
|||
|
PUSH DS
|
|||
|
ASSUME DS:NOTHING
|
|||
|
invoke MakeNode
|
|||
|
POP DS
|
|||
|
POP DX
|
|||
|
OR AL,AL
|
|||
|
JZ creat_open
|
|||
|
CMP AL,3
|
|||
|
JZ creat_open
|
|||
|
creat_no_access:
|
|||
|
error error_access_denied
|
|||
|
creat_open:
|
|||
|
MOV AL,open_for_both
|
|||
|
JMP Open_create
|
|||
|
|
|||
|
$CREAT ENDP
|
|||
|
|
|||
|
|
|||
|
BREAK <$DUP - duplicate a jfn>
|
|||
|
;
|
|||
|
; Assembler usage:
|
|||
|
; MOV BX, fh
|
|||
|
; MOV AH, Dup
|
|||
|
; INT int_command
|
|||
|
; AX has the returned handle
|
|||
|
; Errors:
|
|||
|
; AX = dup_invalid_handle
|
|||
|
; = dup_too_many_open_files
|
|||
|
procedure $DUP,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
context DS
|
|||
|
invoke Find_free_jfn
|
|||
|
JC dup_no_free_handles
|
|||
|
|
|||
|
dup_force:
|
|||
|
PUSH ES
|
|||
|
PUSH DI
|
|||
|
invoke Get_sf_from_jfn
|
|||
|
POP SI
|
|||
|
POP DS
|
|||
|
JC dup_bad_handle
|
|||
|
; ES:DI is pointer to sf entry
|
|||
|
; DS:DI is pointer to jfn
|
|||
|
INC ES:[DI].sf_ref_count ; another jfn reference...
|
|||
|
MOV AL,[BX].PDB_JFN_table ; get old sfn
|
|||
|
MOV [SI],AL ; store in new place
|
|||
|
SUB SI,PDB_JFN_table ; get jfn
|
|||
|
MOV AX,SI
|
|||
|
transfer SYS_RET_OK
|
|||
|
|
|||
|
dup_no_free_handles:
|
|||
|
error error_too_many_open_files
|
|||
|
|
|||
|
dup_bad_handle:
|
|||
|
error error_invalid_handle
|
|||
|
$DUP ENDP
|
|||
|
|
|||
|
BREAK <$DUP2 - force a dup on a particular jfn>
|
|||
|
;
|
|||
|
; Assembler usage:
|
|||
|
; MOV BX, fh
|
|||
|
; MOV CX, newfh
|
|||
|
; MOV AH, Dup2
|
|||
|
; INT int_command
|
|||
|
; Error returns:
|
|||
|
; AX = error_invalid_handle
|
|||
|
;
|
|||
|
procedure $DUP2,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
XCHG BX,CX ; BX < destination jfn
|
|||
|
PUSH BX
|
|||
|
PUSH CX
|
|||
|
invoke $CLOSE ; close BX
|
|||
|
context DS
|
|||
|
POP CX
|
|||
|
POP BX
|
|||
|
invoke Get_jfn_pointer
|
|||
|
XCHG BX,CX
|
|||
|
JNC dup_force
|
|||
|
lseek_bad_handle:
|
|||
|
error error_invalid_handle
|
|||
|
$DUP2 ENDP
|
|||
|
|
|||
|
|
|||
|
BREAK <$CHMOD - change file attributes>
|
|||
|
;
|
|||
|
; Assembler usage:
|
|||
|
; LDS DX, name
|
|||
|
; MOV CX, attributes
|
|||
|
; INT 21h
|
|||
|
; Error returns:
|
|||
|
; AX = error_path_not_found
|
|||
|
; AX = error_access_denied
|
|||
|
;
|
|||
|
procedure $CHMOD,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
CMP AL,1
|
|||
|
JBE chmod_save
|
|||
|
error error_invalid_function
|
|||
|
chmod_save:
|
|||
|
JB chmod_try_file
|
|||
|
MOV BX,CX
|
|||
|
AND BX,NOT attr_changeable
|
|||
|
JZ chmod_try_file
|
|||
|
|
|||
|
chmod_bad:
|
|||
|
error error_access_denied
|
|||
|
|
|||
|
chmod_bye:
|
|||
|
transfer SYS_RET_ERR
|
|||
|
chmod_try_file:
|
|||
|
PUSH CX
|
|||
|
PUSH AX
|
|||
|
CALL access_path
|
|||
|
POP DX
|
|||
|
POP CX
|
|||
|
JC chmod_bye
|
|||
|
LES DI,[CURBUF]
|
|||
|
context DS
|
|||
|
OR DL,DL
|
|||
|
JZ chmod_fetch
|
|||
|
AND BYTE PTR ES:[BX].dir_attr,NOT attr_changeable
|
|||
|
OR BYTE PTR ES:[BX].dir_attr,CL
|
|||
|
MOV ES:[DI.BUFDIRTY],1
|
|||
|
MOV AL,-1
|
|||
|
invoke FlushBuf
|
|||
|
transfer SYS_RET_OK
|
|||
|
chmod_fetch:
|
|||
|
XOR CX,CX
|
|||
|
MOV CL,BYTE PTR ES:[BX].dir_attr
|
|||
|
invoke Get_user_stack
|
|||
|
MOV [SI.user_CX],CX
|
|||
|
transfer SYS_RET_OK
|
|||
|
$chmod ENDP
|
|||
|
|
|||
|
BREAK <$CURRENT_DIR - dump the current directory into user space>
|
|||
|
;
|
|||
|
; Assembler usage:
|
|||
|
; LDS SI,area
|
|||
|
; MOV DL,drive
|
|||
|
; INT 21h
|
|||
|
; ; DS:SI is a pointer to 64 byte area that contains drive
|
|||
|
; ; current directory.
|
|||
|
; Error returns:
|
|||
|
; AX = error_invalid_drive
|
|||
|
;
|
|||
|
procedure $CURRENT_DIR,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
PUSH DS
|
|||
|
PUSH BX
|
|||
|
PUSH SI
|
|||
|
invoke $get_DPB
|
|||
|
;
|
|||
|
; ES:BP points to DPB. DS:SI points to user stack, unless error
|
|||
|
;
|
|||
|
CMP AL,0FFh
|
|||
|
JNZ current_copy
|
|||
|
POP AX ; Clean Stack
|
|||
|
POP AX
|
|||
|
POP AX
|
|||
|
error error_invalid_drive
|
|||
|
|
|||
|
current_copy:
|
|||
|
POP DI ; where to move to
|
|||
|
POP [SI.user_BX] ; restore old BX
|
|||
|
POP BX
|
|||
|
MOV [SI.user_DS],BX ; and restore old DS
|
|||
|
;
|
|||
|
; ES:BP is pointer to DPB. BX:DI is pointer to destination
|
|||
|
;
|
|||
|
CMP ES:[BP.dpb_current_dir],-1
|
|||
|
JNZ current_ok
|
|||
|
PUSH BX
|
|||
|
PUSH DI
|
|||
|
MOV [ATTRIB],attr_all
|
|||
|
invoke GETCURRDIR
|
|||
|
POP DI
|
|||
|
POP BX
|
|||
|
current_ok:
|
|||
|
MOV SI,BP ; ES:SI is source
|
|||
|
PUSH ES
|
|||
|
POP DS ; DS:SI is source
|
|||
|
MOV ES,BX ; ES:DI is destination
|
|||
|
CMP [SI.dpb_current_dir],0
|
|||
|
JNZ current_move
|
|||
|
MOV BYTE PTR [SI.dpb_dir_text],0
|
|||
|
|
|||
|
current_move:
|
|||
|
ADD SI,dpb_dir_text
|
|||
|
MOV CX,DIRSTRLEN
|
|||
|
current_loop:
|
|||
|
LODSB
|
|||
|
STOSB
|
|||
|
OR AL,AL
|
|||
|
LOOPNZ current_loop
|
|||
|
transfer SYS_RET_OK
|
|||
|
$CURRENT_DIR ENDP
|
|||
|
|
|||
|
|
|||
|
BREAK <$RENAME - move directory entries around>
|
|||
|
;
|
|||
|
; Assembler usage:
|
|||
|
; LDS DX, source
|
|||
|
; LES DI, dest
|
|||
|
; MOV AH, Rename
|
|||
|
; INT 21h
|
|||
|
;
|
|||
|
; Error returns:
|
|||
|
; AX = error_file_not_found
|
|||
|
; = error_not_same_device
|
|||
|
; = error_access_denied
|
|||
|
procedure $RENAME,near
|
|||
|
|
|||
|
MOV WORD PTR [rename_source],DX
|
|||
|
MOV WORD PTR [rename_source+2],DS
|
|||
|
MOV WORD PTR [rename_dest],DI
|
|||
|
MOV WORD PTR [rename_dest+2],ES
|
|||
|
CALL Access_path
|
|||
|
JNC rename_check_dir
|
|||
|
transfer SYS_RET_ERR
|
|||
|
|
|||
|
rename_check_dir:
|
|||
|
JZ rename_no_access
|
|||
|
MOV DS,WORD PTR [CurBuf+2]
|
|||
|
PUSH [BX.dir_date]
|
|||
|
PUSH [BX.dir_first]
|
|||
|
PUSH [BX.dir_size_h]
|
|||
|
PUSH [BX.dir_size_l]
|
|||
|
PUSH [BX.dir_time]
|
|||
|
PUSH WORD PTR [BX.dir_attr]
|
|||
|
PUSH WORD PTR [ThisDrv]
|
|||
|
LDS SI,[rename_dest]
|
|||
|
invoke GetPath
|
|||
|
POP AX
|
|||
|
JC rename_check_drives
|
|||
|
rename_bad_access:
|
|||
|
ADD SP,12
|
|||
|
rename_no_access:
|
|||
|
error error_access_denied
|
|||
|
rename_check_drives:
|
|||
|
CMP AL,[ThisDrv]
|
|||
|
JZ rename_create
|
|||
|
ADD SP,12
|
|||
|
error error_not_same_device
|
|||
|
rename_create:
|
|||
|
LDS SI,[rename_dest]
|
|||
|
POP AX
|
|||
|
PUSH AX
|
|||
|
MOV WORD PTR [Creating],0E5FFh
|
|||
|
MOV WORD PTR [ThisFCB+2],SS
|
|||
|
MOV WORD PTR [ThisFCB],OFFSET DOSGROUP:AUXStack-40
|
|||
|
invoke MakeNode
|
|||
|
JC rename_bad_access
|
|||
|
LDS SI,[CurBuf]
|
|||
|
POP AX
|
|||
|
MOV [BX.dir_attr],AL
|
|||
|
POP [BX.dir_time]
|
|||
|
POP [BX.dir_size_l]
|
|||
|
POP [BX.dir_size_h]
|
|||
|
POP [BX.dir_first]
|
|||
|
POP [BX.dir_date]
|
|||
|
MOV [SI.BUFDIRTY],1
|
|||
|
LDS SI,[rename_source]
|
|||
|
invoke GetPath
|
|||
|
LDS SI,[CurBuf]
|
|||
|
MOV BYTE PTR [BX],0E5h
|
|||
|
MOV [SI.BUFDIRTY],1
|
|||
|
context DS
|
|||
|
MOV AL,0FFh
|
|||
|
invoke FlushBuf
|
|||
|
transfer SYS_RET_OK
|
|||
|
|
|||
|
$RENAME ENDP
|
|||
|
|
|||
|
BREAK <$FIND_FIRST - find first matching xenix filename>
|
|||
|
;
|
|||
|
; Assembler usage:
|
|||
|
; MOV AH, FindFirst
|
|||
|
; LDS DX, name
|
|||
|
; MOV CX, attr
|
|||
|
; INT 21h
|
|||
|
; ; DMA address has datablock
|
|||
|
;
|
|||
|
; Error Returns:
|
|||
|
; AX = error_file_not_found
|
|||
|
; = error_no_more_files
|
|||
|
;
|
|||
|
procedure $FIND_FIRST,near
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
CALL Validate_path
|
|||
|
JNC find_get
|
|||
|
JZ find_get
|
|||
|
error error_file_not_found
|
|||
|
find_get:
|
|||
|
MOV SI,DX
|
|||
|
PUSH CX
|
|||
|
INC BYTE PTR [NoSetDir] ; if we find a dir, don't change to it
|
|||
|
MOV WORD PTR [Creating],0E500h
|
|||
|
CALL GetPath
|
|||
|
POP CX
|
|||
|
MOV [Attrib],CL
|
|||
|
find_check:
|
|||
|
JNC find_check_attr
|
|||
|
find_no_more:
|
|||
|
error error_no_more_files
|
|||
|
find_check_attr:
|
|||
|
MOV DS,WORD PTR [CURBUF+2]
|
|||
|
MOV CH,[BX.dir_attr]
|
|||
|
invoke MatchAttributes
|
|||
|
JZ found_it
|
|||
|
PUSH [LastEnt]
|
|||
|
MOV BX,[DirStart]
|
|||
|
JMP find_it_next
|
|||
|
found_it:
|
|||
|
LES DI,[DMAADD]
|
|||
|
MOV AL,[Attrib]
|
|||
|
STOSB ; find_buf 0 = attribute in search
|
|||
|
MOV AL,[ThisDrv]
|
|||
|
STOSB ; find_buf 1 = drive
|
|||
|
MOV CX,11
|
|||
|
PUSH BX
|
|||
|
MOV SI,OFFSET DOSGROUP:NAME1; find_buf 2 = formatted name
|
|||
|
PUSH DS
|
|||
|
PUSH SS
|
|||
|
POP DS
|
|||
|
|
|||
|
IF KANJI
|
|||
|
MOVSB
|
|||
|
CMP BYTE PTR ES:[DI-1],5
|
|||
|
JNZ NOTKANJB
|
|||
|
MOV BYTE PTR ES:[DI-1],0E5H
|
|||
|
NOTKANJB:
|
|||
|
DEC CX
|
|||
|
ENDIF
|
|||
|
|
|||
|
REP MOVSB
|
|||
|
POP DS
|
|||
|
MOV AX,[LastEnt]
|
|||
|
STOSW ; find_buf 13 = LastEnt
|
|||
|
MOV AX,WORD PTR [ThisDPB]
|
|||
|
STOSW ; find_buf 15 = ThisDPB
|
|||
|
MOV AX,WORD PTR [ThisDPB+2]
|
|||
|
STOSW
|
|||
|
MOV AX,[DirStart]
|
|||
|
STOSW ; find_buf 19 = DirStart
|
|||
|
MOV AL,[BX].dir_attr
|
|||
|
STOSB ; find_buf 21 = attribute found
|
|||
|
MOV AX,[BX].dir_time
|
|||
|
STOSW ; find_buf 22 = time
|
|||
|
MOV AX,[BX].dir_date
|
|||
|
STOSW ; find_buf 24 = date
|
|||
|
MOV AX,[BX].dir_size_l
|
|||
|
STOSW ; find_buf 26 = low(size)
|
|||
|
MOV AX,[BX].dir_size_h
|
|||
|
STOSW ; find_buf 28 = high(size)
|
|||
|
POP SI
|
|||
|
MOV CX,8 ; find_buf 30 = packed name
|
|||
|
find_loop_name:
|
|||
|
LODSB
|
|||
|
STOSB
|
|||
|
CMP AL," "
|
|||
|
LOOPNZ find_loop_name
|
|||
|
JNZ find_check_dot
|
|||
|
DEC DI
|
|||
|
find_check_dot:
|
|||
|
ADD SI,CX
|
|||
|
CMP BYTE PTR [SI]," "
|
|||
|
JZ find_done
|
|||
|
MOV AL,"."
|
|||
|
STOSB
|
|||
|
MOV CX,3
|
|||
|
find_loop_ext:
|
|||
|
LODSB
|
|||
|
STOSB
|
|||
|
CMP AL," "
|
|||
|
LOOPNZ find_loop_ext
|
|||
|
JNZ find_done
|
|||
|
DEC DI
|
|||
|
find_done:
|
|||
|
XOR AL,AL
|
|||
|
STOSB
|
|||
|
transfer SYS_RET_OK
|
|||
|
$FIND_FIRST ENDP
|
|||
|
|
|||
|
BREAK <$FIND_NEXT - scan for match in directory>
|
|||
|
;
|
|||
|
; Assembler usage:
|
|||
|
; ; dma points at area returned by find_first
|
|||
|
; MOV AH, findnext
|
|||
|
; INT 21h
|
|||
|
; ; next entry is at dma
|
|||
|
;
|
|||
|
; Error Returns:
|
|||
|
; AX = error_no_more_files
|
|||
|
;
|
|||
|
procedure $FIND_NEXT,near
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
LDS SI,[DMAADD]
|
|||
|
MOV DX,SI
|
|||
|
INC DX
|
|||
|
PUSH SI
|
|||
|
invoke MOVNAMENOSET
|
|||
|
POP SI
|
|||
|
JNC find_load
|
|||
|
findnext_no_more:
|
|||
|
error error_no_more_files
|
|||
|
find_load:
|
|||
|
MOV AX,[SI.find_buf_LastEnt]
|
|||
|
LES BP,[SI.find_buf_ThisDPB]
|
|||
|
OR AX,AX
|
|||
|
JS findnext_no_more
|
|||
|
MOV BX,[SI.find_buf_DirStart]
|
|||
|
MOV DL,[SI.find_buf_sattr]
|
|||
|
MOV [Attrib],DL
|
|||
|
PUSH AX
|
|||
|
MOV WORD PTR [ThisDPB],BP
|
|||
|
MOV WORD PTR [ThisDPB+2],ES
|
|||
|
find_it_next:
|
|||
|
invoke SetDirSrch
|
|||
|
ASSUME DS:DOSGROUP
|
|||
|
POP AX
|
|||
|
MOV [ENTLAST],-1
|
|||
|
invoke GetEnt
|
|||
|
invoke NextEnt
|
|||
|
JMP find_check
|
|||
|
$find_next ENDP
|
|||
|
|
|||
|
do_ext
|
|||
|
|
|||
|
CODE ENDS
|
|||
|
END
|
|||
|
|