diff options
Diffstat (limited to '')
| -rw-r--r-- | v4.0/src/DOS/CLOSE.ASM | 432 |
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 | ||
| 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 | ||