summaryrefslogtreecommitdiff
path: root/v4.0/src/DOS/CLOSE.ASM
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--v4.0/src/DOS/CLOSE.ASM432
1 files changed, 432 insertions, 0 deletions
diff --git a/v4.0/src/DOS/CLOSE.ASM b/v4.0/src/DOS/CLOSE.ASM
new file mode 100644
index 0000000..8156ac8
--- /dev/null
+++ b/v4.0/src/DOS/CLOSE.ASM
@@ -0,0 +1,432 @@
1; SCCSID = @(#)close.asm 1.1 85/04/09
2TITLE DOS_CLOSE/COMMIT - Internal SFT close and commit call for MSDOS
3NAME 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
21include dosseg.asm
22
23CODE SEGMENT BYTE PUBLIC 'CODE'
24 ASSUME SS:DOSGROUP,CS:DOSGROUP
25
26.xcref
27INCLUDE DOSSYM.INC
28INCLUDE DEVSYM.INC
29.cref
30.list
31
32Installed = 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
46if debug
47 I_need BugLev,WORD
48 I_need BugTyp,WORD
49include bugtyp.asm
50endif
51
52Break <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;
83noshare:
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;
89nomore:
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;
99LocalClose:
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;
112nofastsk:
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;
120CloseEntry:
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;
131rdir:
132 CALL DirFromSFT
133ASSUME DS:NOTHING
134 MOV AL,error_access_denied
135 JNC clook
136 JMP CloseFinish ; pretend the close worked.
137clook:
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
158Bye: 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
167CLOSE_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.
176nofcb:
177 MOV AL,[SI].sf_attr ;FT. ;AN000;
178 MOV ES:[DI].dir_attr,AL ;FT. ;AN000;
179setattr:
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
208yesdirty:
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.
223do_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.
228do_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
238FREE_SFT_OK:
239 CLC ; signal no error.
240CloseFinish:
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
261NoFree:
262 LeaveCrit critDisk
263 POPF
264 return
265EndProc 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;
273Procedure 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
282SetCount:
283 XCHG AX,ES:[DI.sf_ref_count]
284 POPF
285 return
286
287EndProc 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
305Procedure 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
336PopDone:
337 RestoreReg <DI,ES>
338 return
339EndProc DirFromSFT
340
341Break <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
361IF NOT Installed
362 transfer NET_COMMIT
363ELSE
364 MOV AX,(multNET SHL 8) OR 7
365 INT 2FH
366 return
367ENDIF
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;
379LOCAL_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
391EndProc DOS_COMMIT
392
393Break <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
405Procedure 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
422if installed
423 call JShare + 14 * 4
424else
425 call ShSU
426endif
427 RestoreReg <BX,AX>
428 return
429EndProc SetSFTTimes
430
431CODE ENDS
432 END