2 ; xenix file calls for MSDOS
11 CODE SEGMENT BYTE PUBLIC 'CODE'
12 ASSUME
SS:DOSGROUP
,CS:DOSGROUP
21 TITLE XENIX
- IO system to mimic UNIX
40 i_need CurrentPDB
,WORD
41 i_need sft_addr
,DWORD ; pointer to head of table
42 i_need CURBUF
,DWORD ; pointer to current buffer
43 i_need DMAADD
,DWORD ; pointer to current dma address
48 DATA SEGMENT BYTE PUBLIC 'DATA'
53 open_jfn
DW ?
; accessed as DD
54 open_jfn_b
DW ?
; accessed as DD with above
56 open_sfoff
DW ?
; accessed as DD
57 open_sfn_b
DW ?
; accessed as DD with above
64 CODE SEGMENT BYTE PUBLIC 'CODE'
66 BREAK <Validate_path
- check to see
if there are meta characters
in path
>
69 ; Input: DS:DX is an ASCIZ path
70 ; Output: Carry set if meta-characters present or path malformed and
71 ; Zero is set if the only problem is that meta-characters
72 ; are present in the last element of the path
73 procedure Validate_path
,near
74 ASSUME
DS:NOTHING
,ES:NOTHING
79 MOV CX,0FFH ;No path seps yet
80 MOV AX,[SI] ; Get first two bytes
82 JZ validate_malformed
; NUL path
84 JNZ validate_loop
; OK so far
86 JZ validate_malformed
; NUL path (just d:)
108 JCXZ validate_malformed
;If path sep, cannot have meta yet
109 LODSB ;Look ahead one char
111 JZ validate_checktslsh
;Trailing path sep
113 JNZ validate_loop1
;Double path sep?
117 JMP SHORT validate_set_carry
120 XOR CX,CX ;Flag metas found
124 ;A bizarre case, "/" is OK, "d:/" is OK, anything else is an error
127 JZ validate_end
;Two chars, the '/' and the NUL
129 JNZ validate_malformed
;Four chars, "D:/<NUL>"
131 CMP BYTE PTR [SI+1],':'
132 JNZ validate_malformed
;Second char must be a ':'
135 OR CX,CX ;Clears carry
136 JNZ validate_ok
;No metas found, leave carry clear
146 BREAK <Access_path
- determine
if file found
>
149 ; Input: DS:DX point to a path
150 ; Output: Carry reset - outputs of GetPath
151 ; carry set - AL has error code
153 procedure Access_path
,NEAR
154 ASSUME
DS:NOTHING
,ES:NOTHING
160 MOV AL,error_file_not_found
164 MOV AL,error_path_not_found
170 BREAK <Find_free_jfn
- return a free jfn
in users PDB
>
172 ; system file table data
176 ; The system file table is two linear tables. The first table is the
177 ; DOS initialization table containing a default number of FCBs. The
178 ; first word in the table is a link to the second table, which
179 ; SYSINIT sets up, the second word is the number of FCBs in the table.
185 ; output: JNC <found>
186 ; ES:DI is pointer to free JFN
188 ; ES,DI indeterminate
190 procedure Find_free_jfn
,NEAR
191 ASSUME
DS:NOTHING
,ES:NOTHING
209 BREAK <find_free_sfn
- return a free sfn
and sf pointer
>
213 ; output: JNC <found>
214 ; ES:DI is free sf entry
217 ; ES,DI,SI indeterminate
219 ; sft_addr --> (link) count (fcbs)
220 ; links = -1 means end of list
222 procedure Find_free_sfn
,NEAR
223 ASSUME
DS:NOTHING
,ES:NOTHING
226 LES BX,sft_addr
; head of chain of tables
227 XOR SI,SI ; count of sfn
229 ; ES:BX points to table... search through table
231 CMP BX,-1 ; end of chain
233 MOV DI,sft_table
; offset to sf entry
234 MOV CX,ES:[BX].sft_count
; count of fcbs in table
237 CMP ES:BYTE PTR [BX+DI].sf_ref_count
,0h
238 JZ Find_got_sfn
; ref count is 0 -> free entry
239 ADD DI,SIZE sf_entry
; look to next entry
242 LES BX,ES:[BX].sft_link
; link to next
243 JMP SHORT Find_sfn_in_table
; look for more
257 BREAK <$Open
- open a
file handle
>
267 ; open_for_read file is opened for reading
268 ; open_for_write file is opened for writing
269 ; open_for_both file is opened for both reading and writing.
272 ; AX = error_invalid_access
273 ; = error_file_not_found
274 ; = error_access_denied
275 ; = error_too_many_open_files
279 ASSUME
DS:NOTHING
,ES:NOTHING
282 CMP AL,open_for_both
; validate access
284 error error_invalid_access
292 invoke Find_free_jfn
; scan through user's area
293 ; ES:DI is the jfn entry
296 error error_too_many_open_files
301 invoke Find_free_sfn
; get a free sft entry
302 ; ES:DI is the SFT entry that's free, SI is the sfn
313 LDS DX,DWORD PTR [open_name
]
318 JNC open_check_access
; carry set -> error
322 MOV ES,WORD PTR [CURBUF
+2] ; get buffer location
325 JNZ open_set_FCB_dev
;is a device
326 MOV AL,ES:[BX].dir_attr
327 TEST AL,attr_directory
; can't open directories
331 error error_access_denied
334 TEST AL,attr_volume_id
; can't open volume ids
336 TEST AL,attr_read_only
; check write on read only
339 JNZ open_set_FCB
; ok if creating read only file
340 CMP open_access
, open_for_read
341 JNZ open_bad_access
; writing on a read only file
342 JMP SHORT open_set_FCB
346 POP ES ;Device opens are DOSGROUP relative
349 MOV CX,11 ; copy name into FCB...
350 PUSH SI ; ES:BX is source, must change
351 MOV SI,BX ; ES:SI is source
352 MOV DI,open_sfoff
; ??:DI is dest
355 MOV ES,open_sfn_b
; ES:DI is dest
356 POP DS ; DS:SI is source
359 ; need to save attribute for the close operation
361 MOV AH,DS:[BX.dir_attr
] ; save attribute for close
362 MOV ES:[DI.sf_attr
],AH
364 ADD DI,sf_fcb
+1 ; point to name
368 CMP BYTE PTR ES:[DI-1],5
370 MOV BYTE PTR ES:[DI-1],0E5H
375 REP MOVSB ; move in parsed name
379 LES DI,DWORD PTR [open_sfoff
]
380 ADD DI,sf_fcb
; offset on fcb in sf entry
382 invoke DOOPEN
; let open code fill in blanks
384 LES DI,DWORD PTR [open_sfoff
]
385 INC ES:[DI].sf_ref_count
; reference this FCB
386 MOV AL,open_access
; stash the access
387 MOV ES:BYTE PTR [DI].sf_mode
,AL
389 MOV ES:WORD PTR [DI.sf_FCB
.fcb_RR
],AX ; beginning of file
390 MOV ES:WORD PTR [DI.sf_FCB
.fcb_RR
+2],AX
392 MOV ES:WORD PTR [DI.sf_FCB
.fcb_RECSIZ
],AX ; byte io only
393 LES DI,DWORD PTR [open_jfn
]
395 MOV ES:BYTE PTR [DI],AL ; stash sfn in PDB
396 SUB DI,PDB_jfn_table
; get jfn for user
402 BREAK <$UNLINK
- delete a
file entry>
410 ; AX = error_file_not_found
411 ; = error_access_denied
413 procedure $UNLINK
,NEAR
414 ASSUME
DS:NOTHING
,ES:NOTHING
416 JNC unlink_check_attr
421 LDS DI,DWORD PTR [CURBUF
] ; get directory entry
422 TEST DS:[BX.dir_attr
],attr_read_only
426 error error_access_denied
429 MOV BYTE PTR DS:[BX.dir_name
],0E5h ; delete dir entry
430 MOV BYTE PTR DS:[DI.BUFDIRTY
],1 ; dirty the buffer
438 MOV AL,BYTE PTR ES:[BP.DPB_drive
]
443 BREAK <$CREAT
- creat a new
file and open him for input
>
450 ; ; AX now has the handle
453 ; AX = error_access_denied
454 ; = error_path_not_found
455 ; = error_too_many_open_files
459 procedure $CREAT
,NEAR
460 ASSUME
DS:NOTHING
,ES:NOTHING
463 error error_path_not_found
468 MOV WORD PTR [CREATING
],0E5FFh
469 MOV WORD PTR [ThisFCB
+2],SS
470 MOV WORD PTR [ThisFCB
],OFFSET DOSGROUP
:AUXSTACK
-40
473 AND CL,attr_read_only
474 MOV [Cr_read_only
],CL
486 error error_access_denied
494 BREAK <$
DUP - duplicate a jfn
>
500 ; AX has the returned handle
502 ; AX = dup_invalid_handle
503 ; = dup_too_many_open_files
505 ASSUME
DS:NOTHING
,ES:NOTHING
508 JC dup_no_free_handles
513 invoke Get_sf_from_jfn
517 ; ES:DI is pointer to sf entry
518 ; DS:DI is pointer to jfn
519 INC ES:[DI].sf_ref_count
; another jfn reference...
520 MOV AL,[BX].PDB_JFN_table
; get old sfn
521 MOV [SI],AL ; store in new place
522 SUB SI,PDB_JFN_table
; get jfn
527 error error_too_many_open_files
530 error error_invalid_handle
533 BREAK <$DUP2
- force a
dup on a particular jfn
>
541 ; AX = error_invalid_handle
544 ASSUME
DS:NOTHING
,ES:NOTHING
545 XCHG BX,CX ; BX < destination jfn
548 invoke $CLOSE
; close BX
552 invoke Get_jfn_pointer
556 error error_invalid_handle
560 BREAK <$CHMOD
- change
file attributes
>
567 ; AX = error_path_not_found
568 ; AX = error_access_denied
570 procedure $CHMOD
,NEAR
571 ASSUME
DS:NOTHING
,ES:NOTHING
574 error error_invalid_function
578 AND BX,NOT attr_changeable
582 error error_access_denied
597 AND BYTE PTR ES:[BX].dir_attr
,NOT attr_changeable
598 OR BYTE PTR ES:[BX].dir_attr
,CL
599 MOV ES:[DI.BUFDIRTY
],1
605 MOV CL,BYTE PTR ES:[BX].dir_attr
606 invoke Get_user_stack
611 BREAK <$CURRENT_DIR
- dump the current directory
into user space
>
617 ; ; DS:SI is a pointer to 64 byte area that contains drive
618 ; ; current directory.
620 ; AX = error_invalid_drive
622 procedure $CURRENT_DIR
,NEAR
623 ASSUME
DS:NOTHING
,ES:NOTHING
629 ; ES:BP points to DPB. DS:SI points to user stack, unless error
636 error error_invalid_drive
639 POP DI ; where to move to
640 POP [SI.user_BX
] ; restore old BX
642 MOV [SI.user_DS
],BX ; and restore old DS
644 ; ES:BP is pointer to DPB. BX:DI is pointer to destination
646 CMP ES:[BP.dpb_current_dir
],-1
650 MOV [ATTRIB
],attr_all
655 MOV SI,BP ; ES:SI is source
657 POP DS ; DS:SI is source
658 MOV ES,BX ; ES:DI is destination
659 CMP [SI.dpb_current_dir
],0
661 MOV BYTE PTR [SI.dpb_dir_text
],0
675 BREAK <$RENAME
- move directory entries around
>
684 ; AX = error_file_not_found
685 ; = error_not_same_device
686 ; = error_access_denied
687 procedure $RENAME
,near
689 MOV WORD PTR [rename_source
],DX
690 MOV WORD PTR [rename_source
+2],DS
691 MOV WORD PTR [rename_dest
],DI
692 MOV WORD PTR [rename_dest
+2],ES
699 MOV DS,WORD PTR [CurBuf
+2]
705 PUSH WORD PTR [BX.dir_attr
]
706 PUSH WORD PTR [ThisDrv
]
710 JC rename_check_drives
714 error error_access_denied
719 error error_not_same_device
724 MOV WORD PTR [Creating
],0E5FFh
725 MOV WORD PTR [ThisFCB
+2],SS
726 MOV WORD PTR [ThisFCB
],OFFSET DOSGROUP
:AUXStack
-40
738 LDS SI,[rename_source
]
741 MOV BYTE PTR [BX],0E5h
750 BREAK <$FIND_FIRST
- find first matching xenix filename
>
757 ; ; DMA address has datablock
760 ; AX = error_file_not_found
761 ; = error_no_more_files
763 procedure $FIND_FIRST
,near
764 ASSUME
DS:NOTHING
,ES:NOTHING
768 error error_file_not_found
772 INC BYTE PTR [NoSetDir
] ; if we find a dir, don't change to it
773 MOV WORD PTR [Creating
],0E500h
780 error error_no_more_files
782 MOV DS,WORD PTR [CURBUF
+2]
784 invoke MatchAttributes
792 STOSB ; find_buf 0 = attribute in search
794 STOSB ; find_buf 1 = drive
797 MOV SI,OFFSET DOSGROUP
:NAME1
; find_buf 2 = formatted name
804 CMP BYTE PTR ES:[DI-1],5
806 MOV BYTE PTR ES:[DI-1],0E5H
814 STOSW ; find_buf 13 = LastEnt
815 MOV AX,WORD PTR [ThisDPB
]
816 STOSW ; find_buf 15 = ThisDPB
817 MOV AX,WORD PTR [ThisDPB
+2]
820 STOSW ; find_buf 19 = DirStart
822 STOSB ; find_buf 21 = attribute found
824 STOSW ; find_buf 22 = time
826 STOSW ; find_buf 24 = date
827 MOV AX,[BX].dir_size_l
828 STOSW ; find_buf 26 = low(size)
829 MOV AX,[BX].dir_size_h
830 STOSW ; find_buf 28 = high(size)
832 MOV CX,8 ; find_buf 30 = packed name
837 LOOPNZ find_loop_name
842 CMP BYTE PTR [SI]," "
860 BREAK <$FIND_NEXT
- scan for
match in directory
>
863 ; ; dma points at area returned by find_first
866 ; ; next entry is at dma
869 ; AX = error_no_more_files
871 procedure $FIND_NEXT
,near
872 ASSUME
DS:NOTHING
,ES:NOTHING
881 error error_no_more_files
883 MOV AX,[SI.find_buf_LastEnt
]
884 LES BP,[SI.find_buf_ThisDPB
]
887 MOV BX,[SI.find_buf_DirStart
]
888 MOV DL,[SI.find_buf_sattr
]
891 MOV WORD PTR [ThisDPB
],BP
892 MOV WORD PTR [ThisDPB
+2],ES