]> wirehaze git hosting - MS-DOS.git/blob - v4.0/src/DOS/CLOSE.ASM

wirehaze git hosting

MZ is back!
[MS-DOS.git] / 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
3 NAME DOS_CLOSE
4 ; Internal Close and Commit calls to close a local or NET SFT.
5 ;
6 ; DOS_CLOSE
7 ; DOS_COMMIT
8 ; FREE_SFT
9 ; SetSFTTimes
10 ;
11 ; Revision history:
12 ;
13 ; AN000 version 4.00 Jan. 1988
14 ; A005 PTM 3718 --- lost clusters when fastopen installed
15 ; A011 PTM 4766 --- C2 fastopen problem
16
17 ;
18 ; get the appropriate segment definitions
19 ;
20 .xlist
21 include dosseg.asm
22
23 CODE SEGMENT BYTE PUBLIC 'CODE'
24 ASSUME SS:DOSGROUP,CS:DOSGROUP
25
26 .xcref
27 INCLUDE DOSSYM.INC
28 INCLUDE DEVSYM.INC
29 .cref
30 .list
31
32 Installed = TRUE
33
34 I_need Attrib,BYTE
35 i_need THISSFT,DWORD
36 i_need CURBUF,DWORD
37 i_need THISDRV,BYTE
38 i_need ALLOWED,BYTE
39 i_need EXTERR_LOCUS,BYTE
40 I_need FailErr,BYTE
41 I_Need PROC_ID,WORD
42 I_Need USER_ID,WORD
43 i_need JShare,DWORD
44 i_need HIGH_SECTOR,WORD ;F.C. >32mb
45 i_need OLD_FIRSTCLUS,WORD ;F.O. >32mb
46 if debug
47 I_need BugLev,WORD
48 I_need BugTyp,WORD
49 include bugtyp.asm
50 endif
51
52 Break <DOS_CLOSE -- CLOSE FILE from SFT>
53
54 ; Inputs:
55 ; [THISSFT] set to the SFT for the file being used
56 ; Function:
57 ; Close the indicated file via the SFT
58 ; Returns:
59 ; sf_ref_count decremented otherwise
60 ; ES:DI point to SFT
61 ; Carry set if error
62 ; AX has error code
63 ; DS preserved, others destroyed
64
65 procedure DOS_CLOSE,NEAR
66 DOSAssume CS,<DS>,"DOS_Close"
67 ASSUME ES:NOTHING
68
69 LES DI,[THISSFT]
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]
73 ;
74 ; Network closes are handled entirely by the net code.
75 ;
76 TEST BX,sf_isnet
77 JZ LocalClose
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;
83 noshare:
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;
89 nomore:
90 return
91
92 ;
93 ; All closes release the sharing information.
94 ; No commit releases sharing information
95 ;
96 ; All closes decrement the ref count.
97 ; No commit decrements the ref count.
98 ;
99 LocalClose:
100 EnterCrit critDisk
101 CALL SetSFTTimes
102 CALL Free_SFT ; dec ref count or mark as busy
103
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;
112 nofastsk:
113 Context DS
114 SaveReg <AX,BX>
115 invoke ShareEnd
116 RestoreReg <BX,AX>
117 ;
118 ; Commit enters here. AX from commit MUST be <> 1, BX is flags word
119 ;
120 CloseEntry:
121 PUSH AX
122 ;
123 ; File clean or device does not get stamped nor disk looked at.
124 ;
125 TEST BX,devid_file_clean + devid_device
126 JZ rdir
127 JMP Free_SFT_OK ; either clean or device
128 ;
129 ; Retrieve the directory entry for the file
130 ;
131 rdir:
132 CALL DirFromSFT
133 ASSUME DS:NOTHING
134 MOV AL,error_access_denied
135 JNC clook
136 JMP CloseFinish ; pretend the close worked.
137 clook:
138 ;
139 ; ES:DI points to entry
140 ; DS:SI points to SFT
141 ; ES:BX points to buffer header
142 ;
143 SaveReg <DI,SI>
144 LEA SI,[SI].sf_name
145 ;
146 ; ES:DI point to directory entry
147 ; DS:SI point to unpacked name
148 ;
149 invoke XCHGP
150 ;
151 ; ES:DI point to unpacked name
152 ; DS:SI point to directory entry
153 ;
154 invoke MetaCompare
155 invoke XCHGP
156 RestoreReg <SI,DI>
157 JZ CLOSE_GO ; Name OK
158 Bye: MOV DI,SI
159 PUSH DS
160 POP ES ; ES:DI points to SFT
161 PUSH SS
162 POP DS
163 STC
164 MOV AL,error_file_not_found
165 JMP CloseFinish
166
167 CLOSE_GO:
168 TEST [SI].sf_mode,sf_isfcb ; FCB ?
169 JZ nofcb ; no, set dir attr, sf_attr
170 MOV CH,ES:[DI].dir_attr
171 MOV AL,[SI].sf_attr
172 MOV Attrib,AL
173 invoke MatchAttributes
174 JNZ Bye ; attributes do not match
175 JMP SHORT setattr ;FT.
176 nofcb:
177 MOV AL,[SI].sf_attr ;FT. ;AN000;
178 MOV ES:[DI].dir_attr,AL ;FT. ;AN000;
179 setattr:
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
183
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
190 MOV AX,[SI.sf_date]
191 MOV ES:[DI.dir_date],AX ;Set date
192 MOV AX,[SI.sf_time]
193 MOV ES:[DI.dir_time],AX ;Set time
194 ;; File Tagging
195
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
202
203 ;; File Tagging
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
208 yesdirty:
209 SaveReg <DS,SI>
210 MOV CX,[SI.sf_firclus] ; do this for Fastopen
211 MOV AL,[THISDRV]
212 ;;; 10/1/86 update fastopen cache
213 PUSH DX
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.
228 do_update: ;AN005;
229 Context DS
230 invoke FastOpen_Update ; invoke fastopen
231 POP DX
232
233 ;;; 10/1/86 update fastopen cache
234 invoke FLUSHBUF ; flush all relevant buffers
235 RestoreReg <DI,ES>
236 MOV AL,error_access_denied
237 JC CloseFinish
238 FREE_SFT_OK:
239 CLC ; signal no error.
240 CloseFinish:
241 ;
242 ; Indicate to the device that the SFT is being closed.
243 ;
244 ;;;; 7/21/86
245 PUSHF ; save flag from DirFromSFT
246 invoke Dev_Close_SFT
247 POPF
248 ;;;; 7/21/86
249 ;
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.
253 ;
254 POP CX ; get old ref count
255 PUSHF
256 fmt TypAccess,LevBUSY,<"$p: DOSFreeSFT: $x:$x from $x\n">,<ES,DI,AX>
257 DEC CX ; if cx != 1
258 JNZ NoFree ; then do NOT free SFT
259 Assert ISSFT,<ES,DI>,"DOS_FREE_SFT"
260 MOV ES:[DI].sf_ref_Count,CX
261 NoFree:
262 LeaveCrit critDisk
263 POPF
264 return
265 EndProc DOS_Close
266
267 ;
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
270 ;
271 ; Note that busy is indicated by the SFT ref count being -1.
272 ;
273 Procedure FREE_SFT,NEAR
274 DOSAssume CS,<DS>,"Free_SFT"
275 ASSUME ES:NOTHING
276
277 PUSHF ; Save carry state
278 MOV AX,ES:[DI.sf_ref_count]
279 DEC AX
280 JNZ SetCount
281 DEC AX
282 SetCount:
283 XCHG AX,ES:[DI.sf_ref_count]
284 POPF
285 return
286
287 EndProc Free_SFT
288
289 ;
290 ; DirFromSFT - locate a directory entry given an SFT.
291 ;
292 ; Inputs: ES:DI point to SFT
293 ; DS = DOSGroup
294 ; Outputs:
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
300 ; DS:SI point to SFT
301 ; Carry SET -> operation failed
302 ; registers trashified
303 ; Registers modified: ALL
304
305 Procedure DirFromSFT,NEAR
306 ASSUME DS:DOSGroup,ES:NOTHING
307
308 MOV [EXTERR_LOCUS],errLOC_Disk
309 SaveReg <ES,DI>
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]
313
314 PUSH [HIGH_SECTOR] ;F.C. >32mb
315 PUSH DX
316 invoke FATREAD_SFT ; ES:BP points to DPB, [THISDRV] set
317 ; [THISDPB] set
318 POP DX
319 POP [HIGH_SECTOR] ;F.C. >32mb
320 JC PopDone
321 XOR AL,AL ; Pre read
322 MOV [ALLOWED],allowed_FAIL + allowed_RETRY
323 invoke GETBUFFR
324 JC PopDone
325 RestoreReg <SI,DS> ; Get back SFT pointer
326 ASSUME DS:NOTHING
327 LES DI,Curbuf
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
332 MUL [SI].sf_DirPos
333 ADD DI,AX ; Point at the entry
334
335 return ; carry is clear
336 PopDone:
337 RestoreReg <DI,ES>
338 return
339 EndProc DirFromSFT
340
341 Break <DOS_Commit - update directory entries>
342
343 ; Inputs:
344 ; Same as DOS_CLOSE
345 ; Function:
346 ; Commit the file
347 ; Returns:
348 ; Same as DOS_CLOSE except ref_count field is not altered
349 ; DS preserved, others destroyed
350
351 procedure DOS_COMMIT,NEAR
352 DOSAssume CS,<DS>,"DOS_Commit"
353 ASSUME ES:NOTHING
354
355 LES DI,[THISSFT]
356 MOV BX,ES:[DI.sf_flags]
357 TEST BX,devid_file_clean + devid_device ;Clears carry
358 retnz
359 TEST BX,sf_isnet
360 JZ LOCAL_COMMIT
361 IF NOT Installed
362 transfer NET_COMMIT
363 ELSE
364 MOV AX,(multNET SHL 8) OR 7
365 INT 2FH
366 return
367 ENDIF
368
369 ;
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.
374 ;
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.
378 ;
379 LOCAL_COMMIT:
380 EnterCrit critDisk
381 EnterCrit critDisk ;PTM. ;AN000;
382 call SetSFTTimes
383 MOV AX,-1
384 call CloseEntry
385 PUSHF ;PTM. ;AN000;
386 invoke DEV_OPEN_SFT ;PTM. increment device count ;AN000;
387 POPF ;PTM. ;AN000;
388 LeaveCrit CritDisk ;PTM. ;AN000;
389 return
390
391 EndProc DOS_COMMIT
392
393 Break <SetSFTTimes - signal a change in the times for an SFT>
394
395 ;
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.
398 ;
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
403 ;
404
405 Procedure SetSFTTimes,NEAR
406 Assert ISSFT,<ES,DI>,"SetSFTTimes"
407 ;
408 ; File clean or device does not get stamped nor disk looked at.
409 ;
410 TEST BX,devid_file_clean + devid_device
411 retnz ; clean or device => no timestamp
412 ;
413 ; file and dirty. See if date is good
414 ;
415 TEST BX,sf_close_nodate
416 retnz ; nodate => no timestamp
417 SaveReg <AX,BX>
418 invoke DATE16 ; Date/Time to AX/DX
419 MOV ES:[DI.sf_date],AX
420 MOV ES:[DI.sf_time],DX
421 XOR AX,AX
422 if installed
423 call JShare + 14 * 4
424 else
425 call ShSU
426 endif
427 RestoreReg <BX,AX>
428 return
429 EndProc SetSFTTimes
430
431 CODE ENDS
432 END