     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                                  [list -]
    26          ******************       warning: redefining multi-line macro `struc' [-w+pp-macro-redef-multi]
    14                              <4> [list -]
    14                              <3> [list -]
     3                              <2> 
     4                              <2> addsection DOSSTART, align=16 PUBLIC class=DOSSTART
     5                              <2> ; (no prior section) ; DOSSTART		ENDS
     6                              <2> 
     7                              <2> addsection DOSSTARTJUMP, align=1 PUBLIC class=START
     8                              <2> ; (no prior section) ; DOSSTARTJUMP		ENDS
     9                              <2> 
    10                              <2> addsection CONSTANTS, align=2 PUBLIC class=CONST
    11                              <2> ; (no prior section) ; CONSTANTS	ENDS
    12                              <2> 
    13                              <2> addsection DATA, align=2 PUBLIC class=DATA
    14                              <2> ; (no prior section) ; DATA		ENDS
    15                              <2> 
    16                              <2> addsection TABLE, align=2 PUBLIC class=TABLE
    17                              <2> ; (no prior section) ; TABLE		ENDS
    18                              <2> 
    19                              <2> addsection DOSDATATABLE, align=2 PUBLIC class=DOSDATACODE
    20                              <2> ; (no prior section) ; DOSDATATABLE		ENDS
    21                              <2> 
    22                              <2> addsection DOSDATACODE, align=1 PUBLIC class=DOSDATACODE
    23                              <2> ; (no prior section) ; DOSDATACODE		ENDS
    24                              <2> 
    25                              <2> addsection DOSBIODATA, align=2 PUBLIC class=DOSBIODATA
    26                              <2> 
    27                              <2> addsection LAST, align=16 PUBLIC class=LAST
    28                              <2> ; (no prior section) ; LAST		ENDS
    29                              <2> 
    30                              <2> group DOSGROUP DOSSTART DOSSTARTJUMP CONSTANTS DATA TABLE DOSDATATABLE DOSDATACODE DOSBIODATA LAST
     8                              <1> 
     9                              <1> %include "dcodeseg.nas"
     1                              <2> 
     2                              <2> %ifndef DCODESEGNAS
     3                              <2> %assign DCODESEGNAS 1
     4                              <2> 
     5                              <2> section DOSCODETABLE align=2 PUBLIC class=DOSCODE
     6                              <2> ; (no prior section) ; DOSCODETABLE		ENDS
     7                              <2> section DOSCODECODE align=1 PUBLIC class=DOSCODE
     8                              <2> ; (no prior section) ; DOSCODECODE		ENDS
     9                              <2> section DOSBIOCODE align=2 PUBLIC class=DOSCODE
    10                              <2> section BIOCODE	align=2 PUBLIC class=DOSCODE
    11                              <2> 
    12                              <2> %ifnidni DOSENTRYGROUP, DOSCODEGROUP
    13                              <2>  group DOSCODEGROUP DOSCODETABLE DOSCODECODE DOSBIOCODE BIOCODE
    14                              <2> %endif
    15                              <2> 
    16                              <2> %endif
    10                              <1> 
    11                              <1> section LAST
    12                              <1> ; (no prior section) ; LAST		ENDS
    31                                  
    32                                  [list +]
    33                                  section DOSCODECODE
    34                                  [list -]
    34          ******************       warning: out: ... for DOS Version 4.00 ... [-w+user]
    34          ******************       warning: out: BPB.INC... [-w+user]
    34          ******************       warning: out: ... CLONE version build switch on ... [-w+user]
    34          ******************       warning: out: DEVSYM.INC... [-w+user]
    41                                  
    42                                  	EXTRN	DOS_MkDir:NEAR,DOS_RmDir:NEAR
    43                                  
    44                                  	I_Need	ThisCDS,DWORD		; pointer to Current CDS
    45                                  	I_Need	WFP_Start,WORD		; pointer to beginning of directory text
    46                                  	I_Need	Curr_Dir_End,WORD	; offset to end of directory part
    47                                  	I_Need	OpenBuf,128		; temp spot for translated name
    48                                  	I_need	fSplice,BYTE		; TRUE => do splice
    49                                  	I_Need	NoSetDir,BYTE		; TRUE => no exact match on splice
    50                                  	I_Need	cMeta,BYTE
    51                                  	I_Need	DrvErr,BYTE							;AN000;
    52                                  
    53                                  BREAK <$CURRENT_DIR - dump the current directory into user space>
    54                                  ;
    55                                  ;   Assembler usage:
    56                                  ;		LDS	SI,area
    57                                  ;		MOV	DL,drive
    58                                  ;		INT	21h
    59                                  ;	    ; DS:SI is a pointer to 64 byte area that contains drive
    60                                  ;	    ; current directory.
    61                                  ;   Error returns:
    62                                  ;	    AX = error_invalid_drive
    63                                  ;
    64                                  
    65                                  	procedure D_CURRENT_DIR,NEAR
    65          ******************       warning: proc D_CURRENT_DIR... [-w+user]
    66                                  	ASSUME	DS:NOTHING,ES:NOTHING,SS:DOSGROUP
    67 00000000 E8(0000)                	EnterCrit   critDisk
    68 00000003 88D0                    	MOV	AL,DL			; get drive number (0=def, 1=A)
    69 00000005 E8(0000)                	Invoke	GetVisDrv		; grab it
    70 00000008 730A                    	JNC	CurrentValidate 	; no error -> go and validate dir
    71                                  CurdirErr:
    72 0000000A E8(0000)                	LeaveCrit   critDisk
    73 0000000D 36A0[0000]              	MOV	AL,[ss:DrvErr]		;IFS.					;AN000;
    74 00000011 E9(0000)                	transfer SYS_RET_ERR		;IFS. make noise			;AN000;
    75                                  CurrentValidate:
    76 00000014 1E56                    	SaveReg <DS,SI> 		; save destination
    77 00000016 36C536[0000]            	LDS	SI,[ss:ThisCDS]
    78 0000001B F744430080              	TEST	word [SI + curdir_flags],curdir_isnet
    79 00000020 7500                    	JNZ	DoCheck
    80                                  ; Random optimization nuked due to some utilities using GetCurrentDir to do
    81                                  ; media check.
    82                                  ;	CMP	[SI].curdir_id,0
    83                                  ;	JZ	GetDst
    84                                  DoCheck:
    85 00000022 36C606[0000]00          	MOV	byte [ss:NoSetDir],0		; interested only in contents
    86                                  DOSGroup equ DOSGROUP	; NASM port equate
    87 00000028 BF[0000]                	MOV	DI,OFFSET OpenBuf wrt DOSGroup
    88 0000002B E8(0000)                	Invoke	ValidateCDS		; output is ES:DI -> CDS
    89 0000002E 0657                    	SaveReg <ES,DI> 		; swap source and destination
    90 00000030 5E1F                    	RestoreReg  <SI,DS>
    91                                  GetDst:
    92 00000032 5F07                    	RestoreReg  <DI,ES>		; get real destination
    93 00000034 72D4                    	JC	CurdirErr
    94 00000036 83C600                  	ADD	SI,curdir_text
    95                                  curdir_END equ curdir_end	; NASM port equate
    96 00000039 03744F                  	ADD	SI,[SI + curdir_END]
    97 0000003C 803C5C                  	CMP	BYTE PTR [SI],'\'       ; root or subdirs present?
    98 0000003F 7501                    	JNZ	CurrentCopy
    99 00000041 46                      	INC	SI
   100                                  CurrentCopy:
   101                                  ;	Invoke	FStrCpy
   102                                  ;; 10/29/86 E5 char
   103 00000042 50                      	PUSH	AX
   104 00000043 AC                      	LODSB			      ; get char
   105 00000044 08C0                    	OR	AL,AL
   106 00000046 7414                    	JZ	FOK
   107 00000048 3C05                    	CMP	AL,05
   108 0000004A 740E                    	JZ	FCHANGE
   109 0000004C EB02                    	JMP	FFF
   110 0000004E 90                      	nop	; identicalise
   111                                  FCPYNEXT:
   112 0000004F AC                      	LODSB			      ; get char
   113                                  FFF:
   114 00000050 3C5C                    	CMP	AL,'\'                ; beginning of directory
   115 00000052 7508                    	JNZ	FOK		      ; no
   116 00000054 AA                      	STOSB			      ; put into user's buffer
   117 00000055 AC                      	LODSB			      ; 1st char of dir is 05?
   118 00000056 3C05                    	CMP	AL,05H
   119 00000058 7502                    	JNZ	FOK		      ; no
   120                                  FCHANGE:
   121 0000005A B0E5                    	MOV	AL,0E5H 	      ; make it E5
   122                                  FOK:
   123 0000005C AA                      	STOSB			      ; put into user's buffer
   124 0000005D 08C0                    	OR	AL,AL		      ; final char
   125 0000005F 75EE                    	JNZ	FCPYNEXT	      ; no
   126 00000061 58                      	POP	AX
   127                                  
   128                                  ;; 10/29/86 E5 char
   129 00000062 30C0                    	xor	AL,AL			; MZ 19 Jan 84
   130 00000064 E8(0000)                	LeaveCrit   critDisk
   131 00000067 E9(0000)                	transfer    Sys_Ret_OK		; no more, bye!
   132                                  EndProc D_Current_Dir
   133                                  
   134                                  BREAK <$RmDir -- Remove a directory>
   135                                  
   136                                  ; Inputs:
   137                                  ;	DS:DX Points to asciz name
   138                                  ; Function:
   139                                  ;	Delete directory if empty
   140                                  ; Returns:
   141                                  ;	STD XENIX Return
   142                                  ;	AX = error_path_not_found If path bad
   143                                  ;	AX = error_access_denied If
   144                                  ;		Directory not empty
   145                                  ;		Path not directory
   146                                  ;		Root directory specified
   147                                  ;		Directory malformed (. and .. not first two entries)
   148                                  ;		User tries to delete a current directory
   149                                  ;	AX = error_current_directory
   150                                  
   151                                  	procedure D_RMDIR,NEAR
   151          ******************       warning: proc D_RMDIR... [-w+user]
   152                                  	ASSUME	DS:NOTHING,ES:NOTHING,SS:DOSGroup
   153                                  
   154 0000006A 52                      	push	dx			; Save ptr to name
   155 0000006B 1E                      	push	ds
   156 0000006C 89D6                    	mov	si,dx			; Load ptr into si
   157 0000006E BF[0000]                	mov	di,offset OpenBuf wrt DOSGroup	; di = ptr to buf for trans name
   158 00000071 57                      	push	di
   159 00000072 E8(0000)                	Invoke	TransPathNoSet		; Translate the name
   160 00000075 5F                      	pop	di			; di = ptr to buf for trans name
   161 00000076 7306                    	jnc	rmlset			; If transpath succeeded, continue
   162 00000078 1F                      	pop	ds
   163                                   assume ds:nothing
   164 00000079 5A                      	pop	dx			; Restore the	 name
   165 0000007A B003EB93                	error	error_path_not_found	; Otherwise, return an error
   166                                  
   167                                  rmlset:
   168 0000007E 36803E[0000]FF          	CMP	byte [ss:cMeta],-1		;   if (cMeta >= 0)
   169 00000084 7512                    	Jnz	rmerr			;	return (-1);
   170 00000086 1607                    	Context ES
   171 00000088 30C0                    	xor	al,al			; al = 0 , ie drive a:
   172 0000008A E8(0000)                rmloop: Invoke	GetCDSFromDrv		; Get curdir for drive in al
   173 0000008D 720F                    	jc	rmcont			; If error, exit loop & cont normally
   174 0000008F E8(0000)                	Invoke	StrCmp			; Are the 2 paths the same?
   175 00000092 7404                    	jz	rmerr			; Yes, report error.
   176 00000094 FEC0                    	inc	al			; No, inc al to next drive number
   177 00000096 EBF2                    	jmp	rmloop			; Go check next drive.
   178                                  
   179                                  rmerr:
   180 00000098 1F                      	pop	ds
   181                                   assume ds:nothing
   182 00000099 5A                      	pop	dx			; Restore the	 name
   183 0000009A B010EBDE                	error	error_current_directory ;  error
   184                                  
   185                                  rmcont:
   186 0000009E 1F                      	pop	ds
   187                                   assume ds:nothing
   188 0000009F 5A                      	pop	dx			; Restore the	 name
   189                                  DOS_RmDIR equ DOS_RmDir	; NASM port label
   190 000000A0 BE[0000]                	MOV	SI,OFFSET DOS_RmDIR
   191 000000A3 E97F00                  	JMP	strict near DoDirCall
   192                                  EndProc D_RMDIR
   193                                  
   194                                  BREAK <$ChDir -- Change current directory on a drive>
   195                                  
   196                                  ;
   197                                  ; $ChDir - Top-level change directory system call.  This call is responsible
   198                                  ; for setting up the CDS for the specified drive appropriately.  There are
   199                                  ; several cases to consider:
   200                                  ;
   201                                  ;   o	Local, simple CDS.  In this case, we take the input path and convert
   202                                  ;	it into a WFP.	We verify the existance of this directory and then
   203                                  ;	copy the WFP into the CDS and set up the ID field to point to the
   204                                  ;	directory cluster.
   205                                  ;   o	Net CDS.  We form the path from the root (including network prefix)
   206                                  ;	and verify its existance (via DOS_Chdir).  If successful, we copy the
   207                                  ;	WFP back into the CDS.
   208                                  ;   o	SUBST'ed CDS.  This is no different than the local, simple CDS.
   209                                  ;   o	JOIN'ed CDS.  This is trouble as there are two CDS's at work.  If we
   210                                  ;	call TransPath, we will get the PHYSICAL CDS that the path refers to
   211                                  ;	and the PHYSICAL WFP that the input path refers to.  This is perfectly
   212                                  ;	good for the validation but not for currency.  We call TransPathNoSet
   213                                  ;	to process the path but to return the logical CDS and the logical
   214                                  ;	path.  We then copy the logical path into the logical CDS.
   215                                  ;
   216                                  ; Inputs:
   217                                  ;	DS:DX Points to asciz name
   218                                  ; Returns:
   219                                  ;	STD XENIX Return
   220                                  ;	AX = chdir_path_not_found if error
   221                                  
   222                                  	procedure D_CHDIR,NEAR
   222          ******************       warning: proc D_CHDIR... [-w+user]
   223                                  	ASSUME	DS:NOTHING,ES:NOTHING,SS:DOSGroup
   224 000000A6 BF[0000]                	MOV	DI,OFFSET OpenBuf wrt DOSGroup  ; spot for translated name
   225 000000A9 89D6                    	MOV	SI,DX			; get source
   226 000000AB E8(0000)                	Invoke	TransPath		; go munge the path and get real CDS
   227 000000AE 7304                    	JNC	ChDirCrack		; no errors, try path
   228                                  ChDirErrP:
   229 000000B0 B003                    	MOV	AL,error_path_not_found
   230                                  ChdirErr:
   231 000000B2 EBE8                    	transfer    SYS_Ret_Err 	; oops!
   232                                  
   233                                  ChDirCrack:
   234                                  	Assume	DS:DOSGroup
   235 000000B4 803E[0000]FF            	CMP	byte [cMeta],-1		; No meta chars allowed.
   236 000000B9 75F5                    	JNZ	ChDirErrP
   237                                  ;
   238                                  ; We cannot do a ChDir (yet) on a raw CDS.  This is treated as a path not
   239                                  ; found.
   240                                  ;
   241 000000BB C43E[0000]              	LES	DI,[ThisCDS]
   242 000000BF 83FFFF                  	CMP	DI,-1			;   if (ThisCDS == NULL)
   243 000000C2 74EC                    	JZ	ChDirErrP		;	error ();
   244                                   ;
   245                                   ; Find out if the directory exists.
   246                                   ;
   247 000000C4 E8(0000)                	Invoke	DOS_ChDir
   248                                  ChDirErr equ ChdirErr	; NASM port label
   249 000000C7 72E9                    	JC	ChDirErr
   250                                  ;
   251                                  ; Get back CDS to see if a join as seen.  Set the currency pointer (only if
   252                                  ; not network).  If one was seen, all we need to do is copy in the text
   253                                  ;
   254 000000C9 C43E[0000]              	LES	DI,[ThisCDS]
   255 000000CD 26F745430020            	TEST	word [ES:DI + curdir_flags],curdir_splice
   256 000000D3 7425                    	JZ	GotCDS
   257                                  ;
   258                                  ; The CDS was joined.  Let's go back and grab the logical CDS.
   259                                  ;
   260 000000D5 065751                  	SaveReg <ES,DI,CX>		; save CDS and cluster...
   261 000000D8 E8(0000)                	Invoke	Get_User_Stack		; get original text
   262                                  	ASSUME	DS:NOTHING
   263                                  User_DX equ user_DX	; NASM port equate
   264 000000DB 8B7C06                  	MOV	DI,[SI + User_DX]
   265                                  User_DS equ user_DS	; NASM port equate
   266 000000DE 8E5C0E                  	MOV	DS,[SI + User_DS]
   267                                   assume ds:nothing
   268 000000E1 BE[0000]                	MOV	SI,OFFSET OpenBuf wrt DOSGroup  ; spot for translated name
   269 000000E4 87F7                    	XCHG	SI,DI
   270 000000E6 30C0                    	XOR	AL,AL			; do no splicing
   271 000000E8 57                      	SaveReg <DI>
   272 000000E9 E8(0000)                	Invoke	TransPathNoSet		; Munge path
   273 000000EC 5E                      	RestoreReg  <SI>
   274                                  	Assume	DS:DOSGroup
   275                                  ;
   276                                  ; There should NEVER be an error here.
   277                                  ;
   278                                  %IF FALSE
   279                                  SKipErr equ SkipErr	; NASM port label
   280                                  	JNC SKipErr
   281                                  	fmt <>,<>,<"$p: Internal CHDIR error\n">
   282                                  SkipErr:
   283                                  %ENDIF
   284 000000ED C43E[0000]              	LES	DI,[ThisCDS]		; get new CDS
   285 000000F1 26C74549FFFF            	MOV	word [ES:DI + curdir_ID],-1	; no valid cluster here...
   286 000000F7 595F07                  	RestoreReg  <CX,DI,ES>
   287                                  ;
   288                                  ; ES:DI point to the physical CDS, CX is the ID (local only)
   289                                  ;
   290                                  GotCDS:
   291                                  ;
   292                                  ; wfp_start points to the text.  See if it is long enough
   293                                  ;
   294 000000FA E85200                  	CALL	Check_PathLen		;PTM.					;AN000;
   295 000000FD 77B1                    	JA	ChDirErrP
   296 000000FF 26F745430080            	TEST	word [ES:DI + curdir_flags],curdir_isnet
   297 00000105 7513                    	JNZ	SkipRecency
   298 00000107 26F745430020            	TEST	word [ES:DI + curdir_flags],curdir_splice   ;PTM. for Join and Subst	;AN000;
   299 0000010D 7403                    	JZ	setdirclus			     ;PTM.			;AN000;
   300 0000010F B9FFFF                  	MOV	CX,-1				     ;PTM.			;AN000;
   301                                  setdirclus:
   302                                  curdir_id equ curdir_ID	; NASM port equate
   303 00000112 26894D49                	MOV	[ES:DI + curdir_id],CX
   304 00000116 C43E[0000]              	LES	DI,[ThisCDS]		; get logical CDS
   305                                  SkipRecency:
   306 0000011A E8(0000)                	invoke	FStrCpy
   307 0000011D 30C0                    	XOR	AL,AL
   308 0000011F E9(0000)                	transfer    Sys_Ret_OK
   309                                  EndProc D_CHDIR
   310                                  
   311                                  BREAK <$MkDir - Make a directory entry>
   312                                  ; Inputs:
   313                                  ;	DS:DX Points to asciz name
   314                                  ; Function:
   315                                  ;	Make a new directory
   316                                  ; Returns:
   317                                  ;	STD XENIX Return
   318                                  ;	AX = mkdir_path_not_found if path bad
   319                                  ;	AX = mkdir_access_denied  If
   320                                  ;		Directory cannot be created
   321                                  ;		Node already exists
   322                                  ;		Device name given
   323                                  ;		Disk or directory(root) full
   324                                  
   325                                  	procedure D_MKDIR,NEAR
   325          ******************       warning: proc D_MKDIR... [-w+user]
   326                                  	ASSUME	DS:NOTHING,ES:NOTHING,SS:DOSGroup
   327 00000122 BE[0000]                	MOV	SI,OFFSET DOS_MkDir
   328                                  DoDirCall:
   329 00000125 BF[0000]                	MOV	DI,OFFSET OpenBuf wrt DOSGroup  ; spot for translated name
   330 00000128 56                      	SaveReg <SI>
   331 00000129 89D6                    	MOV	SI,DX			; get source
   332 0000012B E8(0000)                	Invoke	TransPath		; go munge the path
   333 0000012E 5E                      	RestoreReg  <SI>
   334 0000012F 7305                    	JNC	MkDirCrack		; no errors, try path
   335                                  MkErrP:
   336                                  error_Path_Not_Found equ error_path_not_found	; NASM port equate
   337 00000131 B003                    	MOV	AL,error_Path_Not_Found    ; oops!
   338                                  MkErr:
   339 00000133 E9(0000)                	transfer    Sys_Ret_Err
   340                                  MkDirCrack:
   341 00000136 36803E[0000]FF          	CMP	byte [ss:cMeta],-1
   342 0000013C 75F3                    	JNZ	MkErrP
   343                                  
   344 0000013E 56                      	PUSH	SI			;PTM.					;AN000;
   345 0000013F E80D00                  	CALL	Check_PathLen		;PTM.  check path len > 67 ?		;AN000;
   346 00000142 5E                      	POP	SI			;PTM.					;AN000;
   347 00000143 7604                    	JBE	pathok			;PTM.					;AN000;
   348                                  error_Access_Denied equ error_access_denied	; NASM port equate
   349 00000145 B005                    	MOV	AL,error_Access_Denied	;PTM. ops!
   350 00000147 EBEA                    	transfer Sys_Ret_Err		;PTM.
   351                                  pathok:
   352 00000149 FFD6                    	CALL	SI			; go get file
   353                                  	ASSUME	ES:NOTHING
   354 0000014B 72E6                    	JC	MkErr			; no errors
   355 0000014D EBD0                    	transfer    Sys_Ret_OK
   356                                  EndProc D_MKDIR
   357                                  
   358                                  ; Inputs:
   359                                  ;	nothing
   360                                  ; Function:
   361                                  ;	check if final path length greater than 67
   362                                  ; Returns:
   363                                  ;	Above flag set if > 67
   364                                  
   365                                  	procedure Check_PathLen,NEAR
   365          ******************       warning: proc Check_PathLen... [-w+user]
   366                                  	ASSUME	DS:NOTHING,ES:NOTHING,SS:DOSGroup
   367                                  
   368                                  Wfp_Start equ WFP_Start	; NASM port label
   369 0000014F 368B36[0000]            	MOV	SI,[ss:Wfp_Start]
   370                                    entry Check_PathLen2
   371 00000154 161F                    	Context <DS>
   372 00000156 51                      	SaveReg <CX>
   373 00000157 E8(0000)                	invoke	DStrLen
   374                                  DirStrLen equ DIRSTRLEN	; NASM port equate
   375 0000015A 83F943                  	CMP	CX,DirStrLen
   376 0000015D 59                      	RestoreReg  <CX>
   377 0000015E C3                      	ret
   378                                  EndProc Check_PathLen
   379                                  END
   380                                  
   381                                  
