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

wirehaze git hosting

MZ is back!
[MS-DOS.git] / v4.0 / src / DOS / PATH.ASM
1 ; SCCSID = @(#)path.asm 1.1 85/04/10
2 TITLE PATH - Directory related system calls
3 NAME PATH
4
5 ;
6 ; Directory related system calls. These will be passed direct text of the
7 ; pathname from the user. They will need to be passed through the macro
8 ; expander prior to being sent through the low-level stuff. I/O specs are
9 ; defined in DISPATCH. The system calls are:
10 ;
11 ; $CURRENT_DIR Written
12 ; $RMDIR Written
13 ; $CHDIR Written
14 ; $MKDIR Written
15 ;
16 ;
17 ; Modification history:
18 ;
19 ; Created: ARR 4 April 1983
20 ; MZ 10 May 1983 CurrentDir implemented
21 ; MZ 11 May 1983 RmDir, ChDir, MkDir implemented
22 ; EE 19 Oct 1983 RmDir no longer allows you to delete a
23 ; current directory.
24 ; MZ 19 Jan 1983 Brain damaged applications rely on success
25 ; values of AL.
26 .xlist
27 ;
28 ; get the appropriate segment definitions
29 ;
30 include dosseg.asm
31
32 CODE SEGMENT BYTE PUBLIC 'CODE'
33 ASSUME SS:DOSGroup,CS:DOSGroup
34
35 .xcref
36 INCLUDE DOSSYM.INC
37 INCLUDE DEVSYM.INC
38 .cref
39 .list
40
41 EXTRN DOS_MkDir:NEAR,DOS_RmDir:NEAR
42
43 I_Need ThisCDS,DWORD ; pointer to Current CDS
44 I_Need WFP_Start,WORD ; pointer to beginning of directory text
45 I_Need Curr_Dir_End,WORD ; offset to end of directory part
46 I_Need OpenBuf,128 ; temp spot for translated name
47 I_need fSplice,BYTE ; TRUE => do splice
48 I_Need NoSetDir,BYTE ; TRUE => no exact match on splice
49 I_Need cMeta,BYTE
50 I_Need DrvErr,BYTE ;AN000;
51
52 BREAK <$CURRENT_DIR - dump the current directory into user space>
53 ;
54 ; Assembler usage:
55 ; LDS SI,area
56 ; MOV DL,drive
57 ; INT 21h
58 ; ; DS:SI is a pointer to 64 byte area that contains drive
59 ; ; current directory.
60 ; Error returns:
61 ; AX = error_invalid_drive
62 ;
63
64 procedure $CURRENT_DIR,NEAR
65 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
66 EnterCrit critDisk
67 MOV AL,DL ; get drive number (0=def, 1=A)
68 Invoke GetVisDrv ; grab it
69 JNC CurrentValidate ; no error -> go and validate dir
70 CurdirErr:
71 LeaveCrit critDisk
72 MOV AL,[DrvErr] ;IFS. ;AN000;
73 transfer SYS_RET_ERR ;IFS. make noise ;AN000;
74 CurrentValidate:
75 SaveReg <DS,SI> ; save destination
76 LDS SI,ThisCDS
77 TEST [SI].curdir_flags,curdir_isnet
78 JNZ DoCheck
79 ; Random optimization nuked due to some utilities using GetCurrentDir to do
80 ; media check.
81 ; CMP [SI].curdir_id,0
82 ; JZ GetDst
83 DoCheck:
84 MOV NoSetDir,0 ; interested only in contents
85 MOV DI,OFFSET DOSGroup:OpenBuf
86 Invoke ValidateCDS ; output is ES:DI -> CDS
87 SaveReg <ES,DI> ; swap source and destination
88 RestoreReg <SI,DS>
89 GetDst:
90 RestoreReg <DI,ES> ; get real destination
91 JC CurdirErr
92 ADD SI,curdir_text
93 ADD SI,[SI.curdir_END]
94 CMP BYTE PTR [SI],'\' ; root or subdirs present?
95 JNZ CurrentCopy
96 INC SI
97 CurrentCopy:
98 ; Invoke FStrCpy
99 ;; 10/29/86 E5 char
100 PUSH AX
101 LODSB ; get char
102 OR AL,AL
103 JZ FOK
104 CMP AL,05
105 JZ FCHANGE
106 JMP FFF
107 FCPYNEXT:
108 LODSB ; get char
109 FFF:
110 CMP AL,'\' ; beginning of directory
111 JNZ FOK ; no
112 STOSB ; put into user's buffer
113 LODSB ; 1st char of dir is 05?
114 CMP AL,05H
115 JNZ FOK ; no
116 FCHANGE:
117 MOV AL,0E5H ; make it E5
118 FOK:
119 STOSB ; put into user's buffer
120 OR AL,AL ; final char
121 JNZ FCPYNEXT ; no
122 POP AX
123
124 ;; 10/29/86 E5 char
125 xor AL,AL ; MZ 19 Jan 84
126 LeaveCrit critDisk
127 transfer Sys_Ret_OK ; no more, bye!
128 EndProc $Current_Dir
129
130 BREAK <$RmDir -- Remove a directory>
131
132 ; Inputs:
133 ; DS:DX Points to asciz name
134 ; Function:
135 ; Delete directory if empty
136 ; Returns:
137 ; STD XENIX Return
138 ; AX = error_path_not_found If path bad
139 ; AX = error_access_denied If
140 ; Directory not empty
141 ; Path not directory
142 ; Root directory specified
143 ; Directory malformed (. and .. not first two entries)
144 ; User tries to delete a current directory
145 ; AX = error_current_directory
146
147 procedure $RMDIR,NEAR
148 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
149
150 push dx ; Save ptr to name
151 push ds
152 mov si,dx ; Load ptr into si
153 mov di,offset DOSGroup:OpenBuf ; di = ptr to buf for trans name
154 push di
155 Invoke TransPathNoSet ; Translate the name
156 pop di ; di = ptr to buf for trans name
157 jnc rmlset ; If transpath succeeded, continue
158 pop ds
159 pop dx ; Restore the name
160 error error_path_not_found ; Otherwise, return an error
161
162 rmlset:
163 CMP cMeta,-1 ; if (cMeta >= 0)
164 Jnz rmerr ; return (-1);
165 Context ES
166 xor al,al ; al = 0 , ie drive a:
167 rmloop: Invoke GetCDSFromDrv ; Get curdir for drive in al
168 jc rmcont ; If error, exit loop & cont normally
169 Invoke StrCmp ; Are the 2 paths the same?
170 jz rmerr ; Yes, report error.
171 inc al ; No, inc al to next drive number
172 jmp rmloop ; Go check next drive.
173
174 rmerr:
175 pop ds
176 pop dx ; Restore the name
177 error error_current_directory ; error
178
179 rmcont:
180 pop ds
181 pop dx ; Restore the name
182 MOV SI,OFFSET DOSGroup:DOS_RmDIR
183 JMP DoDirCall
184 EndProc $RMDIR
185
186 BREAK <$ChDir -- Change current directory on a drive>
187
188 ;
189 ; $ChDir - Top-level change directory system call. This call is responsible
190 ; for setting up the CDS for the specified drive appropriately. There are
191 ; several cases to consider:
192 ;
193 ; o Local, simple CDS. In this case, we take the input path and convert
194 ; it into a WFP. We verify the existance of this directory and then
195 ; copy the WFP into the CDS and set up the ID field to point to the
196 ; directory cluster.
197 ; o Net CDS. We form the path from the root (including network prefix)
198 ; and verify its existance (via DOS_Chdir). If successful, we copy the
199 ; WFP back into the CDS.
200 ; o SUBST'ed CDS. This is no different than the local, simple CDS.
201 ; o JOIN'ed CDS. This is trouble as there are two CDS's at work. If we
202 ; call TransPath, we will get the PHYSICAL CDS that the path refers to
203 ; and the PHYSICAL WFP that the input path refers to. This is perfectly
204 ; good for the validation but not for currency. We call TransPathNoSet
205 ; to process the path but to return the logical CDS and the logical
206 ; path. We then copy the logical path into the logical CDS.
207 ;
208 ; Inputs:
209 ; DS:DX Points to asciz name
210 ; Returns:
211 ; STD XENIX Return
212 ; AX = chdir_path_not_found if error
213
214 procedure $CHDIR,NEAR
215 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
216 MOV DI,OFFSET DOSGroup:OpenBuf ; spot for translated name
217 MOV SI,DX ; get source
218 Invoke TransPath ; go munge the path and get real CDS
219 JNC ChDirCrack ; no errors, try path
220 ChDirErrP:
221 MOV AL,error_path_not_found
222 ChdirErr:
223 transfer SYS_Ret_Err ; oops!
224
225 ChDirCrack:
226 Assume DS:DOSGroup
227 CMP cMeta,-1 ; No meta chars allowed.
228 JNZ ChDirErrP
229 ;
230 ; We cannot do a ChDir (yet) on a raw CDS. This is treated as a path not
231 ; found.
232 ;
233 LES DI,ThisCDS
234 CMP DI,-1 ; if (ThisCDS == NULL)
235 JZ ChDirErrP ; error ();
236 ;
237 ; Find out if the directory exists.
238 ;
239 Invoke DOS_ChDir
240 JC ChDirErr
241 ;
242 ; Get back CDS to see if a join as seen. Set the currency pointer (only if
243 ; not network). If one was seen, all we need to do is copy in the text
244 ;
245 LES DI,ThisCDS
246 TEST ES:[DI].curdir_flags,curdir_splice
247 JZ GotCDS
248 ;
249 ; The CDS was joined. Let's go back and grab the logical CDS.
250 ;
251 SaveReg <ES,DI,CX> ; save CDS and cluster...
252 Invoke Get_User_Stack ; get original text
253 ASSUME DS:NOTHING
254 MOV DI,[SI.User_DX]
255 MOV DS,[SI.User_DS]
256 MOV SI,OFFSET DOSGroup:OpenBuf ; spot for translated name
257 XCHG SI,DI
258 XOR AL,AL ; do no splicing
259 SaveReg <DI>
260 Invoke TransPathNoSet ; Munge path
261 RestoreReg <SI>
262 Assume DS:DOSGroup
263 ;
264 ; There should NEVER be an error here.
265 ;
266 IF FALSE
267 JNC SKipErr
268 fmt <>,<>,<"$p: Internal CHDIR error\n">
269 SkipErr:
270 ENDIF
271 LES DI,ThisCDS ; get new CDS
272 MOV ES:[DI].curdir_ID,-1 ; no valid cluster here...
273 RestoreReg <CX,DI,ES>
274 ;
275 ; ES:DI point to the physical CDS, CX is the ID (local only)
276 ;
277 GotCDS:
278 ;
279 ; wfp_start points to the text. See if it is long enough
280 ;
281 CALL Check_PathLen ;PTM. ;AN000;
282 JA ChDirErrP
283 TEST ES:[DI].curdir_flags,curdir_isnet
284 JNZ SkipRecency
285 TEST ES:[DI].curdir_flags,curdir_splice ;PTM. for Join and Subst ;AN000;
286 JZ setdirclus ;PTM. ;AN000;
287 MOV CX,-1 ;PTM. ;AN000;
288 setdirclus:
289 MOV ES:[DI].curdir_id,CX
290 LES DI,ThisCDS ; get logical CDS
291 SkipRecency:
292 invoke FStrCpy
293 XOR AL,AL
294 transfer Sys_Ret_OK
295 EndProc $CHDIR
296
297 BREAK <$MkDir - Make a directory entry>
298 ; Inputs:
299 ; DS:DX Points to asciz name
300 ; Function:
301 ; Make a new directory
302 ; Returns:
303 ; STD XENIX Return
304 ; AX = mkdir_path_not_found if path bad
305 ; AX = mkdir_access_denied If
306 ; Directory cannot be created
307 ; Node already exists
308 ; Device name given
309 ; Disk or directory(root) full
310
311 procedure $MKDIR,NEAR
312 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
313 MOV SI,OFFSET DOSGroup:DOS_MkDir
314 DoDirCall:
315 MOV DI,OFFSET DOSGroup:OpenBuf ; spot for translated name
316 SaveReg <SI>
317 MOV SI,DX ; get source
318 Invoke TransPath ; go munge the path
319 RestoreReg <SI>
320 JNC MkDirCrack ; no errors, try path
321 MkErrP:
322 MOV AL,error_Path_Not_Found ; oops!
323 MkErr:
324 transfer Sys_Ret_Err
325 MkDirCrack:
326 CMP cMeta,-1
327 JNZ MkErrP
328
329 PUSH SI ;PTM. ;AN000;
330 CALL Check_PathLen ;PTM. check path len > 67 ? ;AN000;
331 POP SI ;PTM. ;AN000;
332 JBE pathok ;PTM. ;AN000;
333 MOV AL,error_Access_Denied ;PTM. ops!
334 transfer Sys_Ret_Err ;PTM.
335 pathok:
336 CALL SI ; go get file
337 ASSUME ES:NOTHING
338 JC MkErr ; no errors
339 transfer Sys_Ret_OK
340 EndProc $MKDIR
341
342 ; Inputs:
343 ; nothing
344 ; Function:
345 ; check if final path length greater than 67
346 ; Returns:
347 ; Above flag set if > 67
348
349 procedure Check_PathLen,NEAR
350 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
351
352 MOV SI,Wfp_Start
353 entry Check_PathLen2
354 Context <DS>
355 SaveReg <CX>
356 invoke DStrLen
357 CMP CX,DirStrLen
358 RestoreReg <CX>
359 ret
360 EndProc Check_PathLen
361 CODE ENDS
362 END
363 \1a