summaryrefslogtreecommitdiff
path: root/v4.0/src/DOS/PATH.ASM
blob: 5deed6cbdf9cc19a4aa2a83e7e495ce737f5c267 (plain) (blame)
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
;	SCCSID = @(#)path.asm	1.1 85/04/10
TITLE	PATH - Directory related system calls
NAME	PATH

;
; Directory related system calls.  These will be passed direct text of the
; pathname from the user.  They will need to be passed through the macro
; expander prior to being sent through the low-level stuff.  I/O specs are
; defined in DISPATCH.	The system calls are:
;
;   $CURRENT_DIR  Written
;   $RMDIR	  Written
;   $CHDIR	  Written
;   $MKDIR	  Written
;
;
;   Modification history:
;
;	Created: ARR 4 April 1983
;		 MZ 10 May 1983     CurrentDir implemented
;		 MZ 11 May 1983     RmDir, ChDir, MkDir implemented
;		 EE 19 Oct 1983     RmDir no longer allows you to delete a
;				    current directory.
;		 MZ 19 Jan 1983     Brain damaged applications rely on success
;				    values of AL.
.xlist
;
; get the appropriate segment definitions
;
include dosseg.asm

CODE	SEGMENT BYTE PUBLIC  'CODE'
	ASSUME	SS:DOSGroup,CS:DOSGroup

.xcref
INCLUDE DOSSYM.INC
INCLUDE DEVSYM.INC
.cref
.list

	EXTRN	DOS_MkDir:NEAR,DOS_RmDir:NEAR

	I_Need	ThisCDS,DWORD		; pointer to Current CDS
	I_Need	WFP_Start,WORD		; pointer to beginning of directory text
	I_Need	Curr_Dir_End,WORD	; offset to end of directory part
	I_Need	OpenBuf,128		; temp spot for translated name
	I_need	fSplice,BYTE		; TRUE => do splice
	I_Need	NoSetDir,BYTE		; TRUE => no exact match on splice
	I_Need	cMeta,BYTE
	I_Need	DrvErr,BYTE							;AN000;

BREAK <$CURRENT_DIR - dump the current directory into user space>
;
;   Assembler usage:
;		LDS	SI,area
;		MOV	DL,drive
;		INT	21h
;	    ; DS:SI is a pointer to 64 byte area that contains drive
;	    ; current directory.
;   Error returns:
;	    AX = error_invalid_drive
;

	procedure $CURRENT_DIR,NEAR
	ASSUME	CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
	EnterCrit   critDisk
	MOV	AL,DL			; get drive number (0=def, 1=A)
	Invoke	GetVisDrv		; grab it
	JNC	CurrentValidate 	; no error -> go and validate dir
CurdirErr:
	LeaveCrit   critDisk
	MOV	AL,[DrvErr]		;IFS.					;AN000;
	transfer SYS_RET_ERR		;IFS. make noise			;AN000;
CurrentValidate:
	SaveReg <DS,SI> 		; save destination
	LDS	SI,ThisCDS
	TEST	[SI].curdir_flags,curdir_isnet
	JNZ	DoCheck
; Random optimization nuked due to some utilities using GetCurrentDir to do
; media check.
;	CMP	[SI].curdir_id,0
;	JZ	GetDst
DoCheck:
	MOV	NoSetDir,0		; interested only in contents
	MOV	DI,OFFSET DOSGroup:OpenBuf
	Invoke	ValidateCDS		; output is ES:DI -> CDS
	SaveReg <ES,DI> 		; swap source and destination
	RestoreReg  <SI,DS>
GetDst:
	RestoreReg  <DI,ES>		; get real destination
	JC	CurdirErr
	ADD	SI,curdir_text
	ADD	SI,[SI.curdir_END]
	CMP	BYTE PTR [SI],'\'       ; root or subdirs present?
	JNZ	CurrentCopy
	INC	SI
CurrentCopy:
;	Invoke	FStrCpy
;; 10/29/86 E5 char
	PUSH	AX
	LODSB			      ; get char
	OR	AL,AL
	JZ	FOK
	CMP	AL,05
	JZ	FCHANGE
	JMP	FFF
FCPYNEXT:
	LODSB			      ; get char
FFF:
	CMP	AL,'\'                ; beginning of directory
	JNZ	FOK		      ; no
	STOSB			      ; put into user's buffer
	LODSB			      ; 1st char of dir is 05?
	CMP	AL,05H
	JNZ	FOK		      ; no
FCHANGE:
	MOV	AL,0E5H 	      ; make it E5
FOK:
	STOSB			      ; put into user's buffer
	OR	AL,AL		      ; final char
	JNZ	FCPYNEXT	      ; no
	POP	AX

;; 10/29/86 E5 char
	xor	AL,AL			; MZ 19 Jan 84
	LeaveCrit   critDisk
	transfer    Sys_Ret_OK		; no more, bye!
EndProc $Current_Dir

BREAK <$RmDir -- Remove a directory>

; Inputs:
;	DS:DX Points to asciz name
; Function:
;	Delete directory if empty
; Returns:
;	STD XENIX Return
;	AX = error_path_not_found If path bad
;	AX = error_access_denied If
;		Directory not empty
;		Path not directory
;		Root directory specified
;		Directory malformed (. and .. not first two entries)
;		User tries to delete a current directory
;	AX = error_current_directory

	procedure $RMDIR,NEAR
	ASSUME	CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup

	push	dx			; Save ptr to name
	push	ds
	mov	si,dx			; Load ptr into si
	mov	di,offset DOSGroup:OpenBuf	; di = ptr to buf for trans name
	push	di
	Invoke	TransPathNoSet		; Translate the name
	pop	di			; di = ptr to buf for trans name
	jnc	rmlset			; If transpath succeeded, continue
	pop	ds
	pop	dx			; Restore the	 name
	error	error_path_not_found	; Otherwise, return an error

rmlset:
	CMP	cMeta,-1		;   if (cMeta >= 0)
	Jnz	rmerr			;	return (-1);
	Context ES
	xor	al,al			; al = 0 , ie drive a:
rmloop: Invoke	GetCDSFromDrv		; Get curdir for drive in al
	jc	rmcont			; If error, exit loop & cont normally
	Invoke	StrCmp			; Are the 2 paths the same?
	jz	rmerr			; Yes, report error.
	inc	al			; No, inc al to next drive number
	jmp	rmloop			; Go check next drive.

rmerr:
	pop	ds
	pop	dx			; Restore the	 name
	error	error_current_directory ;  error

rmcont:
	pop	ds
	pop	dx			; Restore the	 name
	MOV	SI,OFFSET DOSGroup:DOS_RmDIR
	JMP	DoDirCall
EndProc $RMDIR

BREAK <$ChDir -- Change current directory on a drive>

;
; $ChDir - Top-level change directory system call.  This call is responsible
; for setting up the CDS for the specified drive appropriately.  There are
; several cases to consider:
;
;   o	Local, simple CDS.  In this case, we take the input path and convert
;	it into a WFP.	We verify the existance of this directory and then
;	copy the WFP into the CDS and set up the ID field to point to the
;	directory cluster.
;   o	Net CDS.  We form the path from the root (including network prefix)
;	and verify its existance (via DOS_Chdir).  If successful, we copy the
;	WFP back into the CDS.
;   o	SUBST'ed CDS.  This is no different than the local, simple CDS.
;   o	JOIN'ed CDS.  This is trouble as there are two CDS's at work.  If we
;	call TransPath, we will get the PHYSICAL CDS that the path refers to
;	and the PHYSICAL WFP that the input path refers to.  This is perfectly
;	good for the validation but not for currency.  We call TransPathNoSet
;	to process the path but to return the logical CDS and the logical
;	path.  We then copy the logical path into the logical CDS.
;
; Inputs:
;	DS:DX Points to asciz name
; Returns:
;	STD XENIX Return
;	AX = chdir_path_not_found if error

	procedure $CHDIR,NEAR
	ASSUME	CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
	MOV	DI,OFFSET DOSGroup:OpenBuf  ; spot for translated name
	MOV	SI,DX			; get source
	Invoke	TransPath		; go munge the path and get real CDS
	JNC	ChDirCrack		; no errors, try path
ChDirErrP:
	MOV	AL,error_path_not_found
ChdirErr:
	transfer    SYS_Ret_Err 	; oops!

ChDirCrack:
	Assume	DS:DOSGroup
	CMP	cMeta,-1		; No meta chars allowed.
	JNZ	ChDirErrP
;
; We cannot do a ChDir (yet) on a raw CDS.  This is treated as a path not
; found.
;
	LES	DI,ThisCDS
	CMP	DI,-1			;   if (ThisCDS == NULL)
	JZ	ChDirErrP		;	error ();
 ;
 ; Find out if the directory exists.
 ;
	Invoke	DOS_ChDir
	JC	ChDirErr
;
; Get back CDS to see if a join as seen.  Set the currency pointer (only if
; not network).  If one was seen, all we need to do is copy in the text
;
	LES	DI,ThisCDS
	TEST	ES:[DI].curdir_flags,curdir_splice
	JZ	GotCDS
;
; The CDS was joined.  Let's go back and grab the logical CDS.
;
	SaveReg <ES,DI,CX>		; save CDS and cluster...
	Invoke	Get_User_Stack		; get original text
	ASSUME	DS:NOTHING
	MOV	DI,[SI.User_DX]
	MOV	DS,[SI.User_DS]
	MOV	SI,OFFSET DOSGroup:OpenBuf  ; spot for translated name
	XCHG	SI,DI
	XOR	AL,AL			; do no splicing
	SaveReg <DI>
	Invoke	TransPathNoSet		; Munge path
	RestoreReg  <SI>
	Assume	DS:DOSGroup
;
; There should NEVER be an error here.
;
IF FALSE
	JNC SKipErr
	fmt <>,<>,<"$p: Internal CHDIR error\n">
SkipErr:
ENDIF
	LES	DI,ThisCDS		; get new CDS
	MOV	ES:[DI].curdir_ID,-1	; no valid cluster here...
	RestoreReg  <CX,DI,ES>
;
; ES:DI point to the physical CDS, CX is the ID (local only)
;
GotCDS:
;
; wfp_start points to the text.  See if it is long enough
;
	CALL	Check_PathLen		;PTM.					;AN000;
	JA	ChDirErrP
	TEST	ES:[DI].curdir_flags,curdir_isnet
	JNZ	SkipRecency
	TEST	ES:[DI].curdir_flags,curdir_splice   ;PTM. for Join and Subst	;AN000;
	JZ	setdirclus			     ;PTM.			;AN000;
	MOV	CX,-1				     ;PTM.			;AN000;
setdirclus:
	MOV	ES:[DI].curdir_id,CX
	LES	DI,ThisCDS		; get logical CDS
SkipRecency:
	invoke	FStrCpy
	XOR	AL,AL
	transfer    Sys_Ret_OK
EndProc $CHDIR

BREAK <$MkDir - Make a directory entry>
; Inputs:
;	DS:DX Points to asciz name
; Function:
;	Make a new directory
; Returns:
;	STD XENIX Return
;	AX = mkdir_path_not_found if path bad
;	AX = mkdir_access_denied  If
;		Directory cannot be created
;		Node already exists
;		Device name given
;		Disk or directory(root) full

	procedure $MKDIR,NEAR
	ASSUME	CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
	MOV	SI,OFFSET DOSGroup:DOS_MkDir
DoDirCall:
	MOV	DI,OFFSET DOSGroup:OpenBuf  ; spot for translated name
	SaveReg <SI>
	MOV	SI,DX			; get source
	Invoke	TransPath		; go munge the path
	RestoreReg  <SI>
	JNC	MkDirCrack		; no errors, try path
MkErrP:
	MOV	AL,error_Path_Not_Found    ; oops!
MkErr:
	transfer    Sys_Ret_Err
MkDirCrack:
	CMP	cMeta,-1
	JNZ	MkErrP

	PUSH	SI			;PTM.					;AN000;
	CALL	Check_PathLen		;PTM.  check path len > 67 ?		;AN000;
	POP	SI			;PTM.					;AN000;
	JBE	pathok			;PTM.					;AN000;
	MOV	AL,error_Access_Denied	;PTM. ops!
	transfer Sys_Ret_Err		;PTM.
pathok:
	CALL	SI			; go get file
	ASSUME	ES:NOTHING
	JC	MkErr			; no errors
	transfer    Sys_Ret_OK
EndProc $MKDIR

; Inputs:
;	nothing
; Function:
;	check if final path length greater than 67
; Returns:
;	Above flag set if > 67

	procedure Check_PathLen,NEAR
	ASSUME	CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup

	MOV	SI,Wfp_Start
  entry Check_PathLen2
	Context <DS>
	SaveReg <CX>
	invoke	DStrLen
	CMP	CX,DirStrLen
	RestoreReg  <CX>
	ret
EndProc Check_PathLen
CODE ENDS
END