diff options
Diffstat (limited to '')
| -rw-r--r-- | v4.0/src/DOS/PATH.ASM | 363 |
1 files changed, 363 insertions, 0 deletions
diff --git a/v4.0/src/DOS/PATH.ASM b/v4.0/src/DOS/PATH.ASM new file mode 100644 index 0000000..5deed6c --- /dev/null +++ b/v4.0/src/DOS/PATH.ASM | |||
| @@ -0,0 +1,363 @@ | |||
| 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 | \ No newline at end of file | ||