     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                                  %if 0	; useless test due to commented out optimisation
    79                                  	TEST	word [SI + curdir_flags],curdir_isnet
    80                                  	JNZ	DoCheck
    81                                  ; Random optimization nuked due to some utilities using GetCurrentDir to do
    82                                  ; media check.
    83                                  ;	CMP	[SI].curdir_id,0
    84                                  ;	JZ	GetDst
    85                                  DoCheck:
    86                                  %endif
    87 0000001B 36C606[0000]00          	MOV	byte [ss:NoSetDir],0		; interested only in contents
    88                                  DOSGroup equ DOSGROUP	; NASM port equate
    89 00000021 BF[0000]                	MOV	DI,OFFSET OpenBuf wrt DOSGroup
    90 00000024 E8(0000)                	Invoke	ValidateCDS		; output is ES:DI -> CDS
    91 00000027 0657                    	SaveReg <ES,DI> 		; swap source and destination
    92 00000029 5E1F                    	RestoreReg  <SI,DS>
    93                                  GetDst:
    94 0000002B 5F07                    	RestoreReg  <DI,ES>		; get real destination
    95 0000002D 72DB                    	JC	CurdirErr
    96 0000002F 83C600                  	ADD	SI,curdir_text
    97                                  curdir_END equ curdir_end	; NASM port equate
    98 00000032 03744F                  	ADD	SI,[SI + curdir_END]
    99 00000035 803C5C                  	CMP	BYTE PTR [SI],'\'       ; root or subdirs present?
   100 00000038 7501                    	JNZ	CurrentCopy
   101 0000003A 46                      	INC	SI
   102                                  CurrentCopy:
   103                                  ;	Invoke	FStrCpy
   104                                  ;; 10/29/86 E5 char
   105 0000003B 50                      	PUSH	AX
   106 0000003C AC                      	LODSB			      ; get char
   107 0000003D 08C0                    	OR	AL,AL
   108 0000003F 7414                    	JZ	FOK
   109 00000041 3C05                    	CMP	AL,05
   110 00000043 740E                    	JZ	FCHANGE
   111 00000045 EB02                    	JMP	FFF
   112 00000047 90                      	nop	; identicalise
   113                                  FCPYNEXT:
   114 00000048 AC                      	LODSB			      ; get char
   115                                  FFF:
   116 00000049 3C5C                    	CMP	AL,'\'                ; beginning of directory
   117 0000004B 7508                    	JNZ	FOK		      ; no
   118 0000004D AA                      	STOSB			      ; put into user's buffer
   119 0000004E AC                      	LODSB			      ; 1st char of dir is 05?
   120 0000004F 3C05                    	CMP	AL,05H
   121 00000051 7502                    	JNZ	FOK		      ; no
   122                                  FCHANGE:
   123 00000053 B0E5                    	MOV	AL,0E5H 	      ; make it E5
   124                                  FOK:
   125 00000055 AA                      	STOSB			      ; put into user's buffer
   126 00000056 08C0                    	OR	AL,AL		      ; final char
   127 00000058 75EE                    	JNZ	FCPYNEXT	      ; no
   128 0000005A 58                      	POP	AX
   129                                  
   130                                  ;; 10/29/86 E5 char
   131                                  	; xor	AL,AL			; MZ 19 Jan 84
   132 0000005B B80001                  	mov ax, 100h			; according to the interrupt list
   133 0000005E E8(0000)                	LeaveCrit   critDisk
   134 00000061 E9(0000)                	transfer    Sys_Ret_OK		; no more, bye!
   135                                  EndProc D_Current_Dir
   136                                  
   137                                  BREAK <$RmDir -- Remove a directory>
   138                                  
   139                                  ; Inputs:
   140                                  ;	DS:DX Points to asciz name
   141                                  ; Function:
   142                                  ;	Delete directory if empty
   143                                  ; Returns:
   144                                  ;	STD XENIX Return
   145                                  ;	AX = error_path_not_found If path bad
   146                                  ;	AX = error_access_denied If
   147                                  ;		Directory not empty
   148                                  ;		Path not directory
   149                                  ;		Root directory specified
   150                                  ;		Directory malformed (. and .. not first two entries)
   151                                  ;		User tries to delete a current directory
   152                                  ;	AX = error_current_directory
   153                                  
   154                                  	procedure D_RMDIR,NEAR
   154          ******************       warning: proc D_RMDIR... [-w+user]
   155                                  	ASSUME	DS:NOTHING,ES:NOTHING,SS:DOSGroup
   156                                  
   157 00000064 52                      	push	dx			; Save ptr to name
   158 00000065 1E                      	push	ds
   159 00000066 89D6                    	mov	si,dx			; Load ptr into si
   160 00000068 BF[0000]                	mov	di,offset OpenBuf wrt DOSGroup	; di = ptr to buf for trans name
   161 0000006B 57                      	push	di
   162 0000006C E8(0000)                	Invoke	TransPathNoSet		; Translate the name
   163 0000006F 5F                      	pop	di			; di = ptr to buf for trans name
   164 00000070 7306                    	jnc	rmlset			; If transpath succeeded, continue
   165 00000072 1F                      	pop	ds
   166                                   assume ds:nothing
   167 00000073 5A                      	pop	dx			; Restore the	 name
   168 00000074 B003EB99                	error	error_path_not_found	; Otherwise, return an error
   169                                  
   170                                  rmlset:
   171 00000078 36803E[0000]FF          	CMP	byte [ss:cMeta],-1		;   if (cMeta >= 0)
   172 0000007E 7512                    	Jnz	rmerr			;	return (-1);
   173 00000080 1607                    	Context ES
   174 00000082 30C0                    	xor	al,al			; al = 0 , ie drive a:
   175 00000084 E8(0000)                rmloop: Invoke	GetCDSFromDrv		; Get curdir for drive in al
   176 00000087 720F                    	jc	rmcont			; If error, exit loop & cont normally
   177 00000089 E8(0000)                	Invoke	StrCmp			; Are the 2 paths the same?
   178 0000008C 7404                    	jz	rmerr			; Yes, report error.
   179 0000008E FEC0                    	inc	al			; No, inc al to next drive number
   180 00000090 EBF2                    	jmp	rmloop			; Go check next drive.
   181                                  
   182                                  rmerr:
   183 00000092 1F                      	pop	ds
   184                                   assume ds:nothing
   185 00000093 5A                      	pop	dx			; Restore the	 name
   186 00000094 B010EBDE                	error	error_current_directory ;  error
   187                                  
   188                                  rmcont:
   189 00000098 1F                      	pop	ds
   190                                   assume ds:nothing
   191 00000099 5A                      	pop	dx			; Restore the	 name
   192                                  DOS_RmDIR equ DOS_RmDir	; NASM port label
   193 0000009A BE[0000]                	MOV	SI,OFFSET DOS_RmDIR
   194 0000009D E97F00                  	JMP	strict near DoDirCall
   195                                  EndProc D_RMDIR
   196                                  
   197                                  BREAK <$ChDir -- Change current directory on a drive>
   198                                  
   199                                  ;
   200                                  ; $ChDir - Top-level change directory system call.  This call is responsible
   201                                  ; for setting up the CDS for the specified drive appropriately.  There are
   202                                  ; several cases to consider:
   203                                  ;
   204                                  ;   o	Local, simple CDS.  In this case, we take the input path and convert
   205                                  ;	it into a WFP.	We verify the existance of this directory and then
   206                                  ;	copy the WFP into the CDS and set up the ID field to point to the
   207                                  ;	directory cluster.
   208                                  ;   o	Net CDS.  We form the path from the root (including network prefix)
   209                                  ;	and verify its existance (via DOS_Chdir).  If successful, we copy the
   210                                  ;	WFP back into the CDS.
   211                                  ;   o	SUBST'ed CDS.  This is no different than the local, simple CDS.
   212                                  ;   o	JOIN'ed CDS.  This is trouble as there are two CDS's at work.  If we
   213                                  ;	call TransPath, we will get the PHYSICAL CDS that the path refers to
   214                                  ;	and the PHYSICAL WFP that the input path refers to.  This is perfectly
   215                                  ;	good for the validation but not for currency.  We call TransPathNoSet
   216                                  ;	to process the path but to return the logical CDS and the logical
   217                                  ;	path.  We then copy the logical path into the logical CDS.
   218                                  ;
   219                                  ; Inputs:
   220                                  ;	DS:DX Points to asciz name
   221                                  ; Returns:
   222                                  ;	STD XENIX Return
   223                                  ;	AX = chdir_path_not_found if error
   224                                  
   225                                  	procedure D_CHDIR,NEAR
   225          ******************       warning: proc D_CHDIR... [-w+user]
   226                                  	ASSUME	DS:NOTHING,ES:NOTHING,SS:DOSGroup
   227 000000A0 BF[0000]                	MOV	DI,OFFSET OpenBuf wrt DOSGroup  ; spot for translated name
   228 000000A3 89D6                    	MOV	SI,DX			; get source
   229 000000A5 E8(0000)                	Invoke	TransPath		; go munge the path and get real CDS
   230 000000A8 7304                    	JNC	ChDirCrack		; no errors, try path
   231                                  ChDirErrP:
   232 000000AA B003                    	MOV	AL,error_path_not_found
   233                                  ChdirErr:
   234 000000AC EBE8                    	transfer    SYS_Ret_Err 	; oops!
   235                                  
   236                                  ChDirCrack:
   237                                  	Assume	DS:DOSGroup
   238 000000AE 803E[0000]FF            	CMP	byte [cMeta],-1		; No meta chars allowed.
   239 000000B3 75F5                    	JNZ	ChDirErrP
   240                                  ;
   241                                  ; We cannot do a ChDir (yet) on a raw CDS.  This is treated as a path not
   242                                  ; found.
   243                                  ;
   244 000000B5 C43E[0000]              	LES	DI,[ThisCDS]
   245 000000B9 83FFFF                  	CMP	DI,-1			;   if (ThisCDS == NULL)
   246 000000BC 74EC                    	JZ	ChDirErrP		;	error ();
   247                                   ;
   248                                   ; Find out if the directory exists.
   249                                   ;
   250 000000BE E8(0000)                	Invoke	DOS_ChDir
   251                                  ChDirErr equ ChdirErr	; NASM port label
   252 000000C1 72E9                    	JC	ChDirErr
   253                                  ;
   254                                  ; Get back CDS to see if a join as seen.  Set the currency pointer (only if
   255                                  ; not network).  If one was seen, all we need to do is copy in the text
   256                                  ;
   257 000000C3 C43E[0000]              	LES	DI,[ThisCDS]
   258 000000C7 26F745430020            	TEST	word [ES:DI + curdir_flags],curdir_splice
   259 000000CD 7425                    	JZ	GotCDS
   260                                  ;
   261                                  ; The CDS was joined.  Let's go back and grab the logical CDS.
   262                                  ;
   263 000000CF 065751                  	SaveReg <ES,DI,CX>		; save CDS and cluster...
   264 000000D2 E8(0000)                	Invoke	Get_User_Stack		; get original text
   265                                  	ASSUME	DS:NOTHING
   266                                  User_DX equ user_DX	; NASM port equate
   267 000000D5 8B7C06                  	MOV	DI,[SI + User_DX]
   268                                  User_DS equ user_DS	; NASM port equate
   269 000000D8 8E5C0E                  	MOV	DS,[SI + User_DS]
   270                                   assume ds:nothing
   271 000000DB BE[0000]                	MOV	SI,OFFSET OpenBuf wrt DOSGroup  ; spot for translated name
   272 000000DE 87F7                    	XCHG	SI,DI
   273 000000E0 30C0                    	XOR	AL,AL			; do no splicing
   274 000000E2 57                      	SaveReg <DI>
   275 000000E3 E8(0000)                	Invoke	TransPathNoSet		; Munge path
   276 000000E6 5E                      	RestoreReg  <SI>
   277                                  	Assume	DS:DOSGroup
   278                                  ;
   279                                  ; There should NEVER be an error here.
   280                                  ;
   281                                  %IF FALSE
   282                                  SKipErr equ SkipErr	; NASM port label
   283                                  	JNC SKipErr
   284                                  	fmt <>,<>,<"$p: Internal CHDIR error\n">
   285                                  SkipErr:
   286                                  %ENDIF
   287 000000E7 C43E[0000]              	LES	DI,[ThisCDS]		; get new CDS
   288 000000EB 26C74549FFFF            	MOV	word [ES:DI + curdir_ID],-1	; no valid cluster here...
   289 000000F1 595F07                  	RestoreReg  <CX,DI,ES>
   290                                  ;
   291                                  ; ES:DI point to the physical CDS, CX is the ID (local only)
   292                                  ;
   293                                  GotCDS:
   294                                  ;
   295                                  ; wfp_start points to the text.  See if it is long enough
   296                                  ;
   297 000000F4 E85200                  	CALL	Check_PathLen		;PTM.					;AN000;
   298 000000F7 77B1                    	JA	ChDirErrP
   299 000000F9 26F745430080            	TEST	word [ES:DI + curdir_flags],curdir_isnet
   300 000000FF 7513                    	JNZ	SkipRecency
   301 00000101 26F745430020            	TEST	word [ES:DI + curdir_flags],curdir_splice   ;PTM. for Join and Subst	;AN000;
   302 00000107 7403                    	JZ	setdirclus			     ;PTM.			;AN000;
   303 00000109 B9FFFF                  	MOV	CX,-1				     ;PTM.			;AN000;
   304                                  setdirclus:
   305                                  curdir_id equ curdir_ID	; NASM port equate
   306 0000010C 26894D49                	MOV	[ES:DI + curdir_id],CX
   307 00000110 C43E[0000]              	LES	DI,[ThisCDS]		; get logical CDS
   308                                  SkipRecency:
   309 00000114 E8(0000)                	invoke	FStrCpy
   310 00000117 30C0                    	XOR	AL,AL
   311 00000119 E9(0000)                	transfer    Sys_Ret_OK
   312                                  EndProc D_CHDIR
   313                                  
   314                                  BREAK <$MkDir - Make a directory entry>
   315                                  ; Inputs:
   316                                  ;	DS:DX Points to asciz name
   317                                  ; Function:
   318                                  ;	Make a new directory
   319                                  ; Returns:
   320                                  ;	STD XENIX Return
   321                                  ;	AX = mkdir_path_not_found if path bad
   322                                  ;	AX = mkdir_access_denied  If
   323                                  ;		Directory cannot be created
   324                                  ;		Node already exists
   325                                  ;		Device name given
   326                                  ;		Disk or directory(root) full
   327                                  
   328                                  	procedure D_MKDIR,NEAR
   328          ******************       warning: proc D_MKDIR... [-w+user]
   329                                  	ASSUME	DS:NOTHING,ES:NOTHING,SS:DOSGroup
   330 0000011C BE[0000]                	MOV	SI,OFFSET DOS_MkDir
   331                                  DoDirCall:
   332 0000011F BF[0000]                	MOV	DI,OFFSET OpenBuf wrt DOSGroup  ; spot for translated name
   333 00000122 56                      	SaveReg <SI>
   334 00000123 89D6                    	MOV	SI,DX			; get source
   335 00000125 E8(0000)                	Invoke	TransPath		; go munge the path
   336 00000128 5E                      	RestoreReg  <SI>
   337 00000129 7305                    	JNC	MkDirCrack		; no errors, try path
   338                                  MkErrP:
   339                                  error_Path_Not_Found equ error_path_not_found	; NASM port equate
   340 0000012B B003                    	MOV	AL,error_Path_Not_Found    ; oops!
   341                                  MkErr:
   342 0000012D E9(0000)                	transfer    Sys_Ret_Err
   343                                  MkDirCrack:
   344 00000130 36803E[0000]FF          	CMP	byte [ss:cMeta],-1
   345 00000136 75F3                    	JNZ	MkErrP
   346                                  
   347 00000138 56                      	PUSH	SI			;PTM.					;AN000;
   348 00000139 E80D00                  	CALL	Check_PathLen		;PTM.  check path len > 67 ?		;AN000;
   349 0000013C 5E                      	POP	SI			;PTM.					;AN000;
   350 0000013D 7604                    	JBE	pathok			;PTM.					;AN000;
   351                                  error_Access_Denied equ error_access_denied	; NASM port equate
   352 0000013F B005                    	MOV	AL,error_Access_Denied	;PTM. ops!
   353 00000141 EBEA                    	transfer Sys_Ret_Err		;PTM.
   354                                  pathok:
   355 00000143 FFD6                    	CALL	SI			; go get file
   356                                  	ASSUME	ES:NOTHING
   357 00000145 72E6                    	JC	MkErr			; no errors
   358 00000147 EBD0                    	transfer    Sys_Ret_OK
   359                                  EndProc D_MKDIR
   360                                  
   361                                  ; Inputs:
   362                                  ;	nothing
   363                                  ; Function:
   364                                  ;	check if final path length greater than 67
   365                                  ; Returns:
   366                                  ;	Above flag set if > 67
   367                                  
   368                                  	procedure Check_PathLen,NEAR
   368          ******************       warning: proc Check_PathLen... [-w+user]
   369                                  	ASSUME	DS:NOTHING,ES:NOTHING,SS:DOSGroup
   370                                  
   371                                  Wfp_Start equ WFP_Start	; NASM port label
   372 00000149 368B36[0000]            	MOV	SI,[ss:Wfp_Start]
   373                                    entry Check_PathLen2
   374 0000014E 161F                    	Context <DS>
   375 00000150 51                      	SaveReg <CX>
   376 00000151 E8(0000)                	invoke	DStrLen
   377                                  DirStrLen equ DIRSTRLEN	; NASM port equate
   378 00000154 83F943                  	CMP	CX,DirStrLen
   379 00000157 59                      	RestoreReg  <CX>
   380 00000158 C3                      	ret
   381                                  EndProc Check_PathLen
   382                                  END
   383                                  
   384                                  
