1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
|
; SCCSID = @(#)dircall.asm 1.1 85/04/10
; SCCSID = @(#)dircall.asm 1.1 85/04/10
TITLE DIRCALL - Directory manipulation internal calls
NAME DIRCALL
; Low level directory manipulation routines for making removing and
; verifying local or NET directories
;
; DOS_MKDIR
; DOS_CHDIR
; DOS_RMDIR
;
; Modification history:
;
; Created: ARR 30 March 1983
;
;
; get the appropriate segment definitions
;
.xlist
include dosseg.asm
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.xcref
INCLUDE DOSSYM.INC
INCLUDE DEVSYM.INC
INCLUDE FASTOPEN.INC
INCLUDE FASTXXXX.INC
.cref
.list
Installed = TRUE
i_need THISSFT,DWORD
i_need THISCDS,DWORD
i_need NoSetDir,BYTE
i_need CURBUF, DWORD
i_need DIRSTART,WORD
i_need THISDPB,DWORD
i_need NAME1,BYTE
i_need LASTENT,WORD
i_need SATTRIB,BYTE
i_need ATTRIB,BYTE
i_need ALLOWED,BYTE
i_need FAILERR,BYTE
i_need RenBuf,BYTE
i_need FastOpenFlg,BYTE ; DOS 3.3
i_need FastOpenTable,BYTE ; DOS 3.3
i_need WFP_START,WORD ; DOS 3.3
i_need HIGH_SECTOR,WORD ; F.C. >32mb
BREAK <DOS_MkDir - Make a directory entry>
; Inputs:
; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL
; terminated)
; [CURR_DIR_END] Points to end of Current dir part of string
; ( = -1 if current dir not involved, else
; Points to first char after last "/" of current dir part)
; [THISCDS] Points to CDS being used
; (Low word = -1 if NUL CDS (Net direct request))
; Function:
; Make a new directory
; Returns:
; Carry Clear
; No error
; Carry Set
; AX is error code
; error_path_not_found
; Bad path (not in curr dir part if present)
; error_bad_curr_dir
; Bad path in current directory part of path
; error_access_denied
; Already exists, device name
; DS preserved, Others destroyed
procedure DOS_MKDIR,NEAR
DOSAssume CS,<DS>,"DOS_MkDir"
ASSUME ES:NOTHING
Invoke TestNet
JNC local_mkdir
IF NOT Installed
transfer NET_MKDIR
ELSE
MOV AX,(multNET SHL 8) OR 3
INT 2FH
return
ENDIF
NODEACCERRJ:
MOV AX,error_access_denied
BadRet:
STC
LeaveCrit critDisk
return
PATHNFJ:
LeaveCrit critDisk
transfer SET_MKND_ERR ; Map the MakeNode error and return
LOCAL_MKDIR:
EnterCrit critDisk
;
; MakeNode requires an SFT to fiddle with. We Use a temp spot (RENBUF)
;
MOV WORD PTR [THISSFT+2],SS
MOV WORD PTR [THISSFT],OFFSET DOSGroup:RenBuf
;
; NOTE: Need WORD PTR because MASM takes type of
; TempSFT (byte) instead of type of sf_mft (word).
;
MOV WORD PTR RenBuf.sf_mft,0 ; make sure SHARER won't complain.
MOV AL,attr_directory
invoke MAKENODE
JC PATHNFJ
CMP AX,3
JZ NODEACCERRJ ; Can't make a device into a directory
LES BP,[THISDPB] ; Makenode zaps this
LDS DI,[CURBUF]
ASSUME DS:NOTHING
SUB SI,DI
PUSH SI ; Pointer to dir_first
PUSH WORD PTR [DI.buf_sector+2] ;F.C. >32mb
PUSH WORD PTR [DI.buf_sector] ; Sector of new node
context DS
PUSH [DIRSTART] ; Parent for .. entry
XOR AX,AX
MOV [DIRSTART],AX ; Null directory
invoke NEWDIR
JC NODEEXISTSPOPDEL ; No room
invoke GETENT ; First entry
JC NODEEXISTSPOPDEL ; Screw up
LES DI,[CURBUF]
TEST ES:[DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000;
JNZ yesdirty ;LB. don't increment dirty count ;AN000;
invoke INC_DIRTY_COUNT ;LB. ;AN000;
OR ES:[DI.buf_flags],buf_dirty
yesdirty:
ADD DI,BUFINSIZ ; Point at buffer
MOV AX,202EH ; ". "
MOV DX,[DIRSTART] ; Point at itself
invoke SETDOTENT
MOV AX,2E2EH ; ".."
POP DX ; Parent
invoke SETDOTENT
LES BP,[THISDPB]
MOV [ALLOWED],allowed_FAIL + allowed_RETRY
POP DX ; Entry sector
POP [HIGH_SECTOR] ;F.C. >32mb
XOR AL,AL ; Pre read
invoke GETBUFFR
JC NODEEXISTSP
MOV DX,[DIRSTART]
LDS DI,[CURBUF]
ASSUME DS:NOTHING
OR [DI.buf_flags],buf_isDIR
POP SI ; dir_first pointer
ADD SI,DI
MOV [SI],DX
XOR DX,DX
MOV [SI+2],DX ; Zero size
MOV [SI+4],DX
DIRUP:
TEST [DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000;
JNZ yesdirty2 ;LB. don't increment dirty count ;AN000;
invoke INC_DIRTY_COUNT ;LB. ;AN000;
OR [DI.buf_flags],buf_dirty ; Dirty buffer
yesdirty2:
context DS
MOV AL,ES:[BP.dpb_drive]
invoke FLUSHBUF
MOV AX,error_access_denied
LeaveCrit critDisk
return
NODEEXISTSPOPDEL:
POP DX ; Parent
POP DX ; Entry sector
POP [HIGH_SECTOR] ; F.C. >32mb
LES BP,[THISDPB]
MOV [ALLOWED],allowed_FAIL + allowed_RETRY
XOR AL,AL ; Pre read
invoke GETBUFFR
JC NODEEXISTSP
LDS DI,[CURBUF]
ASSUME DS:NOTHING
OR [DI.buf_flags],buf_isDIR
POP SI ; dir_first pointer
ADD SI,DI
SUB SI,dir_first ;Point back to start of dir entry
MOV BYTE PTR [SI],0E5H ; Free the entry
CALL DIRUP ; Error doesn't matter since erroring anyway
NODEEXISTS:
JMP NODEACCERRJ
NODEEXISTSP:
POP SI ; Clean stack
JMP NODEEXISTS
EndProc DOS_MKDIR
BREAK <DOS_ChDir -- Verify a directory>
; Inputs:
; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL
; terminated)
; [CURR_DIR_END] Points to end of Current dir part of string
; ( = -1 if current dir not involved, else
; Points to first char after last "/" of current dir part)
; [THISCDS] Points to CDS being used May not be NUL
; Function:
; Validate the path for potential new current directory
; Returns:
; NOTE:
; [SATTRIB] is modified by this call
; Carry Clear
; CX is cluster number of the DIR, LOCAL CDS ONLY
; Caller must NOT set ID fields on a NET CDS.
; Carry Set
; AX is error code
; error_path_not_found
; Bad path
; error_access_denied
; device or file name
; DS preserved, Others destroyed
procedure DOS_CHDIR,NEAR
DOSAssume CS,<DS>,"DOS_Chdir"
ASSUME ES:NOTHING
Invoke TestNet
JNC LOCAL_CHDIR
IF NOT Installed
transfer NET_CHDIR
ELSE
MOV AX,(multNET SHL 8) OR 5
INT 2FH
return
ENDIF
LOCAL_CHDIR:
EnterCrit critDisk
TEST ES:[DI.curdir_flags],curdir_splice ;PTM.
JZ nojoin ;PTM.
MOV ES:[DI.curdir_ID],0FFFFH ;PTM.
nojoin:
MOV [NoSetDir],FALSE
MOV [SATTRIB],attr_directory+attr_system+attr_hidden
; Dir calls can find these
; DOS 3.3 6/24/86 FastOpen
OR [FastOpenFlg],FastOpen_Set ; set fastopen flag
invoke GetPath
PUSHF ;AN000;
AND [FastOpenFlg],Fast_yes ; clear it all ;AC000;
POPF ;AN000;
; DOS 3.3 6/24/86 FastOpen
MOV AX,error_path_not_found
JC ChDirDone
JNZ NOTDIRPATH ; Path not a DIR
MOV CX,[DIRSTART] ; Get cluster number
CLC
ChDirDone:
LeaveCrit critDisk
return
EndProc DOS_CHDIR
BREAK <DOS_RmDir -- Remove a directory>
; Inputs:
; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL
; terminated)
; [CURR_DIR_END] Points to end of Current dir part of string
; ( = -1 if current dir not involved, else
; Points to first char after last "/" of current dir part)
; [THISCDS] Points to CDS being used
; (Low word = -1 if NUL CDS (Net direct request))
; Function:
; Remove a directory
; NOTE: Attempt to remove current directory must be detected by caller
; Returns:
; NOTE:
; [SATTRIB] is modified by this call
; Carry Clear
; No error
; Carry Set
; AX is error code
; error_path_not_found
; Bad path (not in curr dir part if present)
; error_bad_curr_dir
; Bad path in current directory part of path
; error_access_denied
; device or file name, root directory
; Bad directory ('.' '..' messed up)
; DS preserved, Others destroyed
procedure DOS_RMDIR,NEAR
DOSAssume CS,<DS>,"DOS_RmDir"
ASSUME ES:NOTHING
Invoke TestNet
JNC Local_RmDIR
IF NOT Installed
transfer NET_RMDIR
ELSE
MOV AX,(multNET SHL 8) OR 1
INT 2FH
return
ENDIF
LOCAL_RMDIR:
EnterCrit critDisk
MOV [NoSetDir],0
MOV [SATTRIB],attr_directory+attr_system+attr_hidden
; Dir calls can find these
invoke GetPath
JC NOPATH ; Path not found
JNZ NOTDIRPATH ; Path not a DIR
MOV DI,[DIRSTART]
OR DI,DI ; Root ?
JNZ rmdir_get_buf ; No
JMP SHORT NOTDIRPATH
NOPATH:
MOV AX,error_path_not_found
JMP BadRet
NOTDIRPATHPOP:
POP AX ;F.C. >32mb
POP AX
NOTDIRPATHPOP2:
POP AX
NOTDIRPATH:
JMP NodeAccErrJ
rmdir_get_buf:
LDS DI,[CURBUF]
ASSUME DS:NOTHING
SUB BX,DI ; Compute true offset
PUSH BX ; Save entry pointer
PUSH WORD PTR [DI.buf_sector+2] ;F.C. >32mb
PUSH WORD PTR [DI.buf_sector] ; Save sector number
context DS
context ES
MOV DI,OFFSET DOSGROUP:NAME1
MOV AL,'?'
MOV CX,11
REP STOSB
XOR AL,AL
STOSB ; Nul terminate it
invoke STARTSRCH ; Set search
invoke GETENTRY ; Get start of directory
JC NOTDIRPATHPOP ; Screw up
MOV DS,WORD PTR [CURBUF+2]
ASSUME DS:NOTHING
MOV SI,BX
LODSW
CMP AX,(' ' SHL 8) OR '.' ; First entry '.'?
JNZ NOTDIRPATHPOP ; Nope
ADD SI,(SIZE dir_entry) - 2 ; Next entry
LODSW
CMP AX,('.' SHL 8) OR '.' ; Second entry '..'?
JNZ NOTDIRPATHPOP ; Nope
context DS
MOV [LASTENT],2 ; Skip . and ..
invoke GETENTRY ; Get next entry
JC NOTDIRPATHPOP ; Screw up
MOV [ATTRIB],attr_directory+attr_hidden+attr_system
invoke SRCH ; Do a search
JNC NOTDIRPATHPOP ; Found another entry!
CMP [FAILERR],0
JNZ NOTDIRPATHPOP ; Failure of search due to I 24 FAIL
LES BP,[THISDPB]
MOV BX,[DIRSTART]
;; FastSeek 10/27/86
invoke Delete_FSeek ; delete the fastseek entry
;; FastSeek 10/27/86
invoke RELEASE ; Release data in sub dir
JC NOTDIRPATHPOP ; Screw up
POP DX ; Sector # of entry
POP [HIGH_SECTOR] ; F.C. >32mb
MOV [ALLOWED],allowed_FAIL + allowed_RETRY
XOR AL,AL ; Pre read
invoke GETBUFFR ; Get sector back
JC NOTDIRPATHPOP2 ; Screw up
LDS DI,[CURBUF]
ASSUME DS:NOTHING
OR [DI.buf_flags],buf_isDIR
POP BX ; Pointer to start of entry
ADD BX,DI ; Corrected
MOV BYTE PTR [BX],0E5H ; Free the entry
;DOS 3.3 FastOpen 6/16/86 F.C.
PUSH DS
context DS
invoke FastOpen_Delete ; call fastopen to delete an entry
POP DS
;DOS 3.3 FastOpen 6/16/86 F.C.
JMP DIRUP ; In MKDIR, dirty buffer and flush
EndProc DOS_RMDIR
CODE ENDS
END
|