]>
wirehaze git hosting - MS-DOS.git/blob - v4.0/src/DOS/CLOSE.ASM
1 ; SCCSID = @(#)close.asm 1.1 85/04/09
2 TITLE DOS_CLOSE
/COMMIT
- Internal SFT close
and commit
call for MSDOS
4 ; Internal Close and Commit calls to close a local or NET SFT.
13 ; AN000 version 4.00 Jan. 1988
14 ; A005 PTM 3718 --- lost clusters when fastopen installed
15 ; A011 PTM 4766 --- C2 fastopen problem
18 ; get the appropriate segment definitions
23 CODE SEGMENT BYTE PUBLIC 'CODE'
24 ASSUME
SS:DOSGROUP
,CS:DOSGROUP
39 i_need EXTERR_LOCUS
,BYTE
44 i_need HIGH_SECTOR
,WORD ;F.C. >32mb
45 i_need OLD_FIRSTCLUS
,WORD ;F.O. >32mb
52 Break <DOS_CLOSE
-- CLOSE
FILE from SFT
>
55 ; [THISSFT] set to the SFT for the file being used
57 ; Close the indicated file via the SFT
59 ; sf_ref_count decremented otherwise
63 ; DS preserved, others destroyed
65 procedure DOS_CLOSE
,NEAR
66 DOSAssume
CS,<DS>,"DOS_Close"
70 Assert ISSFT
,<ES,DI>,<"DOS_CLOSE">
71 fmt TypAccess
,LevBUSY
,<"$p: CLOSE SFT: $x:$x\n">,<ES,DI>
72 MOV BX,ES:[DI.sf_flags
]
74 ; Network closes are handled entirely by the net code.
78 ; invoke OWN_SHARE ;IFS. IFS owns share ? ;AN000;
79 ; JZ noshare ;IFS. yes ;AN000;
80 ; EnterCrit critDisk ;IFS. ;AN000;
81 ; CALL SetSFTTimes ;IFS. set time for all SFT ;AN000;
82 ; LeaveCrit critDisk ;IFS. ;AN000;
84 CallInstall Net_Close
,multnet
,6
85 ; JC nomore ;IFS. error ;AN000;
86 ; invoke OWN_SHARE ;IFS. IFS owns share ? ;AN000;
87 ; JZ nomore ;IFS. yes ;AN000;
88 ; invoke ShareEnd ;IFS. remove SFT entry from share ;AN000;
93 ; All closes release the sharing information.
94 ; No commit releases sharing information
96 ; All closes decrement the ref count.
97 ; No commit decrements the ref count.
102 CALL Free_SFT
; dec ref count or mark as busy
104 TEST BX,devid_device
;FS. device ? ;AN000;
105 JNZ nofastsk
;FS. yes ;AN000;
106 MOV CX,ES:[DI.sf_firclus
] ;FS. cx= first cluster ;AN000;
107 OR CX,CX ;FS. cx=0 ? ;AN000;
108 JZ nofastsk
;FS. yes, dont do it ;AN000;
109 LDS SI,ES:[DI.sf_devptr
] ;FS. ;AN000;
110 MOV DL,[SI.dpb_drive
] ;FS. dl= drive ;AN000;
111 invoke FastSeek_Close
;FS. invoke fastseek ;AN000;
118 ; Commit enters here. AX from commit MUST be <> 1, BX is flags word
123 ; File clean or device does not get stamped nor disk looked at.
125 TEST BX,devid_file_clean
+ devid_device
127 JMP Free_SFT_OK
; either clean or device
129 ; Retrieve the directory entry for the file
134 MOV AL,error_access_denied
136 JMP CloseFinish
; pretend the close worked.
139 ; ES:DI points to entry
140 ; DS:SI points to SFT
141 ; ES:BX points to buffer header
146 ; ES:DI point to directory entry
147 ; DS:SI point to unpacked name
151 ; ES:DI point to unpacked name
152 ; DS:SI point to directory entry
157 JZ CLOSE_GO
; Name OK
160 POP ES ; ES:DI points to SFT
164 MOV AL,error_file_not_found
168 TEST [SI].sf_mode
,sf_isfcb
; FCB ?
169 JZ nofcb
; no, set dir attr, sf_attr
170 MOV CH,ES:[DI].dir_attr
173 invoke MatchAttributes
174 JNZ Bye
; attributes do not match
175 JMP SHORT setattr
;FT.
177 MOV AL,[SI].sf_attr
;FT. ;AN000;
178 MOV ES:[DI].dir_attr
,AL ;FT. ;AN000;
180 OR BYTE PTR ES:[DI.dir_attr
],attr_archive
;Set archive
181 MOV AX,ES:[DI.dir_first
] ;AN011;F.O. save old first clusetr
182 MOV [OLD_FIRSTCLUS
],AX ;AN011;F.O. save old first clusetr
184 MOV AX,[SI.sf_firclus
]
185 MOV ES:[DI.dir_first
],AX ;Set firclus pointer
186 MOV AX,WORD PTR [SI.sf_size
]
187 MOV ES:[DI.dir_size_l
],AX ;Set size
188 MOV AX,WORD PTR [SI.sf_size
+2]
189 MOV ES:[DI.dir_size_h
],AX
191 MOV ES:[DI.dir_date
],AX ;Set date
193 MOV ES:[DI.dir_time
],AX ;Set time
196 ; MOV AX,[SI.sf_codepage] ;AN000;
197 ; MOV ES:[DI.dir_codepg],AX ;AN000;Set code page
198 ; MOV AX,[SI.sf_extcluster] ;AN000;
199 ; MOV ES:[DI.dir_extcluster],AX ;AN000; ;Set XA cluster
200 ; MOV AL,[SI.sf_attr_hi] ;AN000;
201 ; MOV ES:[DI.dir_attr2],AL ;AN000; ;Set high attr
204 TEST ES:[BX.buf_flags
],buf_dirty
;LB. if already dirty ;AN000;
205 JNZ yesdirty
;LB. don't increment dirty count ;AN000;
206 invoke INC_DIRTY_COUNT
;LB. ;AN000;
207 OR ES:[BX.buf_flags
],buf_dirty
;Buffer dirty
210 MOV CX,[SI.sf_firclus
] ; do this for Fastopen
212 ;;; 10/1/86 update fastopen cache
214 MOV AH,0 ; dir entry update
215 MOV DL,AL ; drive number A=0, B=1,,,
216 OR CX,CX ;AN005; first cluster 0; may be truncated
217 JNZ do_update2
;AN005; no, do update
218 MOV AH,3 ;AN005; do a delete cache entry
219 MOV DI,WORD PTR [SI.sf_dirsec
] ;AN005; cx:di = dir sector
220 MOV CX,WORD PTR [SI.sf_dirsec
+2] ;AN005;
221 MOV DH,[SI.sf_dirpos
] ;AN005; dh= dir pos
222 JMP SHORT do_update
;AN011;F.O.
223 do_update2: ;AN011;F.O.
224 CMP CX,[OLD_FIRSTCLUS
] ;AN011;F.O. same as old first clusetr?
225 JZ do_update
;AN011;F.O. yes
226 MOV AH,2 ;AN011;F.O. delete the old entry
227 MOV CX,[OLD_FIRSTCLUS
] ;AN011;F.O.
230 invoke FastOpen_Update
; invoke fastopen
233 ;;; 10/1/86 update fastopen cache
234 invoke FLUSHBUF
; flush all relevant buffers
236 MOV AL,error_access_denied
239 CLC ; signal no error.
242 ; Indicate to the device that the SFT is being closed.
245 PUSHF ; save flag from DirFromSFT
250 ; See if the ref count indicates that we have busied the SFT. If so, mark the
251 ; SFT as being free. Note that we do NOT need to be in critSFT as we are ONLY
252 ; going to be moving from busy to free.
254 POP CX ; get old ref count
256 fmt TypAccess
,LevBUSY
,<"$p: DOSFreeSFT: $x:$x from $x\n">,<ES,DI,AX>
258 JNZ NoFree
; then do NOT free SFT
259 Assert ISSFT
,<ES,DI>,"DOS_FREE_SFT"
260 MOV ES:[DI].sf_ref_Count
,CX
268 ; ES:DI -> SFT. Decs sft_ref_count. If the count goes to 0, mark it as busy.
269 ; Flags preserved. Return old ref count in AX
271 ; Note that busy is indicated by the SFT ref count being -1.
273 Procedure FREE_SFT
,NEAR
274 DOSAssume
CS,<DS>,"Free_SFT"
277 PUSHF ; Save carry state
278 MOV AX,ES:[DI.sf_ref_count
]
283 XCHG AX,ES:[DI.sf_ref_count
]
290 ; DirFromSFT - locate a directory entry given an SFT.
292 ; Inputs: ES:DI point to SFT
295 ; EXTERR_LOCUS = errLOC_Disk
296 ; CurBuf points to buffer
297 ; Carry Clear -> operation OK
298 ; ES:DI point to entry
299 ; ES:BX point to buffer
301 ; Carry SET -> operation failed
302 ; registers trashified
303 ; Registers modified: ALL
305 Procedure DirFromSFT
,NEAR
306 ASSUME
DS:DOSGroup
,ES:NOTHING
308 MOV [EXTERR_LOCUS
],errLOC_Disk
310 MOV DX,WORD PTR ES:[DI.sf_dirsec
+2] ;F.C. >32mb
311 MOV [HIGH_SECTOR
],DX ;F.C. >32mb
312 MOV DX,WORD PTR ES:[DI.sf_dirsec
]
314 PUSH [HIGH_SECTOR
] ;F.C. >32mb
316 invoke FATREAD_SFT
; ES:BP points to DPB, [THISDRV] set
319 POP [HIGH_SECTOR
] ;F.C. >32mb
322 MOV [ALLOWED
],allowed_FAIL
+ allowed_RETRY
325 RestoreReg
<SI,DS> ; Get back SFT pointer
328 OR ES:[DI.buf_flags
],buf_isDIR
329 MOV BX,DI ; ES:BX point to buffer header
330 LEA DI,[DI].BUFINSIZ
; Point to buffer
331 MOV AL,SIZE dir_entry
333 ADD DI,AX ; Point at the entry
335 return
; carry is clear
341 Break <DOS_Commit
- update directory entries
>
348 ; Same as DOS_CLOSE except ref_count field is not altered
349 ; DS preserved, others destroyed
351 procedure DOS_COMMIT
,NEAR
352 DOSAssume
CS,<DS>,"DOS_Commit"
356 MOV BX,ES:[DI.sf_flags
]
357 TEST BX,devid_file_clean
+ devid_device
;Clears carry
364 MOV AX,(multNET
SHL 8) OR 7
370 ; Perform local commit operation by doing a close but not releaseing the SFT.
371 ; There are three ways we can do this. One is to enter a critical section to
372 ; protect a potential free. The second is to increment the ref count to mask
373 ; the close decrementing.
375 ; The proper way is to let the caller's of close decide if a decrement should
376 ; be done. We do this by providing another entry into close after the
377 ; decrement and after the share information release.
381 EnterCrit critDisk
;PTM. ;AN000;
386 invoke DEV_OPEN_SFT
;PTM. increment device count ;AN000;
388 LeaveCrit CritDisk
;PTM. ;AN000;
393 Break <SetSFTTimes
- signal a change
in the
times for an SFT
>
396 ; SetSFTTimes - Examine the flags for a SFT and set the time appropriately.
397 ; Reflect these times in other SFT's for the same file.
399 ; Inputs: ES:DI point to SFT
400 ; BX = sf_flags set apprpriately
401 ; Outputs: Set sft times to current time iff File & dirty & !nodate
402 ; Registers modified: All except ES:DI, BX, AX
405 Procedure SetSFTTimes
,NEAR
406 Assert ISSFT
,<ES,DI>,"SetSFTTimes"
408 ; File clean or device does not get stamped nor disk looked at.
410 TEST BX,devid_file_clean
+ devid_device
411 retnz
; clean or device => no timestamp
413 ; file and dirty. See if date is good
415 TEST BX,sf_close_nodate
416 retnz
; nodate => no timestamp
418 invoke DATE16
; Date/Time to AX/DX
419 MOV ES:[DI.sf_date
],AX
420 MOV ES:[DI.sf_time
],DX