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

wirehaze git hosting

MZ is back!
[MS-DOS.git] / v4.0 / src / DOS / MKNODE.ASM
1 ; SCCSID = @(#)mknode.asm 1.5 85/08/29
2 TITLE MKNODE - Node maker
3 NAME MKNODE
4 ; Low level routines for making a new local file system node
5 ; and filling in an SFT from a directory entry
6 ;
7 ; BUILDDIR
8 ; SETDOTENT
9 ; MakeNode
10 ; NEWENTRY
11 ; FREEENT
12 ; NEWDIR
13 ; DOOPEN
14 ; RENAME_MAKE
15 ; CHECK_VIRT_OPEN
16 ;
17 ; Revision history:
18 ;
19 ; AN000 version 4.0 Jan. 1988
20 ; A004 PTM 3680 --- Make SFT NAME field offset same as 3.30
21
22 ;
23 ; get the appropriate segment definitions
24 ;
25 .xlist
26 include dosseg.asm
27 include fastopen.inc
28
29 CODE SEGMENT BYTE PUBLIC 'CODE'
30 ASSUME SS:DOSGROUP,CS:DOSGROUP
31
32 .xcref
33 include dossym.inc
34 include devsym.inc
35 .cref
36 .list
37
38 i_need EntFree,WORD
39 i_need DirStart,WORD
40 i_need LastEnt,WORD
41 i_need ClusNum,WORD
42 i_need CurBuf,DWORD
43 i_need Attrib,BYTE
44 i_need VolID,BYTE
45 i_need Name1,BYTE
46 i_need ThisDPB,DWORD
47 i_need EntLast,WORD
48 i_need Creating,BYTE
49 i_need SecClusPos,BYTE
50 i_need ClusFac,BYTE
51 i_need NxtClusNum,WORD
52 i_need DirSec,WORD
53 i_need NoSetDir,BYTE
54 i_need THISSFT,DWORD
55 i_need SATTRIB,BYTE
56 i_need ALLOWED,BYTE
57 i_need FAILERR,BYTE
58 i_need VIRTUAL_OPEN
59 I_need FastOpen_Ext_info,BYTE ; DOS 3.3
60 I_need FastOpenFlg,BYTE ; DOS 3.3
61 I_need CPSWFLAG,BYTE ;FT. DOS 3.4 ;AN000;
62 I_need EXTOPEN_ON,BYTE ;FT. DOS 3.4 ;AN000;
63 I_need EXTOPEN_FLAG,WORD ;FT. DOS 3.4 ;AN000;
64 I_need EXTOPEN_IO_MODE,WORD ;FT. DOS 3.4 ;AN000;
65 I_need HIGH_SECTOR,WORD ;>32mb ;AN000;
66 I_need ACT_PAGE,WORD ;>32mb ;AN000;
67
68 Break <BUILDDIR,NEWDIR -- ALLOCATE DIRECTORIES>
69
70 ; Inputs:
71 ; ES:BP Points to DPB
72 ; [THISSFT] Set if using NEWDIR entry point
73 ; (used by ALLOCATE)
74 ; [LASTENT] current last valid entry number in directory if no free
75 ; entries
76 ; [DIRSTART] Points to first cluster of dir (0 means root)
77 ; Function:
78 ; Grow directory if no free entries and not root
79 ; Outputs:
80 ; CARRY SET IF FAILURE
81 ; ELSE
82 ; AX entry number of new entry
83 ; If a new dir [DIRSTART],[CLUSFAC],[CLUSNUM],[DIRSEC] set
84 ; AX = first entry of new dir
85 ; GETENT should be called to set [LASTENT]
86
87 procedure BUILDDIR,NEAR
88 DOSAssume CS,<DS>,"BuildDir"
89 ASSUME ES:NOTHING
90
91 MOV AX,[ENTFREE]
92 CMP AX,-1
93 JZ CHECK_IF_ROOT
94 CLC
95 return
96
97 CHECK_IF_ROOT:
98 CMP [DIRSTART],0
99 JNZ NEWDIR
100 STC
101 return ; Can't grow root
102
103 entry NEWDIR
104 MOV BX,[DIRSTART]
105 OR BX,BX
106 JZ NULLDIR
107 invoke GETEOF
108 retc ; Screw up
109 NULLDIR:
110 MOV CX,1
111 invoke ALLOCATE
112 retc
113 MOV DX,[DIRSTART]
114 OR DX,DX
115 JNZ ADDINGDIR
116 invoke SETDIRSRCH
117 retc
118 MOV [LASTENT],-1
119 JMP SHORT GOTDIRREC
120 ADDINGDIR:
121 PUSH BX
122 MOV BX,[ClusNum]
123 Invoke IsEof
124 POP BX
125 JB NOTFIRSTGROW
126 ;;;; 10/17/86 update CLUSNUM in the fastopen cache
127 MOV [CLUSNUM],BX
128 PUSH CX
129 PUSH AX
130 PUSH BP
131 MOV AH,1 ; CLUSNUM update
132 MOV DL,ES:[BP.dpb_drive] ; drive #
133 MOV CX,[DIRSTART] ; first cluster #
134 MOV BP,BX ; CLUSNUM
135 invoke FastOpen_Update
136 POP BP
137 POP AX
138 POP CX
139
140 ;;;; 10/17/86 update CLUSNUM in the fastopen cache
141 NOTFIRSTGROW:
142 MOV DX,BX
143 XOR BL,BL
144 invoke FIGREC
145 GOTDIRREC:
146 MOV CL,ES:[BP.dpb_cluster_mask]
147 INC CL
148 XOR CH,CH
149 ZERODIR:
150 PUSH CX
151 MOV [ALLOWED],allowed_FAIL + allowed_RETRY
152 MOV AL,0FFH
153 invoke GETBUFFR
154 JNC GET_SSIZE
155 POP CX
156 return
157
158 GET_SSIZE:
159 MOV CX,ES:[BP.dpb_sector_size]
160 PUSH ES
161 LES DI,[CURBUF]
162 OR ES:[DI.buf_flags],buf_isDIR
163 PUSH DI
164 ADD DI,BUFINSIZ
165 XOR AX,AX
166 SHR CX,1
167 REP STOSW
168 JNC EVENZ
169 STOSB
170 EVENZ:
171 POP DI
172
173 TEST ES:[DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000;
174 JNZ yesdirty ;LB. don't increment dirty count ;AN000;
175 invoke INC_DIRTY_COUNT ;LB. ;AN000;
176 OR ES:[DI.buf_flags],buf_dirty
177 yesdirty:
178 POP ES
179 POP CX
180 INC DX
181 LOOP ZERODIR
182 MOV AX,[LASTENT]
183 INC AX
184 CLC
185 return
186
187 EndProc BUILDDIR
188
189 ;
190 ; set up a . or .. directory entry for a directory.
191 ;
192 ; Inputs: ES:DI point to the beginning of a directory entry.
193 ; AX contains ". " or ".."
194 ; DX contains first cluster of entry
195 ;
196 procedure SETDOTENT,NEAR
197 DOSAssume CS,<DS>,"SetDotEnt"
198 ;
199 ; Fill in name field
200 ;
201 STOSW
202 MOV CX,4
203 MOV AX," "
204 REP STOSW
205 STOSB
206 ;
207 ; Set up attribute
208 ;
209 MOV AL,attr_directory
210 errnz dir_attr-(dir_name+11)
211 STOSB
212 ;
213 ; Initialize time and date of creation
214 ;
215 ADD DI,10
216 MOV SI,WORD PTR [THISSFT]
217 MOV AX,[SI.sf_time]
218 errnz dir_time-(dir_attr+1+10)
219 STOSW
220 MOV AX,[SI.sf_date]
221 errnz dir_date-(dir_time+2)
222 STOSW
223 ;
224 ; Set up first cluster field
225 ;
226 MOV AX,DX
227 errnz dir_first-(dir_date+2)
228 STOSW
229 ;
230 ; 0 file size
231 ;
232 XOR AX,AX
233 errnz dir_size_l-(dir_first+2)
234 STOSW
235 STOSW
236 errnz <(size dir_entry)-(dir_size_l+4)>
237 return
238 EndProc SETDOTENT
239
240 Break <MAKENODE -- CREATE A NEW NODE>
241
242 ; Inputs:
243 ; AL - attribute to create
244 ; AH = 0 if it is ok to truncate a file already by this name
245 ; AH = Non 0 if this is an error
246 ; (AH ignored on dirs and devices)
247 ; NOTE: When making a DIR or volume ID, AH need not be set since
248 ; a name already existant is ALWAYS an error in these cases.
249 ; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL
250 ; terminated)
251 ; [CURR_DIR_END] Points to end of Current dir part of string
252 ; ( = -1 if current dir not involved, else
253 ; Points to first char after last "/" of current dir part)
254 ; [THISCDS] Points to CDS being used
255 ; [THISSFT] Points to an empty SFT. EXCEPT sf_mode filled in.
256 ; Function:
257 ; Make a new node
258 ; Outputs:
259 ; Sets EXTERR_LOCUS = errLOC_Disk or errLOC_Unk via GetPathNoset
260 ; CARRY SET IF ERROR
261 ; AX = 1 A node by this name exists and is a directory
262 ; AX = 2 A new node could not be created
263 ; AX = 3 A node by this name exists and is a disk file
264 ; (AH was NZ on input)
265 ; AX = 4 Bad Path
266 ; SI return from GetPath maintained
267 ; AX = 5 Attribute mismatch
268 ; AX = 6 Sharing Violation
269 ; (INT 24 generated ALWAYS since create is always compat mode
270 ; AX = 7 file not found for Extended Open (not exists and fails)
271 ; ELSE
272 ; AX = 0 Disk Node
273 ; AX = 3 Device Node (error in some cases)
274 ; [DIRSTART],[DIRSEC],[CLUSFAC],[CLUSNUM] set to directory
275 ; containing new node.
276 ; [CURBUF+2]:BX Points to entry
277 ; [CURBUF+2]:SI Points to entry.dir_first
278 ; [THISSFT] is filled in
279 ; sf_mode = unchanged.
280 ; Attribute byte in entry is input AL
281 ; DS preserved, others destroyed
282
283 procedure MakeNode,NEAR
284 DOSAssume CS,<DS>,"MakeNode"
285 ASSUME ES:NOTHING
286
287 MOV WORD PTR [CREATING],0E5FFH ; Creating, not DEL *.*
288 PUSH AX ; Save AH value
289 MOV [NoSetDir],0
290 MOV [SATTRIB],AL
291 invoke GetPathNoSet
292 MOV DL,CL ; Save CL info
293 MOV CX,AX ; Device ID to CH
294 POP AX ; Get back AH
295 JNC make_exists ; File existed
296 JNZ make_err_4 ; Path bad
297 CMP DL,80H ; Check "CL" return from GETPATH
298 JZ make_type ; Name simply not found, and no metas
299 make_err_4:
300 MOV AL,4 ; case 1 bad path
301 make_err_ret:
302 XOR AH,AH
303 STC
304 return
305
306 entry RENAME_MAKE ; Used by DOS_RENAME to "copy" a node
307
308 make_type:
309 ;Extended Open hooks
310 TEST [EXTOPEN_ON],ext_open_on ;FT. from extended open ;AN000;
311 JZ make_type2 ;FT. no ;AN000;
312 OR [EXTOPEN_ON],ext_file_not_exists ;FT. set for extended open ;AN000;
313 TEST [EXTOPEN_FLAG],0F0H ;FT. not exists and fails ;AN000;
314 JNZ make_type2 ;FT. no ;AN000;
315 STC ;FT. set carry ;AN000;
316 MOV AX,7 ;FT. file not found ;AN000;
317 return ;FT. ;AN000;
318 make_type2:
319 ;Extended Open hooks
320 LES DI,[THISSFT]
321 ; MOV ES:[DI.sf_mode],sharing_compat + open_for_both
322 XOR AX,AX ; nothing exists Disk Node
323 STC ; Not found
324 JMP make_new
325
326 ;
327 ; The node exists. It may be either a device, directory or file:
328 ; Zero set => directory
329 ; High bit of CH on => device
330 ; else => file
331 make_exists:
332 JZ make_exists_dir
333 MOV AL,3 ; file exists type 3 (error or device node)
334 TEST BYTE PTR [ATTRIB],(attr_volume_id+attr_directory)
335 JNZ make_err_ret_5 ; Cannot already exist as Disk or Device Node
336 ; if making DIR or Volume ID
337 OR CH,CH
338 JS make_share ; No further checks on attributes if device
339 OR AH,AH
340 JNZ make_err_ret ; truncating NOT OK (AL = 3)
341 PUSH CX ; Save device ID
342 MOV ES,WORD PTR [CURBUF+2]
343 MOV CH,ES:[BX+dir_attr] ; Get file attributes
344 TEST CH,attr_read_only
345 JNZ make_err_ret_5P ; Cannot create on read only files
346 invoke MatchAttributes
347 POP CX ; Devid back in CH
348 JNZ make_err_ret_5 ; Attributes not ok
349 XOR AL,AL ; AL = 0, Disk Node
350 make_share:
351 XOR AH,AH
352 PUSH AX ; Save Disk or Device node
353 PUSH CX ; Save Device ID
354 MOV AH,CH ; Device ID to AH
355 CALL DOOPEN ; Fill in SFT for share check
356 LES DI,[THISSFT]
357 ; MOV ES:[DI.sf_mode],sharing_compat + open_for_both
358 SaveReg <SI,BX> ; Save CURBUF pointers
359 invoke ShareEnter
360 jnc MakeEndShare
361 ;
362 ; User failed request.
363 ;
364 RestoreReg <BX,SI,CX,AX>
365 Make_Share_ret:
366 MOV AL,6
367 JMP make_err_ret
368
369 make_err_ret_5P:
370 POP CX ; Get back device ID
371 make_err_ret_5:
372 MOV AL,5 ; Attribute mismatch
373 JMP make_err_ret
374
375 make_exists_dir:
376 MOV AL,1 ; exists as directory, always an error
377 JMP make_err_ret
378
379 make_save:
380 PUSH AX ; Save whether Disk or File
381 MOV AX,CX ; Device ID to AH
382 CALL NewEntry
383 POP AX ; 0 if Disk, 3 if File
384 retnc
385 MOV AL,2 ; create failed case 2
386 return
387
388 make_new:
389 call make_save
390 retc ; case 2 fail
391 TEST BYTE PTR [ATTRIB],attr_directory
392 retnz ; Don't "open" directories, so don't
393 ; tell the sharer about them
394 SaveReg <AX,BX,SI> ; Save AL code
395 invoke ShareEnter
396 RestoreReg <SI,BX,AX>
397 retnc
398 ;
399 ; We get here by having the user FAIL a share problem. Typically a failure of
400 ; this nature is an out-of-space or an internal error. We clean up as best as
401 ; possible: delete the newly created directory entry and return share_error.
402 ;
403 PUSH AX
404 LES DI,CurBuf
405 MOV BYTE PTR ES:[BX],0E5H ; nuke newly created entry.
406
407 TEST ES:[DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000;
408 JNZ yesdirty2 ;LB. don't increment dirty count ;AN000;
409 invoke INC_DIRTY_COUNT ;LB. ;AN000;
410 OR ES:[DI].buf_flags,buf_dirty ; flag buffer as dirty
411 yesdirty2:
412 LES BP,ThisDPB
413 MOV AL,ES:[BP].DPB_Drive ; get drive for flush
414 Invoke FlushBuf ; write out buffer.
415 POP AX
416 jmp make_Share_ret
417 ;
418 ; We have found an existing file. We have also entered it into the share set.
419 ; At this point we need to call newentry to correctly address the problem of
420 ; getting rid of old data (create an existing file) or creating a new
421 ; directory entry (create a new file). Unfortunately, this operation may
422 ; result in an INT 24 that the user doesn't return from, thus locking the file
423 ; irretrievably into the share set. The correct solution is for us to LEAVE
424 ; the share set now, do the operation and then reassert the share access.
425 ;
426 ; We are allowed to do this! There is no window! After all, we are in
427 ; critDisk here and for someone else to get in, they must enter critDisk also.
428 ;
429 MakeEndShare:
430 LES DI,ThisSFT ; grab SFT
431 XOR AX,AX
432 EnterCrit critSFT
433 XCHG AX,ES:[DI].sf_ref_count
434 SaveReg <AX,DI,ES>
435 PUSHF
436 invoke ShareEnd ; remove sharing
437 POPF
438 RestoreReg <ES,DI,ES:[DI].sf_ref_count>
439 LeaveCrit critSFT
440 RestoreReg <BX,SI,CX,AX>
441 CALL make_save
442 ;
443 ; If the user failed, we do not reenter into the sharing set.
444 ;
445 retc ; bye if error
446 SaveReg <AX,BX,SI>
447 PUSHF
448 invoke ShareEnter
449 POPF
450 RestoreReg <SI,BX,AX>
451 ;
452 ; If Share_check fails, then we have an internal ERROR!!!!!
453 ;
454 return
455 EndProc MakeNode
456
457 ; Inputs:
458 ; [THISSFT] set
459 ; [THISDPB] set
460 ; [LASTENT] current last valid entry number in directory if no free
461 ; entries
462 ; [VOLID] set if a volume ID was found during search
463 ; [ATTRIB] Contains attributes for new file
464 ; [DIRSTART] Points to first cluster of dir (0 means root)
465 ; CARRY FLAG INDICATES STATUS OF SEARCH FOR FILE
466 ; NC means file existed (device)
467 ; C means file did not exist
468 ; AH = Device ID byte
469 ; If FILE
470 ; [CURBUF+2]:BX points to start of directory entry
471 ; [CURBUF+2]:SI points to dir_first of directory entry
472 ; If device
473 ; DS:BX points to start of "fake" directory entry
474 ; DS:SI points to dir_first of "fake" directory entry
475 ; (has DWORD pointer to device header)
476 ; Function:
477 ; Make a new directory entry
478 ; If an old one existed it is truncated first
479 ; Outputs:
480 ; Carry set if error
481 ; Can't grow dir, atts didn't match, attempt to make 2nd
482 ; vol ID, user FAILed to I 24
483 ; else
484 ; outputs of DOOPEN
485 ; DS, BX, SI preserved (meaning on SI BX, not value), others destroyed
486
487 procedure NEWENTRY,NEAR
488 DOSAssume CS,<DS>,"NewEntry"
489 ASSUME ES:NOTHING
490
491 LES BP,[THISDPB]
492 ASSUME ES:NOTHING
493 JNC EXISTENT
494 CMP [FAILERR],0
495 STC
496 retnz ; User FAILed, node might exist
497 CALL BUILDDIR ; Try to build dir
498 retc ; Failed
499 invoke GETENT ; Point at that free entry
500 retc ; Failed
501 JMP SHORT FREESPOT
502
503 ERRRET3:
504 STC
505 return
506
507 EXISTENT:
508 DOSAssume CS,<DS>,"MKNODE/ExistEnt"
509 OR AH,AH ; Check if file is I/O device
510 JNS NOT_DEV1
511 JMP DOOPEN ; If so, proceed with open
512
513 NOT_DEV1:
514 invoke FREEENT ; Free cluster chain
515 retc ; Failed
516 FREESPOT:
517 TEST BYTE PTR [ATTRIB],attr_volume_id
518 JZ NOTVOLID
519 CMP BYTE PTR [VOLID],0
520 JNZ ERRRET3 ; Can't create a second volume ID
521 NOTVOLID:
522 MOV ES,WORD PTR [CURBUF+2]
523 MOV DI,BX
524 MOV SI,OFFSET DOSGROUP:NAME1
525 MOV CX,5
526 REP MOVSW
527 MOVSB ; Move name into dir entry
528 MOV AL,[ATTRIB]
529 errnz dir_attr-(dir_name+11)
530 STOSB ; Attributes
531 ;; File Tagging for Create DOS 4.00
532 MOV CL,5 ;FT. assume normal ;AN000;
533 ; CMP [CPSWFLAG],0 ;FT. code page matching on ;AN000;
534 ; JZ NORMFT ;FT. no, make null code page ;AN000;
535 ; invoke Get_Global_CdPg ;FT. get global code page ;AN000;
536 ; STOSW ;FT. tag this file with global code page ;AN000;
537 ; DEC CL ;FT. only 4 ;AN000;
538 ;NORMFT: ;FT. ;AN000;
539
540 ;; File Tagging for Create DOS 4.00
541 XOR AX,AX
542 REP STOSW ; Zero pad
543 invoke DATE16
544 XCHG AX,DX
545 errnz dir_time-(dir_attr+1+2*5)
546 STOSW ; dir_time
547 XCHG AX,DX
548 errnz dir_date-(dir_time+2)
549 STOSW ; dir_date
550 XOR AX,AX
551 PUSH DI ; Correct SI input value (recomputed for new buffer)
552
553 errnz dir_first-(dir_date+2)
554 STOSW ; Zero dir_first and size
555 errnz dir_size_l-(dir_first+2)
556 STOSW
557 STOSW
558 updnxt:
559 errnz <(size dir_entry)-(dir_size_l+4)>
560 MOV SI,WORD PTR [CURBUF]
561
562 TEST ES:[SI.buf_flags],buf_dirty ;LB. if already dirty ;AN000;
563 JNZ yesdirty3 ;LB. don't increment dirty count ;AN000;
564 invoke INC_DIRTY_COUNT ;LB. ;AN000;
565 OR ES:[SI.buf_flags],buf_dirty
566 yesdirty3:
567 LES BP,[THISDPB]
568 MOV AL,ES:[BP.dpb_drive] ; Sets AH value again (in AL)
569 PUSH AX
570 PUSH BX
571 ; If we have a file, we need to increment the open ref. count so that
572 ; we have some protection against invalid media changes if an Int 24
573 ; error occurs.
574 ; Do nothing for a device.
575 SaveReg <ES,DI>
576 LES DI,[THISSFT]
577 test es:[di.sf_flags],devid_device
578 jnz GotADevice
579 SaveReg <DS,BX>
580 LDS BX,[THISDPB]
581 MOV word ptr ES:[DI.sf_devptr],BX
582 MOV BX,DS
583 MOV word ptr ES:[DI.sf_devptr+2],BX
584 RestoreReg <BX,DS> ; need to use DS for segment later on
585 invoke Dev_Open_SFT ; increment ref. count
586 mov [VIRTUAL_OPEN],1; set flag
587 GotADevice:
588 RestoreReg <DI,ES>
589
590 PUSH [ACT_PAGE] ;LB. save EMS page for curbuf ;AN000;
591 invoke FLUSHBUF
592 POP BX ;LB. restore EMS page for curbuf ;AN000;
593 PUSHF ;LB. save flushbuf falg ;AN000;
594 CMP BX,-1 ;BL-NETWORK PTM #-?
595 JE Page_ok ;BL-NETWORK PTM #-?
596 invoke SET_MAP_PAGE ;LB. remap curbuf ;AN000;
597 Page_ok: ;BL-NETWORK PTM #-?
598 POPF ;LB. restore flush flag ;AN000;
599 Call CHECK_VIRT_OPEN ; decrement ref. count ;AN000;
600 POP BX
601 POP AX
602 POP SI ; Get SI input back
603 MOV AH,AL ; Get I/O driver number back
604 retc ; Failed
605
606
607 ;NOTE FALL THROUGH
608
609 ; Inputs:
610 ; [THISDPB] points to DPB if file
611 ; [THISSFT] points to SFT being used
612 ; AH = Device ID byte
613 ; If FILE
614 ; [CURBUF+2]:BX points to start of directory entry
615 ; [CURBUF+2]:SI points to dir_first of directory entry
616 ; If device
617 ; DS:BX points to start of "fake" directory entry
618 ; DS:SI points to dir_first of "fake" directory entry
619 ; (has DWORD pointer to device header)
620 ; Function:
621 ; Fill in SFT from dir entry
622 ; Outputs:
623 ; CARRY CLEAR
624 ; sf_ref_count and sf_mode fields not altered
625 ; sf_flags high byte = 0
626 ; sf_flags low byte = AH except
627 ; sf_flags Bit 6 set (not dirty or not EOF)
628 ; sf_attr sf_date sf_time sf_name set from entry
629 ; sf_position = 0
630 ; If device
631 ; sf_devptr = dword at dir_first (pointer to device header)
632 ; sf_size = 0
633 ; If file
634 ; sf_firclus sf_size set from entry
635 ; sf_devptr = [THISDPB]
636 ; sf_cluspos = 0
637 ; sf_lstclus = sf_firclus
638 ; sf_dirsec sf_dirpos set
639 ; DS,SI,BX preserved, others destroyed
640
641 entry DOOPEN
642 DOSAssume CS,<DS>,"DoOpen"
643 ASSUME ES:NOTHING
644
645 ;
646 ; Generate and store attribute
647 ;
648 MOV DH,AH ; AH to different place
649 LES DI,[THISSFT]
650 ADD DI,sf_attr ; Skip ref_count and mode fields
651 XOR AL,AL ; Assume it's a device, devices have an
652 ; attribute of 0 (for R/O testing etc).
653 OR DH,DH ; See if our assumption good.
654 JS DEV_SFT1 ; If device DS=DOSGROUP
655 MOV DS,WORD PTR [CURBUF+2]
656 ASSUME DS:NOTHING
657 MOV AL,[BX.dir_attr] ; If file, get attrib from dir entry
658 DEV_SFT1:
659 STOSB ; sf_attr, ES:DI -> sf_flags
660 ;
661 ; Generate and store flags word
662 ;
663 XOR AX,AX
664 MOV AL,DH
665 OR AL,devid_file_clean
666 STOSW ; sf_flags, ES:DI -> sf_devptr
667 ;
668 ; Generate and store device pointer
669 ;
670 PUSH DS
671 LDS AX,DWORD PTR [BX.dir_first] ; Assume device
672 OR DH,DH
673 JS DEV_SFT2
674 LDS AX,[THISDPB] ; Was file
675 DEV_SFT2:
676 STOSW ; store offset
677 MOV AX,DS
678 POP DS
679 STOSW ; store segment
680 ; ES:DI -> sf_firclus
681 ;
682 ; Generate pointer to, generate and store first cluster (irrelevant for
683 ; devices)
684 ;
685 PUSH SI ; Save pointer to dir_first
686 MOVSW ; dir_first -> sf_firclus
687 ; DS:SI -> dir_size_l, ES:DI -> sf_time
688 ;
689 ; Copy time/date of last modification
690 ;
691 SUB SI,dir_size_l - dir_time ; DS:SI->dir_time
692 MOVSW ; dir_time -> sf_time
693 ; DS:SI -> dir_date, ES:DI -> sf_date
694 MOVSW ; dir_date -> sf_date
695 ; DS:SI -> dir_first, ES:DI -> sf_size
696 ;
697 ; Generate and store file size (0 for devices)
698 ;
699 LODSW ; skip dir_first, DS:SI -> dir_size_l
700 LODSW ; dir_size_l in AX , DS:SI -> dir_size_h
701 MOV CX,AX ; dir_size_l in CX
702 LODSW ; dir_size_h (size AX:CX), DS:SI -> ????
703 OR DH,DH
704 JNS FILE_SFT1
705 XOR AX,AX
706 MOV CX,AX ; Devices are open ended
707 FILE_SFT1:
708 XCHG AX,CX
709 STOSW ; Low word of sf_size
710 XCHG AX,CX
711 STOSW ; High word of sf_size
712 ; ES:DI -> sf_position
713 ;
714 ; Initialize position to 0
715 ;
716 XOR AX,AX
717 STOSW
718 STOSW ; sf_position
719 ; ES:DI -> sf_cluspos
720 ;
721 ; Generate cluster optimizations for files
722 ;
723 OR DH,DH
724 JS DEV_SFT3
725 STOSW ; sf_cluspos
726 MOV AX,[BX.dir_first]
727 ;;;; STOSW ; sf_lstclus
728 PUSH DI ;AN004; save dirsec offset
729 SUB DI,sf_dirsec ;AN004; es:di -> SFT
730 MOV ES:[DI.sf_lstclus],AX ;AN004; save it
731 POP DI ;AN004; restore dirsec offset
732
733
734
735 ; DOS 3.3 FastOpen 6/13/86
736
737 PUSH DS
738 context DS
739 TEST [FastOpenFlg],Special_Fill_Set
740 JZ Not_FastOpen
741 MOV SI,OFFSET DOSGROUP:FastOpen_Ext_Info
742 MOV AX,WORD PTR [SI.FEI_dirsec]
743 STOSW ; sf_dirsec
744 MOV AX,WORD PTR [SI.FEI_dirsec+2] ;;; changed for >32mb
745 STOSW ; sf_dirsec
746 MOV AL,[SI.FEI_dirpos]
747 STOSB ; sf_dirpos
748 POP DS
749 JMP Next_Name
750
751 ; DOS 3.3 FastOpen 6/13/86
752
753 Not_FastOpen:
754 POP DS ; normal path
755 ASSUME DS:NOTHING
756 MOV SI,WORD PTR [CURBUF] ; DS:SI->buffer header
757 MOV AX,WORD PTR [SI.buf_sector] ;F.C. >32mb ;AN000;
758 STOSW ; sf_dirsec ;F.C. >32mb ;AN000;
759 MOV AX,WORD PTR [SI.buf_sector+2] ;F.C. >32mb ;AN000;
760 STOSW ; sf_dirsec ;F.C. >32mb ;AN000;
761 MOV AX,BX
762 ADD SI,BUFINSIZ ; DS:SI-> start of data in buffer
763 SUB AX,SI ; AX = BX relative to start of sector
764 MOV CL,SIZE dir_entry
765 DIV CL
766 STOSB ; sf_dirpos
767
768 Next_Name:
769 errnz sf_name-(sf_dirpos+1)
770 JMP SHORT FILE_SFT2
771
772 DEV_SFT3:
773 ADD DI,sf_name - sf_cluspos
774 FILE_SFT2:
775 ;
776 ; Copy in the object's name
777 ;
778 MOV SI,BX ; DS:SI points to dir_name
779 MOV CX,11
780 REP MOVSB ; sf_name
781 POP SI ; recover DS:SI -> dir_first
782 ;; File tagging , code page and XA cluster must be after name
783 ; MOV AX,[BX.dir_CODEPG] ;FT. set file's code page ;AN000;
784 ; STOSW ;FT. ;AN000;
785 ; MOV AX,[BX.dir_EXTCLUSTER] ;FT. set XA cluster ;AN000;
786 ; STOSW ;FT. ;AN000;
787 ; MOV AX,[EXTOPEN_IO_MODE] ;FT. extended open ;AN000;
788 ; STOSW ;FT. ;AN000;
789 ; MOV AL,[BX.dir_attr2] ;FT. high attribute ;AN000;
790 ; STOSB ;FT. ;AN000;
791
792 ;; File tagging , code page and XA cluster must be after name
793
794 context DS
795 CLC
796 return
797
798 EndProc NEWENTRY
799
800 ; Inputs:
801 ; ES:BP -> DPB
802 ; [CURBUF] Set
803 ; [CURBUF+2]:BX points to directory entry
804 ; [CURBUF+2]:SI points to above dir_first
805 ; Function:
806 ; Free the cluster chain for the entry if present
807 ; Outputs:
808 ; Carry set if error (currently user FAILed to I 24)
809 ; (NOTE dir_firclus and dir_size_l/h are wrong)
810 ; DS BX SI ES BP preserved (BX,SI in meaning, not value) others destroyed
811
812 procedure FREEENT,NEAR
813 DOSAssume CS,<DS>,"FreeEnt"
814 ASSUME ES:NOTHING
815
816 PUSH DS
817 LDS DI,[CURBUF]
818 ASSUME DS:NOTHING
819 MOV CX,[SI] ; Get pointer to clusters
820 MOV DX,WORD PTR [DI.buf_sector+2] ;F.C. >32mb ;AN000;
821 MOV [HIGH_SECTOR],DX ;F.C. >32mb ;AN000;
822 MOV DX,WORD PTR [DI.buf_sector]
823 POP DS
824 DOSAssume CS,<DS>,"MKNODE/FreeEnt"
825 CMP CX,2
826 JB RET1 ; Was 0 length file (or mucked Firclus if CX=1)
827 CMP CX,ES:[BP.dpb_max_cluster]
828 JA RET1 ; Treat like zero length file (firclus mucked)
829 SUB BX,DI
830 PUSH BX ; Save offset
831 PUSH [HIGH_SECTOR] ;F.C. >32mb ;AN000;
832 PUSH DX ; Save sector number
833
834 MOV BX,CX
835 invoke Delete_FSeek ; FS. delete Fastseek Clusters ;AN000;
836 invoke RELEASE ; Free any data allocated
837 POP DX
838 POP [HIGH_SECTOR] ;F.C. >32mb ;AN000;
839 JNC GET_BUF_BACK
840 POP BX
841 return ; Screw up
842
843 GET_BUF_BACK:
844
845 MOV [ALLOWED],allowed_RETRY + allowed_FAIL
846 XOR AL,AL
847 invoke GETBUFFR ; Get sector back
848 POP BX ; Get offset back
849 retc
850 invoke SET_BUF_AS_DIR
851 ADD BX,WORD PTR [CURBUF] ; Correct it for new buffer
852 MOV SI,BX
853 ADD SI,dir_first ; Get corrected SI
854 RET1:
855 CLC
856 return
857 EndProc FREEENT
858
859 ;
860 ; CHECK_VIRT_OPEN checks to see if we had performed a "virtual open" (by
861 ; examining the flag [VIRTUAL_OPEN] to see if it is 1). If we did, then
862 ; it calls Dev_Close_SFT to decrement the ref. count. It also resets the
863 ; flag [VIRTUAL_OPEN].
864 ; No registers affected (including flags).
865 ; On input, [THISSFT] points to current SFT.
866 ;
867 Procedure CHECK_VIRT_OPEN,NEAR
868 DOSAssume CS,<DS>,"Check_Virt_Open"
869
870 PUSH AX
871 lahf ; preserve flags
872 CMP [VIRTUAL_OPEN],0
873 JZ ALL_CLOSED
874 mov [VIRTUAL_OPEN],0 ; reset flag
875 SaveReg <ES,DI>
876 LES DI,[THISSFT]
877 INVOKE DEV_CLOSE_SFT
878 RestoreReg <DI,ES>
879
880 ALL_CLOSED:
881 sahf ; restore flags
882 POP AX
883 return
884
885 EndProc CHECK_VIRT_OPEN
886
887
888 CODE ENDS
889 END
890 \1a