FUNCS.FDO
上传用户:xiaogehua
上传日期:2007-01-08
资源大小:1183k
文件大小:66k
源码类别:

操作系统开发

开发平台:

Asm

  1. ;    File              : $FUNCS.FDO$
  2. ;
  3. ;    Description       :
  4. ;
  5. ;    Original Author   : DIGITAL RESEARCH
  6. ;
  7. ;    Last Edited By    : $CALDERA$
  8. ;
  9. ;-----------------------------------------------------------------------;
  10. ;    Copyright Work of Caldera, Inc. All Rights Reserved.
  11. ;      
  12. ;    THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
  13. ;    PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
  14. ;    ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
  15. ;    WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
  16. ;    THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
  17. ;    HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
  18. ;    AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
  19. ;    AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
  20. ;    COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
  21. ;    CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
  22. ;    TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
  23. ;    CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
  24. ;    AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
  25. ;    CIVIL LIABILITY.
  26. ;-----------------------------------------------------------------------;
  27. ;
  28. ;    *** Current Edit History ***
  29. ;    *** End of Current Edit History ***;
  30. ;    $Log$;
  31. ;    ENDLOG
  32. ; General function include module for FDOS.A86
  33. BDOS_CODE cseg
  34. public fdos_entry
  35. ;==========
  36. fdos_entry: ; FDOS module entry point
  37. ;==========
  38. ; On Entry:
  39. ; DS:DX -> parameter block
  40. ; On exit:
  41. ; AX = BX = return code
  42. ; (DS/ES corrupted)
  43. ; entry: DS:DX = argument
  44. ;
  45. ; exit: AX,BX = return code
  46. mov si,dx
  47. lodsw ; AX = FDOS number
  48. sub ax,39h ; base it at zero
  49.  jc fd_error ; stop if too low
  50. cmp ax,FDOS_MAX ; check if function in range
  51.  jae fd_error ; yes, continue
  52. push ds ; save parameter segment
  53. push dx ; save parameter offset
  54. push ax ; save sub-function
  55. mov bp,sp ; SS:BP -> working variables
  56. mov bx,ax
  57. add bx,ax
  58. add bx,ax
  59. call fdos_tbl[bx]
  60. add sp,3*WORD ; clean up stack
  61. mov ax,bx
  62. ret
  63. fd_error:
  64. mov ax,ED_FUNCTION ; return "invalid function"
  65. mov bx,ax
  66. ret
  67. fdos_tbl dw fdos_mkdir ; 39-make directory
  68. db 2
  69. dw fdos_rmdir ; 3A-remove directory
  70. db 2
  71. dw fdos_chdir ; 3B-change directory
  72. db 2
  73. dw fdos_creat ; 3C-create file
  74. db 4
  75. dw fdos_open ; 3D-open file
  76. db 4
  77. dw fdos_close ; 3E-close file
  78. db 1
  79. dw fdos_read ; 3F-read from file
  80. db 4
  81. dw fdos_write ; 40-write to file
  82. db 4
  83. dw fdos_unlink ; 41-delete file
  84. db 4
  85. dw fdos_lseek ; 42-set file pointer
  86. db 4
  87. dw fdos_chmod ; 43-get/set file attributes
  88. db 6
  89. dw fdos_ioctl ; 44-IOCTL emulation
  90. db 3
  91. dw fdos_dup ; 45-duplicate handle
  92. db 2
  93. dw fdos_fdup ; 46-force duplicate handle
  94. db 2
  95. dw fdos_curdir ; 47-get current directory
  96. db 3
  97. dw fdos_getdpb ;*48*disk information
  98. db 4
  99. dw fdos_flush ;*49*flush buffers
  100. db 0
  101. dw fdos_select ;*4A*drive select
  102. db 1
  103. dw fdos_exec ;*4B*create child PSP
  104. db 1
  105. dw fdos_exit ;*4C*close child PSP
  106. db 0
  107. dw fdos_fcb ;*4D*generic FCB call
  108. db 5
  109. dw fdos_first ; 4E-find first matching file
  110. db 4
  111. dw fdos_next ; 4F-find next matching file
  112. db 0
  113. dw fdos_commit ;*50*commit file
  114. db 1
  115. dw fdos_mknew ;*51*make new file
  116. db 4
  117. dw fdos_lock ;*52*lock/unlock block
  118. db 6
  119. dw fdos_mkddsc ; 53 build DDSC from BPB
  120. db 4
  121. dw fdos_ddio ;*54*Int 25/26 emulation
  122. db 6
  123. dw fdos_expand ;*55*expand file name
  124. db 6
  125. dw fdos_move ; 56-rename file
  126. db 6
  127. dw fdos_dattim ; 57-get/set file name
  128. db 4
  129. dw fdos_reopen_fcb ; 58-FCB reopen support function
  130. db 5
  131. FDOS_MAX equ (offset $ - offset fdos_tbl) / 3
  132. Public local_disk
  133. local_disk: ; continue execution within MXdisk semaphore
  134. ;----------
  135. ; This function will make local copies of the parameters
  136. ; and continue
  137. callf ss:lock_tables
  138. pop fdos_addr ; return address
  139. add sp,2*WORD ; discard return from call fdos_tbl[bx]
  140. ;    and function #
  141. pop si ; get parameter offset
  142. pop ax ; get parameter segment
  143. mov sp_save,sp ; save for re-entry/errors
  144. mov ds,ax ; DS:SI -> paremeter block
  145. fdos_reenter:
  146. push ss ! pop es ; ES = local data segment
  147. mov di,offset fdos_pb ; ES:DI -> local parameter block copy
  148. lodsw ! stosw ; load subfunction number
  149. mov es:fdos_info,si ; save it for BDOS return
  150. mov es:fdos_info+WORD,ds ; save parameter segment for return
  151. mov bx,ax
  152. add bx,ax
  153. add bx,ax ; BX = function # * 3
  154. mov cl,byte ptr fdos_tbl-(39h*(WORD+BYTE))+WORD[bx]
  155. mov ch,0
  156. ; get table of # of parameters
  157. mov es:fdos_info+2*WORD,cx ; save the parameter count
  158. rep movsw ; copy parameter block
  159. push es ! pop ds ; DS = SYSDAT
  160. mov ioexerr,0FFh ; assume default error code
  161. mov rwmode,0
  162. mov finddfcb_mask,DA_VOLUME*256
  163. xor ax,ax
  164. mov fdos_ret,ax ; assume success unless proven otherwise
  165. call fdos_addr ; call code following "call local_disk"
  166. mov ax,fdos_ret ; get return code, fall thru to exit
  167. Public fdos_error
  168. fdos_error:
  169. ;----------
  170. ; AX = return code
  171. mov sp,sp_save ; stack to entry value (for errors)
  172. mov si,offset fdos_pb+2 ; get local copy
  173. les di,dword ptr fdos_info ; get parameter block address
  174. mov cx,fdos_info+2*WORD ; get parameter block size
  175. rep movsw ; copy return values
  176. mov bx,ax
  177. callf ss:unlock_tables
  178. ret ; return to BDOS, which copies BX to AX
  179. Public fdos_restart
  180. fdos_restart: ; we want to restart the function after an error
  181. ;------------ ; we already have MXdisk
  182. ;
  183. mov sp,sp_save ; break out from low levels
  184. lds si,dword ptr fdos_info
  185. dec si ! dec si ; DS:SI -> parameter block
  186. jmps fdos_reenter ; try from scratch
  187. fdos_ED_ROOM:
  188. ;-----------
  189. mov ax,ED_ROOM ; no more files
  190. jmps fdos_error
  191. fdos_ED_DRIVE:
  192. ;-----------
  193. mov ax,ED_DRIVE ; bad drive
  194. jmps fdos_error
  195. fdos_ED_PATH:
  196. mov ax,ED_PATH ; invalid path or drive
  197. jmps fdos_error
  198. fdos_ED_PROTECT:
  199. mov ax,ED_PROTECT ; write protect error
  200. jmps fdos_error
  201. Public fdos_ED_ACCESS
  202. fdos_ED_ACCESS:
  203. mov ax,ED_ACCESS ; access denied error
  204. jmps fdos_error
  205. eject
  206. ; MAKE DIRECTORY (MKDIR)
  207. ; +----+----+----+----+----+----+
  208. ; |    39   |        name       |
  209. ; +----+----+----+----+----+----+
  210. ; entry:
  211. ; ------
  212. ; name: segmented address of ASCIIZ name
  213. ; exit:
  214. ; -----
  215. ; AX: 0000 or error code ( < 0)
  216. fdos_mkdir:
  217. ;----------
  218. call redir_asciiz_offer
  219. call local_disk ; get MXdisk, switch stack
  220. call path_prep_chk ; parse path, walk down the tree
  221. call finddfcbf ; find matching FCB
  222.  jnz mkdir_access ; file/dir exists, "access denied"
  223. call allocdir ; allocate a directory entry
  224. push ax ; save pointer to directory entry
  225. lea si,info_fcb+1 ; SI -> file name
  226. xchg ax,di ; DI -> DNAME
  227. mov cx,11
  228. rep movsb ; copy file name into directory buffer
  229. ; lea di,DATTS[si]
  230. mov al,DA_DIR
  231. stosb ; mark it as a directory
  232. xor ax,ax
  233. mov cx,(32-12)
  234. rep stosb ; zero remainder of new FCB
  235. pop si ; SI -> directory
  236. call stamp_dir_entry ; set time and date in FCB
  237. xor ax,ax
  238. call alloc_cluster ; Allocate a block
  239.  jc mkdir_err ; Report Error(no room on disk)
  240. mov si,dirp
  241. mov DBLOCK1[si],ax ; Initialize 1st block of fcb
  242. push ax ; save block
  243. call update_fat ; Write the fat to disk
  244. call update_dir ; Write the directory to disk
  245. pop ax ; now initialise the sub-directory
  246. call mkdir_init ;  '.' and '..' entries
  247. call update_dir ; update directory entry
  248. mov ax,5 ; return a magic value for some
  249. mov fdos_ret,ax ;  PD expansion program
  250. ret
  251. mkdir_err:
  252. ;---------
  253. mov bx,dirp ; can't make dir, no data space
  254. mov DNAME[bx],0E5h ; so release our directory entry
  255. call update_dir ; release this entry
  256. mkdir_access:
  257. jmp fdos_ED_ACCESS ; return "access denied" error
  258. chk_no_dot: ; reject "." and ".." names
  259. cmp info_fcb+1,'.'
  260.  je mkdir_access
  261. ret
  262. eject
  263. ; REMOVE DIRECTORY (RMDIR)
  264. ; +----+----+----+----+----+----+
  265. ; |    3A   |        name       |
  266. ; +----+----+----+----+----+----+
  267. ; entry:
  268. ; ------
  269. ; name: segmented address of ASCIIZ name
  270. ; exit:
  271. ; -----
  272. ; AX: 0000 or error code ( < 0)
  273. fdos_rmdir:
  274. ;----------
  275. call redir_asciiz_offer
  276. call local_disk ; get MXdisk, switch stack
  277. call path_prep_chk ; parse path to bottom level
  278. call finddfcbf ; try to locate directory entry
  279.  jz fdos_rmdir20 ; skip if we can't find it
  280. test DATTS[bx],DA_DIR ; check directory attribute
  281.  jz fdos_rmdir30 ; O.K. if a directory
  282. call chkcds ; make sure no-where current
  283.  jnc    fdos_rmdir40
  284. call path_prep ; redo as rmdir_ok may destroy info
  285. call finddfcbf ; find the entry again
  286. call rmdir_ok ; make sure not in use
  287. call finddfcbf ; find the entry again
  288. if PASSWORD
  289.     call    check_pwd_any      
  290. endif
  291. kill_entry:
  292. call kill_file ; actually delete entry
  293. update_dir_fat:
  294. call update_dir ; update directory entry
  295. jmp update_fat ; update file allocation table
  296. fdos_rmdir20:
  297. jmp fdos_ED_PATH ; "invalid path"
  298. fdos_rmdir30:
  299. jmp fdos_ED_ACCESS ; "access denied"
  300. fdos_rmdir40:
  301. mov ax,ED_DIR
  302. jmp fdos_error
  303. eject
  304. ; CHANGE DIRECTORY (CHDIR)
  305. ; +----+----+----+----+----+----+
  306. ; |    3B   |        name       |
  307. ; +----+----+----+----+----+----+
  308. ; entry:
  309. ; ------
  310. ; name: segmented address of ASCIIZ name
  311. ; exit:
  312. ; -----
  313. ; AX: 0000 or error code ( < 0)
  314. chdir_ED_PATH:
  315. jmp fdos_ED_PATH ; all logical errors give "no path"
  316. chdir_ED_DRIVE:
  317. mov ax,ED_DRIVE ; bad drive error message
  318. chdir_err:
  319. jmp fdos_error
  320. fdos_chdir:
  321. ;----------
  322. call redir_asciiz_offer
  323. call local_disk ; get MXdisk, switch stack
  324. fdos_move_chdir:
  325. ;---------------
  326. mov orig_drive,0FFFFh ; set drive to invalid
  327. les di,dword ptr fdos_pb+2 ; get string address
  328. call get_path_drive ; from asciiz or default
  329.  jc chdir_ED_DRIVE ;  continue if drive A: - Z:
  330. call islocal ; reject networked drives
  331.  jc chdir_ED_DRIVE ;  as bad drives
  332. call path_prep_cont ; continue if drive legal
  333.  jc chdir_err ; return error to application
  334. call chk_no_dev ; no devices allowed
  335. call chk_no_wild ; no wild cards allowed here
  336. cmp orig_drive,0FFFFh ; check if assign to specified drive
  337.  jne chdir10 ; skip drive specified
  338. mov ax,path_drive ; else same as path drive
  339. mov orig_drive,ax
  340. chdir10:
  341. if JOIN
  342. call offer_join ; are we opening a JOIN'd drive ?
  343.  jnc chdir30 ;  if so move to it and skip open_dir
  344. endif
  345. call chk_for_root ; check if we are in the root
  346.  je chdir30 ; if so, just skip the open_dir
  347. call finddfcbf ; try to locate directory entry
  348.  jz chdir_ED_PATH ; skip if no valid directory
  349. test DATTS[bx],DA_DIR ; check directory attribute
  350.  jz chdir_ED_PATH ; return if not a directory
  351. if PASSWORD
  352. call check_pwd_any ; check if PW prot'd & wrong PW
  353. endif
  354. call open_dir ; else open last directory
  355.  jc chdir_ED_PATH ; return an error if we can't
  356. chdir30:
  357. mov ax,orig_drive ; get logical drive
  358. call get_ldt ; ES:BX -> LDT_
  359.  jc chdir10 ; no LDT_, must be init time...
  360. mov si,es:LDT_FLAGS[bx] ; normally we inherit parents
  361. mov cx,es:LDT_ROOTLEN[bx] ; root block and drive
  362. mov dx,es:word ptr LDT_NAME[bx]
  363. mov bx,es:LDT_ROOT[bx]  ; if it's a "SUBST I: C:PATH" form
  364. cmp ax,path_drive ;  we pick up new root and drive
  365.  je chdir50 ;  like this
  366. mov ax,path_drive ; ASCII drive from path drive
  367. mov dx,'A'+256*':' ; make it into ASCII "C:"
  368. add dx,ax ; in case LDT does not exist
  369. call get_ldt ; get LDT_ in case it's subst'd
  370.  jc chdir40
  371. mov dx,es:word ptr LDT_NAME[bx]
  372. chdir40:
  373. mov bx,fdos_hds_blk ; root block from fdos_hds
  374. chdir50:
  375. mov di,offset pri_pathname ; build new LDT_ here
  376. or si,LFLG_PHYSICAL ; drive is always physical
  377. mov LDT_FLAGS[di],si
  378. mov LDT_ROOTLEN[di],cx ; inherit rootlen from parent
  379. mov LDT_ROOT[di],bx ; root as above
  380. mov ax,fdos_hds_blk ; current block from HDS
  381. mov LDT_BLK[di],ax
  382. mov al,fdos_hds_drv ; current drive we from HDS
  383. mov LDT_DRV[di],al
  384. mov ax,word ptr current_ddsc
  385. mov word ptr LDT_PDT[di],ax
  386. mov ax,word ptr current_ddsc+WORD
  387. mov word ptr LDT_PDT+WORD[di],ax
  388. push ss ! pop es ; now build ASCII path
  389. ; lea di,LDT_NAME[di] ; ES:DI -> name
  390. xchg ax,dx
  391. stosw ; plant 'A:'
  392. mov ax,''
  393. stosw ; make that 'A:',0
  394. dec di ; point at NUL
  395. mov fdos_hds_root,0 ; we want to go back to root
  396. mov fdos_pb+6,di ; rebuild into LDT_ at the address
  397. mov fdos_pb+8,es
  398. push ds ! pop es
  399. chdir60:
  400. call hdsblk ; get current block
  401. if JOIN
  402.  jnz chdir65 ; if not at root unparse
  403. call check_join ; check if drive is joined to another
  404.  jz chdir80 ; at root, unJOIN'd, so exit
  405. ; we are at the root of this drive
  406. xchg al,fdos_hds_drv ; update HDS drive so we can force
  407. push es ;  an exit next time round
  408. call get_ldt ; now copy the JOIN'd name
  409. push ds ! push es ! pop ds ! pop es
  410. lea si,LDT_NAME+3[bx] ; point to my JOIN data
  411. mov di,offset save_area
  412. call copy_asciiz
  413. push es ! pop ds
  414. pop es
  415. jmps chdir70 ; copy this into place
  416. chdir65:
  417. else
  418.  jz chdir80 ; if at root, we're done
  419. endif
  420. call parent2save_area ; parental name written in save_area
  421. chdir70:
  422. dec di ; DI -> '' at end
  423. mov al,'' ! stosb ; add a trailing backslash
  424. sub di,offset save_area+1
  425. mov dx,di ; DX = length of name
  426. push es ; insert name into user buffer
  427. les di,dword ptr fdos_pb+6
  428. mov al,0 ! scasb ; check if first directory
  429.  je chdir75 ; if not 1st in path
  430. inc dx ; we need space for ''
  431. chdir75:
  432. dec di ; adjust for scan
  433. call mkspace_parent ; move ES:DI up by DX bytes
  434. mov di,fdos_pb+6 ; ES:DI -> user buffer
  435. rep movsb ; copy directory into user buffer
  436. pop es ; ES = local segment again
  437. jmp chdir60 ; try again til root
  438. chdir80: ; arrive here when root reached
  439. mov ax,orig_drive ; get logical drive
  440. call get_ldt ; ES:BX -> LDT_
  441.  jc chdir85 ; no LDT_, what happended ?
  442. push ds
  443. mov di,bx ; ES:DI -> destination LDT_
  444. push ss ! pop ds
  445. mov si,offset pri_pathname ; DS:SI -> new LDT_ we just built
  446. mov cx,LDT_LEN
  447. rep movsb ; copy the new LDT_ into place
  448. pop ds
  449. cmp ax,path_drive ; if the drive's are same
  450.  je chdir85 ;  "CD" or "SUBST d:=d:path"
  451. or es:LDT_FLAGS[bx],LFLG_SUBST
  452. lea di,LDT_NAME[bx] ; ES:DI -> name
  453. xor ax,ax
  454. mov cx,LDT_FLAGS-LDT_NAME ; name can be this long
  455. repne scasb ; look for terminating NUL
  456. sub di,bx ; get # chars skipped
  457. dec di ; forget the NUL
  458. cmp di,3 ; root is special case again !
  459.  jbe chdir85
  460. mov es:LDT_ROOTLEN[bx],di ; set new root position
  461. chdir85:
  462. ret
  463. eject
  464. ; CREATE FILE (CREAT)
  465. ; +----+----+----+----+----+----+----+----+----+----+
  466. ; |    3C   |        name       |  mode   |  attrib |
  467. ; +----+----+----+----+----+----+----+----+----+----+
  468. ; entry:
  469. ; ------
  470. ; name: segmented address of ASCIIZ name
  471. ; mode: open mode for handle
  472. ;   attrib: attribute for file
  473. ; exit:
  474. ; -----
  475. ; AX: file handle or error code ( < 0)
  476. fdos_creat:
  477. ;----------
  478. call redir_asciiz_dev_offer ; offer it as a network device
  479. call asciiz_dev_offer ; offer it as a local device
  480. call redir_asciiz_file_offer ; offer it as a network file
  481. call local_disk ; get MXdisk, switch stack
  482. call mustbe_free_handle ; make sure we have spare handle
  483. call path_prep ; parse path, walk down the tree
  484. call check_device ; is it a device ?
  485.  jc creat_disk
  486. jmp open_dev ; open as a device handle
  487. creat_disk:
  488. call chk_no_dot_or_wild
  489. test byte ptr fdos_pb+8,DA_VOLUME
  490.  jz creat_nolbl ; skip if not volume label
  491. call mustbe_nolbl ; do we have an existing label ?
  492. jmps creat_new_file ; no, create one
  493. creat_nolbl:
  494. call finddfcbf ; find entry, ignore labels
  495.  jz creat_new_file ; skip if it doesn't exist yet
  496. call check_no_dir ; make sure not a directory
  497. call check_ro ; check if file is read/only
  498. call close_if_open ; make sure not open by any process
  499. if PASSWORD
  500. call check_pwd_d ; check if PW req'd & supplied
  501. endif
  502. mov bx,dirp
  503. mov ax,DBLOCK1[bx] ; release all blocks of the file
  504. call delfat ; so it is truncated to zero size
  505. call update_fat ; update file allocation table
  506. jmps creat2 ; reinitialize directory entry
  507. creat_new_file: ; create new file - shared by MKNEW
  508. call allocdir ; allocate a directory entry
  509. creat2:
  510. mov bx,dirp ; BX -> directory entry
  511. lea di,DNAME[bx] ; DI -> name offset in dir buffer
  512. mov si,offset info_fcb+1 ; SI -> name offset in FCB
  513. mov cx,11
  514. rep movsb ; copy name into directory
  515. mov ax,fdos_pb+8 ; get creation file attribute
  516. mov dx,fdos_pb+6 ; open in r/w, compatibilty mode
  517. test al,not (DA_RO+DA_SYSTEM+DA_HIDDEN+DA_ARCHIVE)
  518.  jz creat5 ; allow r/o, hidden, system, archive
  519. test al,DA_VOLUME ; failure as file, creating a label?
  520.  jz creat_access_err ;  no, then it's really a problem
  521. mov dl,DHM_RO+DHM_LOCAL ; open in compatibility mode
  522. creat5:
  523. or al,DA_ARCHIVE ; always create as new file
  524. stosb ; update directory attributes
  525. sub ax,ax ; zero out remainder of entry
  526. mov cx,32-12
  527. rep stosb ; zero remainder of entry
  528. push bx ; save dirp
  529. push dx ; save the open mode
  530. call stamp_dir_entry ; set time and date in FCB
  531. call update_dir ; update directory
  532. pop ax ; restore open mode
  533. pop bx ; restore dirp
  534. jmp creat_handle ; now allocate file handle
  535. creat_access_err:
  536. jmp fdos_ED_ACCESS ; return "access denied"
  537. eject
  538. ; OPEN FILE (OPEN)
  539. ; +----+----+----+----+----+----+----+----+----+----+
  540. ; |    3D   |        name       |  mode   |  attrib |
  541. ; +----+----+----+----+----+----+----+----+----+----+
  542. ; entry:
  543. ; ------
  544. ; name: segmented address of ASCIIZ name
  545. ;   mode:   open mode 
  546. ; attrib: file attrib for search (default = 16h)
  547. ; exit:
  548. ; -----
  549. ; AX: file handle or error code ( < 0)
  550. fdos_open:
  551. ;---------
  552. call redir_asciiz_dev_offer ; offer it as a network device
  553. call asciiz_dev_offer ; offer it as a local device
  554. call redir_asciiz_file_offer ; offer it as a network file
  555. call local_disk ; get MXdisk, switch stack
  556. call mustbe_free_handle ; make sure we have spare handle
  557. call path_prep ; parse the path, go to bottom level
  558. call check_device
  559.  jc open_disk
  560. jmp open_dev ; open as a device
  561. open_disk:
  562. call chk_no_wild ; we don't allow no wild cards here
  563. call finddfcbf ; search by name
  564.  jz open8 ; bail out if not found
  565. mov al,byte ptr fdos_pb+8 ; check requested attributes
  566. if PASSWORD
  567. cmp word ptr DPWD[bx],0
  568.  je open1
  569. or al,DA_HIDDEN
  570. open1:
  571. endif
  572. not al
  573. and al,DA_HIDDEN+DA_SYSTEM
  574. or al,DA_DIR+DA_VOLUME
  575. test DATTS[bx],al
  576.  jnz open9 ; error if attrib not as requested
  577. mov ax,fdos_pb+6 ; determine open mode
  578. if PASSWORD
  579. sub dx,dx ; assume no PW conflicts
  580. endif
  581. test al,DHM_RW+DHM_WO ; test if read/only access
  582.  jz open2
  583. if PASSWORD ; if write or r/w check writes
  584. or dx,PWM_W ;  check for write password
  585. endif
  586. ; mov bx,dirp ; get directory pointer
  587. test DATTS[bx],DA_RO ; read/only file?
  588.  jz open2 ;  no, skip FCB check
  589. test ax,DHM_FCB ; if FCB open of read-only file
  590.  jz open9 ; allow it, but adjust to read-only
  591. and al,not DHM_RWMSK ;  open mode and proceed
  592. open2:
  593. if PASSWORD
  594. test al,DHM_WO ; will we try to read?
  595.  jnz open3 ; skip if not open for reading
  596. or dx,PWM_R + PWM_E ; else check for read/exec password
  597. open3:
  598. push ax ; save the open mode
  599. xchg ax,dx ; AX = password modes to check for
  600. call check_pwd ; check for r/w passwords
  601. pop ax
  602. endif
  603. jmp open_handle ; now allocate file handle
  604. open8:
  605. jmp fdos_ED_FILE ; "file not found"
  606. open9:
  607. jmp fdos_ED_ACCESS ; return "access denied" error
  608. eject
  609. ; CLOSE FILE (CLOSE)
  610. ; +----+----+----+----+
  611. ; |    3E   |  handle |
  612. ; +----+----+----+----+
  613. ; entry:
  614. ; ------
  615. ; handle: open file handle to be closed
  616. ; exit:
  617. ; -----
  618. ; AX: 3Exx (where xx = # time it was open) or error code ( < 0)
  619. fdos_close:
  620. ;----------
  621. call vfy_dhndl_ptr ; check file handle #
  622. call redir_dhndl_offer
  623. call local_disk ; get MXdisk, switch stack
  624. call check_handle ; check if legal file handle
  625. mov ax,es:DHNDL_COUNT[bx] ; return # times file WAS open
  626. mov ah,3Eh ; AH = MS_X_CLOSE
  627.     mov fdos_ret,ax     ; return 3Exx if successful
  628.  jc close20 ; skip if character device close
  629. close_dhndl:
  630. call release_handle ; release file handle into pool
  631. callf ss:share_stub+S_CLOSE ; call the fdos stub routine
  632. dec es:DHNDL_COUNT[bx] ; one less XFN refers to this IFN
  633. test es:DHNDL_WATTR[bx],DHAT_REMOTE+DHAT_CLEAN
  634.  jnz close10 ; skip update if not dirty local file
  635. call select_handle ; select the disk
  636. call file_update ; update directory & FAT if written
  637. close10:
  638. ret
  639. close20: ; handle refers to character device
  640. jmp close_dev ; close the device handle
  641. eject
  642. ; READ FROM FILE (READ)
  643. ; +----+----+----+----+----+----+----+----+----+----+
  644. ; |    3F   |  handle |       buffer      |  count  |
  645. ; +----+----+----+----+----+----+----+----+----+----+
  646. ; entry:
  647. ; ------
  648. ; handle: open file handle
  649. ; buffer: buffer to read into
  650. ; count: max. number of bytes to read
  651. ; exit:
  652. ; -----
  653. ; AX: byte count or error code ( < 0)
  654. fdos_read:
  655. ;---------
  656. call vfy_dhndl_ptr ; check file handle #
  657. test es:DHNDL_MODE[bx],DHM_WO
  658.  jnz rw_ED_ACCESS ; fail if open write only
  659. call redir_dhndl_offer
  660. test es:DHNDL_WATTR[bx],DHAT_DEV
  661.  jnz fdos_read_dev ; skip if character device
  662. call local_disk ; get MXdisk, switch stack
  663. call verify_handle ; check if legal file handle
  664. mov cx,fdos_pb+8 ; get requested transfer length
  665. mov ax,es:DHNDL_POSLO[bx] ; If we get an error we want to have
  666. mov dx,es:DHNDL_POSHI[bx] ; xfer len adjusted for EOF (CopyIIpc)
  667. sub ax,es:DHNDL_SIZELO[bx] ; are we beyond EOF ?
  668. sbb dx,es:DHNDL_SIZEHI[bx]
  669. ;  jb read2 ; beyond EOF already, no action required
  670. ;  ja read2 ; more the 64K to go, no problems
  671.  jnz read2
  672. cmp ax,cx ; do we want more than there is?
  673.  jae read2 ; yes, shorten the fdos_pb count
  674. sub fdos_pb+8,ax ;  in case of a critical error
  675. read2:
  676. mov fdrwflg,1 ; we're reading
  677. les di,dword ptr fdos_pb+4 ; get disk transfer address
  678. call fdosrw ; read from file
  679. xor ax,ax ; return OK
  680. xchg ax,fdos_ret ; get returned byte count
  681. mov fdos_pb+8,ax ; return in requested count
  682. ret
  683. fdos_read_dev:
  684. jmp read_dev ; read from character device
  685. rw_ED_ACCESS:
  686. mov bx,ED_ACCESS ; return access denied
  687. ret
  688. eject
  689. ; WRITE TO FILE (WRITE)
  690. ; +----+----+----+----+----+----+----+----+----+----+
  691. ; |    40   |  handle |       buffer      |  count  |
  692. ; +----+----+----+----+----+----+----+----+----+----+
  693. ; entry:
  694. ; ------
  695. ; handle: open file handle
  696. ; buffer: buffer to be wriiten
  697. ; count: max. number of bytes to write
  698. ; exit:
  699. ; -----
  700. ; AX: byte count or error code ( < 0)
  701. fdos_write:
  702. ;----------
  703. call vfy_dhndl_ptr ; check file handle #
  704. test es:DHNDL_MODE[bx],DHM_WO+DHM_RW
  705.  jz rw_ED_ACCESS ; fail if not open in r/w or w mode?
  706. call redir_dhndl_offer
  707. test es:DHNDL_WATTR[bx],DHAT_DEV
  708.  jnz fdos_write_dev ; skip if not character device
  709. call local_disk ; get MXdisk, switch stack
  710. call verify_handle ; check if legal file handle
  711. mov fdrwflg,0 ; we're writing
  712. les di,dword ptr fdos_pb+4 ; get disk transfer address
  713. mov cx,fdos_pb+8 ; get requested transfer length
  714. call fdosrw ; write to file file
  715. xor ax,ax ; return OK
  716. xchg ax,fdos_ret ; get returned byte count
  717. mov fdos_pb+8,ax ; return in requested count
  718. ret
  719. fdos_write_dev:
  720. jmp write_dev ; write to character device
  721. eject
  722. ; DELETE FILE (UNLINK)
  723. ; +----+----+----+----+----+----+----+----+----+----+
  724. ; |    41   |        name       |  *****  |  attrib |
  725. ; +----+----+----+----+----+----+----+----+----+----+
  726. ; entry:
  727. ; ------
  728. ; name: segmented address of ASCIIZ name
  729. ; attrib: delete mask (FCB only..)
  730. ; exit:
  731. ; -----
  732. ; AX: 0000 or error code ( < 0)
  733. fdos_unlink:
  734. ;-----------
  735. call redir_asciiz_offer
  736. call local_disk ; get MXdisk, switch stack
  737. call path_prep ; parse the path, go to bottom level
  738. call chk_no_dev ; can't be a device
  739. ; look to see is the call is a remote
  740. cmp ss:remote_call,0 ;  a 21/5D00 one or a local FCB one
  741.  jz unlink1 ; neither, no wild cards allowed
  742.  jns unlink2 ; if it's an FCB call we need to check
  743. test fdos_pb+8,DA_VOLUME ;  for deleting a VOLUME label
  744.  jz unlink2
  745. call find_labelf ; lets find the volume label
  746.  jz unlink4 ;  reporting error if we don't match
  747. jmp kill_entry ; found it - delete it
  748. unlink4:
  749. jmp fdos_ED_FILE ; return "file not found"
  750. unlink1:
  751. call chk_no_wild ; make sure not a wild card
  752. unlink2:
  753. call setenddir ; search from the start
  754. ; We now skip any labels/dirs, returning ED_FILE if no other matches
  755. unlink3:
  756. call finddfcb ; try to locate directory entry
  757.  jz unlink4 ;  returning an error on failure
  758. test DATTS[bx],DA_DIR+DA_VOLUME
  759.  jnz unlink3 ; make sure it isn't a label/directory
  760. unlink5:
  761. ; we have a match, so return ED_ACCESS if we can't find a file we can delete
  762. call unlink_attribs ; AL = attribs we can't delete
  763.  jz unlink7 ; yes, go for it
  764. call finddfcb ; look for another entry
  765.  jnz unlink5 ;  try this one instead
  766. jmp fdos_ED_ACCESS ; "access denied" if nothing deleted
  767. ;  since we found at least 1 file
  768. ; we will delete at least one file, so now we succeed
  769. unlink6:
  770. call unlink_attribs ; AL = attribs we can't delete
  771.  jnz unlink8 ; yes, go for it
  772. unlink7:
  773. call close_if_same_psp ; make sure not open by any process
  774. if PASSWORD
  775. call check_pwd_d ; check for password
  776. endif
  777. call kill_file ; delete file
  778. unlink8:
  779. call finddfcb ; look for another entry
  780.  jnz unlink6 ;  try and delete it if we find one
  781. jmp update_dir_fat ; write out dirty directories/FAT
  782. unlink_attribs:
  783. ; On Entry:
  784. ; BX -> directory entry
  785. ; On Exit:
  786. ; AL = attribute mask which prevents deletion
  787. ; ZF = 1 if delete OK, ZF = 0 if file should be skipped
  788. ;
  789. mov al,byte ptr fdos_pb+8 ; check attributes
  790. if PASSWORD
  791. cmp word ptr DPWD[bx],0
  792.  je unlink_attribs10
  793. or al,DA_HIDDEN
  794. unlink_attribs10:
  795. endif
  796. not al
  797. and al,DA_HIDDEN+DA_SYSTEM+DA_RO
  798.     or  al,DA_DIR+DA_VOLUME 
  799. test DATTS[bx],al ; should we delete this entry ?
  800. ret
  801. eject
  802. ; GET/SET FILE POSITION (LSEEK)
  803. ; +----+----+----+----+----+----+----+----+----+----+
  804. ; |    42   |  handle |       offset      !  method |
  805. ; +----+----+----+----+----+----+----+----+----+----+
  806. ; entry:
  807. ; ------
  808. ; handle: open file handle
  809. ; offset: long integer offset
  810. ; method: 0 = begin, 1 = current, 2 = end of file
  811. ; exit:
  812. ; -----
  813. ; AX: 0000 or error code ( < 0)
  814. ; offset: new offset
  815. fdos_lseek:
  816. ;----------
  817. call vfy_dhndl_ptr ; check file handle #
  818. call redir_dhndl_offer
  819. test es:DHNDL_ATTR[bx],DHAT_DEV
  820.  jnz lseek_dev ; skip if character device
  821. call local_disk ; get MXdisk, switch stack
  822. call check_handle ; check if legal file handle
  823. mov ax,fdos_pb+4 ; get 32-bit file offset
  824. mov dx,fdos_pb+6 ; into AX,DX
  825. mov cx,fdos_pb+8 ; get seek mode
  826.  jcxz lseek4 ; seek from beginning
  827. dec cx
  828.  jz lseek2 ; seek from current position
  829. dec cx
  830.  jz lseek3 ; seek from end
  831. mov ax,ED_DATA ; else invalid seek mode
  832. jmp fdos_error ; return error code
  833. lseek1:
  834. ret ; return error code
  835. lseek2: ; seek mode 1: relative to position
  836. add ax,es:DHNDL_POSLO[bx]
  837. adc dx,es:DHNDL_POSHI[bx]
  838. jmps lseek4 ; update new position
  839. lseek3: ; seek mode 2: relative to end
  840. add ax,es:DHNDL_SIZELO[bx]
  841. adc dx,es:DHNDL_SIZEHI[bx] ; add file size + offset
  842. lseek4: ; seek mode 0: set absolute position
  843. mov es:DHNDL_POSLO[bx],ax
  844. mov es:DHNDL_POSHI[bx],dx
  845. mov fdos_pb+4,ax ; set return values
  846. mov fdos_pb+6,dx
  847. ret
  848. lseek_dev: ; jump here if character device
  849. mov si,2[bp] ; SI -> parameter block
  850. xor bx,bx
  851. mov 4[si],bx ; always return result of 0000h
  852. mov 6[si],bx
  853. ret
  854. eject
  855. ; GET/SET FILE ATTRIBUTES (CHMOD)
  856. ; +----+----+----+----+----+----+----+----+----+----+
  857. ; |    43   |        name       |   flag  | attrib  |
  858. ; +----+----+----+----+----+----+----+----+----+----+
  859. ; |        size       |
  860. ; +----+----+----+----+
  861. ; entry:
  862. ; ------
  863. ; name: pointer to ASCIIZ file name
  864. ; flag: 00 = get attrib/size
  865. ; 01 = set attrib
  866. ; attrib: file attribute if flag=1
  867. ;
  868. ; exit:
  869. ; -----
  870. ; AX: 0000 or error code ( < 0)
  871. ; attrib: file attribute if flag=0
  872. ; size: file size if flag=0
  873. ;
  874. if PASSWORD
  875. ; entry:
  876. ; ------
  877. ; name: pointer to ASCIIZ file name
  878. ; flag: 02 = get password mode
  879. ; 03 = set pw mode/password
  880. ; 04 = get encrypted password
  881. ; 05 = set encrypted password
  882. ; attrib: password mode if flag = 3,5
  883. ; dma: ascii     password if flag = 3
  884. ; encrypted password if flag = 5
  885. ;
  886. ; exit:
  887. ; -----
  888. ; AX: 0000 or error code ( < 0)
  889. ; attrib: file's attribute if flag = 0
  890. ; password mode if flag = 2
  891. ; encrypted password if flag = 4
  892. endif
  893. if UNDELETE
  894. ; entry:
  895. ; ------
  896. ; name: pointer to ASCIIZ file name
  897. ; flag: 80 = undelete file
  898. ; 81 = purge file
  899. ; dma: result of sucessful search
  900. ;
  901. ; exit:
  902. ; -----
  903. ; AX: 0000 or error code ( < 0)
  904. ;
  905. endif
  906. fdos_chmod:
  907. ;----------
  908. if UNDELETE
  909. mov si,2[bp] ; SI -> parameter block
  910. mov al,6[si] ; AX = flag
  911. sub al,80h ; is it undelete or purge
  912.  jb fdos_chmod_path ; if so set
  913. cmp al,1
  914.  ja fdos_chmod_path
  915. call local_disk ; get MXdisk, switch stack
  916. call select_from_DTA ; prepare for the search
  917. mov chdblk,0 ; don't assume sequential access
  918. dec dcnt ; retract so we find the same entry
  919. call find_pending_delete ; did we find it ?
  920.  jz chmod_notfound ; No, then skip
  921. call hdsblk ; AX = directory root cluster
  922. xchg ax,dx ; DX = dir cluster
  923. mov cx,dcnt ; CX = directory index for entry
  924. mov ax,fdos_pb+6 ; get operation type
  925. mov ah,DELW_UNDEL ; assume we are about to undelete
  926. cmp al,80h ; is it undelete ?
  927.  je fdos_undelete_purge
  928. mov ah,DELW_PURGE ; no, it must be purge entry
  929. fdos_undelete_purge:
  930. mov al,physical_drv ; give delwatch a chance to do it
  931. callf ss:fdos_stub
  932.  jc fdos_ED_FUNCTION ; return error if DELWATCH not there
  933. mov fdos_ret,ax ;  else return result
  934. ret
  935. fdos_chmod_path:
  936. endif
  937. call redir_asciiz_offer
  938. call local_disk ; get MXdisk, switch stack
  939. call path_prep ; parse the path, go to bottom level
  940. call chk_no_wild ; can't have wildcards
  941. call finddfcbf ; find first matching FCB
  942.  jnz chmod10 ; if we can't find a file/dir
  943. call chk_for_root ;  check if we are in the root
  944.  jnz chmod_notfound ; if so return directory attribute
  945. mov cx,fdos_pb+6 ;  but only for get attributes
  946.  jcxz chmod_root ;  other fall through to not found
  947. chmod_notfound:
  948. jmp fdos_ED_FILE
  949. chmod_root:
  950. mov fdos_pb+8,DA_DIR ; return directory attribute
  951. ret
  952. fdos_ED_FUNCTION:
  953. mov ax,ED_FUNCTION ; invalid subfunction
  954. jmp fdos_error
  955. chmod10:
  956. mov bx,dirp ; BX -> matching directory entry
  957. mov ax,DSIZE[bx]
  958. mov fdos_pb+10,ax
  959. mov ax,DSIZE+WORD[bx]
  960. mov fdos_pb+12,ax
  961. xor ax,ax
  962. mov al,DATTS[bx] ; get directory attributes
  963. mov cx,fdos_pb+6 ; get function #
  964.  jcxz chmod30 ; always allow get attribs
  965. if PASSWORD
  966. cmp cl,5 ; validate sub-function number
  967.  ja chmod15
  968. mov ax,DPWM[bx] ; assume return password mode
  969. and ax,PWM_ANY ; isolate password mode bits
  970. cmp cl,2 ; is it get mode ?
  971.  je chmod30 ; yes, just return it
  972. push ax
  973. push cx
  974. call check_pwd_any ; check the password
  975. pop cx
  976. pop ax
  977. mov dx,fdos_pb+8 ; DX = new attributes
  978. cmp cl,2 ; is it get mode ?
  979.  ja chmod20 ; how about other password functions?
  980. else
  981. cmp cl,1 ; validate sub-function number
  982.  ja chmod15
  983. mov dx,fdos_pb+8 ; DX = new attributes
  984. endif
  985. ; Set new file attrib
  986. ; BX = DIRP
  987. ; DX = attrib
  988. ;
  989. test dl,DA_DIR ; directory bit not allowed
  990.  jnz chmod12
  991. xor dl,DATTS[bx] ; check which bits are changed
  992. and dl,not DA_DIR ; don't check or flip directory bit
  993. test dl,DA_FIXED ; trying to change the unchangeable?
  994.  jz chmod13
  995. chmod12:
  996. jmp fdos_ED_ACCESS ; return "access denied"
  997. chmod13:
  998. xor DATTS[bx],dl ; set new attributes
  999. if PASSWORD
  1000. jmps chmod90
  1001. else
  1002. jmp update_dir ; update directory
  1003. endif
  1004. chmod15:
  1005. mov ah,PASSWD_CHMOD ; call out to SECURITY TSR
  1006. callf ss:fdos_stub
  1007.  jc fdos_ED_FUNCTION
  1008. jmps chmod90
  1009. if PASSWORD
  1010. chmod20:
  1011. ; Password support for functions 3-5
  1012. ; BX = DIRP
  1013. ; CX = flag
  1014. ; DX = attrib
  1015. ;
  1016. push bx
  1017. push cx
  1018. push dx
  1019. mov di,S_DENY_IF_OPEN ; check if file already open
  1020. call check_with_share ; and stop if it is
  1021. pop dx
  1022. pop cx
  1023. pop bx
  1024. mov ax,DPWD[bx] ; assume get encrypted password
  1025. cmp cl,4 ;  was it ?
  1026.  jne chmod50
  1027. endif ; yes, return encrypted password
  1028. chmod30:
  1029. mov fdos_pb+8,ax
  1030. ret
  1031. if PASSWORD
  1032. ; Password support for functions 3/5
  1033. ; BX = DIRP
  1034. ; CX = flag
  1035. ; DX = attrib
  1036. chmod50: ; set password/password mode
  1037. test dh,80h ; assign new password?
  1038.  jz chmod70 ; skip if mode change only
  1039. mov di,offset save_area ; ES:DI -> local structure
  1040. push ds
  1041. call lds_si_dmaptr ; DS:SI -> users DMA address
  1042. lodsw ; AX = possible encrypted password
  1043. cmp cl,5 ; was it set encrypted password ?
  1044.  je chmod60
  1045. dec si ; no, the DMA buffer contains
  1046. dec si ;  an 8 character password so we
  1047. call hash_pwd ;  compute password hash code
  1048. chmod60:
  1049. pop ds
  1050. or DATTS[bx],DA_HIDDEN ; file will be hidden
  1051. mov DPWD[bx],ax ; set new file password
  1052. test ax,ax ; null password?
  1053.  jnz chmod70
  1054. xor dx,dx ; can't be protected....
  1055. chmod70:
  1056. mov ax,not PWM_ANY ; clear existing file
  1057. and DPWM[bx],ax ;  password mode bits
  1058. not ax ; isolate password mode bits
  1059. and dx,ax ;  in new password mode
  1060.  jz chmod80 ; if no protection, leave them off
  1061. test DATTS[bx],DA_DIR ; directories protected in all modes
  1062.  jz chmod80 ; skip if not a directory
  1063. xchg ax,dx ; force all modes on
  1064. chmod80:
  1065. or DPWM[bx],dx ; set password mode bits
  1066. test dx,dx ; test if protection enabled
  1067.  jnz chmod90 ; skip if any protection still active
  1068. mov DPWD[bx],dx ; remove the password and hidden bit
  1069. and DATTS[bx],not DA_HIDDEN ;  as file is no longer protected
  1070. endif
  1071. chmod90:
  1072. jmp update_dir ; now update the directory
  1073. eject
  1074. ; DUPLICATE FILE HANDLE (DUP)
  1075. ; +----+----+----+----+----+----+
  1076. ; |    45   |  handle |  newhnd |
  1077. ; +----+----+----+----+----+----+
  1078. ; entry:
  1079. ; ------
  1080. ; handle: open file handle
  1081. ; exit:
  1082. ; -----
  1083. ; newhnd: new file handle
  1084. ; AX: duplicate file handle or error code ( < 0)
  1085. fdos_dup:
  1086. ;--------
  1087. call find_xfn ; find new external file #
  1088. mov si,2[bp] ; SI -> parameter block
  1089. mov ds:4[si],di ; save new handle #
  1090.  jnc fdos_fdup ; share the code with DUP2
  1091. mov bx,ED_HANDLE ; can't find a handle
  1092. ret
  1093. eject
  1094. ; FORCE DUPLICATE FILE HANDLE (DUP2)
  1095. ; +----+----+----+----+----+----+
  1096. ; |    46   |  handle |  newhnd |
  1097. ; +----+----+----+----+----+----+
  1098. ; entry:
  1099. ; ------
  1100. ; handle: open file handle
  1101. ; newhnd: new file handle
  1102. ; exit:
  1103. ; -----
  1104. ; AX: duplicate file handle or error code ( < 0)
  1105. fdos_fdup:
  1106. ;---------
  1107. call vfy_dhndl_ptr ; check file handle #
  1108. call local_disk ; get critical section locks
  1109. call get_xftptr ; ES:DI -> XFN table
  1110.  jc dup_err ; we need one..
  1111. mov bx,fdos_pb+4 ; get user file number (0-19)
  1112. cmp bx,cx ; is it sensible ?
  1113.  jae dup_err
  1114. cmp es:byte ptr [di+bx],0FFh
  1115.  jne dup_err ; handle should be closed by PCMODE..
  1116. call check_handle ; check if legal file handle
  1117. inc es:DHNDL_COUNT[bx] ; another user
  1118. call dup_dev ; inform device driver it's happened
  1119. call get_xftptr ; ES:DI -> XFT's
  1120. mov bx,fdos_pb+2 ; get XFN to dup from
  1121. mov al,es:[di+bx] ; get it's IFN
  1122. mov bx,fdos_pb+4 ; BX = XFN to dup to
  1123. mov es:[di+bx],al ; it gets same IFN
  1124. mov fdos_ret,bx ; return XFN to caller
  1125. ret
  1126. dup_err: ; complain someone stole my handle
  1127. jmp fdos_ED_H_MATCH
  1128. eject
  1129. ; GET CURRENT DIRECTORY
  1130. ;
  1131. ; +----+----+----+----+----+----+----+----+
  1132. ; |    47   |   drive |        path       |
  1133. ; +----+----+----+----+----+----+----+----+
  1134. ; entry:
  1135. ; ------
  1136. ; drive: drive to get path for
  1137. ; path: address of 64 byte path buffer to be
  1138. ; filled in with current path
  1139. ; exit:
  1140. ; -----
  1141. ; BX: 0100 or error code
  1142. fdos_curdir:
  1143. ;-----------
  1144. call local_disk ; it's a disk function
  1145. call get_pb2_drive ; get specified drive in AL
  1146. call get_ldt ; ES:BX -> LDT_ for drive
  1147.  jc fdos_curdir30
  1148. mov dx,es:LDT_FLAGS[bx]
  1149. test dx,LFLG_NETWRKD
  1150.  jnz fdos_curdir10
  1151. test dx,LFLG_PHYSICAL
  1152.  jz fdos_curdir30
  1153. call select_unique ; select the drive for media changes
  1154. les bx,ss:current_ldt ; ES:BX -> LDT_ for this drive
  1155. cmp es:LDT_BLK[bx],0FFFFh ; is LDT valid
  1156.  jne fdos_curdir10
  1157. call rebuild_ldt_curdir ; no, better rebuild it
  1158. fdos_curdir10:
  1159. push ds
  1160. push es ! push bx ; save LDT
  1161. les di,dword ptr fdos_pb+4 ; ES:DI -> destination buffer
  1162. pop si ! pop ds ; DS:SI -> LDT
  1163. add si,ds:LDT_ROOTLEN[si] ; skip the '\serverdir'
  1164. lodsb ; eat the slash
  1165. call check_slash ; if it is one..
  1166.  je fdos_curdir20
  1167. dec si ; I didn't mean it!
  1168. fdos_curdir20:
  1169. call copy_asciiz ; copy the string
  1170. pop ds
  1171. mov fdos_ret,100h ; return 100h for success
  1172.     ret      
  1173. fdos_curdir30:
  1174. jmp fdos_ED_DRIVE ; naughty - it's a bad drive
  1175. eject
  1176. ; GET DISK PARAMETER BLOCK
  1177. ; +----+----+----+----+----+----+----+----+----+----+
  1178. ; |    48   |  drive  |        dpb        | adjust  |
  1179. ; +----+----+----+----+----+----+----+----+----+----+
  1180. ; entry:
  1181. ; ------
  1182. ; drive: drive to get information about
  1183. ; (top bit of word set if free space not required)
  1184. ; exit:
  1185. ; -----
  1186. ; AX: 0000 or error code ( < 0)
  1187. ; dpb: address of DOS DPB (offset/segment)
  1188. ; adjust: delwatch adjustment of free space
  1189. fdos_getdpb:
  1190. ;-----------
  1191. call redir_drv_offer
  1192. call local_disk ; get MXdisk, switch stack
  1193. call get_pb2_drive ; get drive from parameter block
  1194. call logical2physical ; AX = physical drive
  1195. call select_physical_drv
  1196. test fdos_pb+2,8000h ; free space required ?
  1197.  jnz fdos_getdpb10
  1198. call update_ddsc_free ; then make sure it is up to date
  1199. if DELWATCH
  1200. xor cx,cx ; assume no adjustment
  1201. mov ah,DELW_SPACE
  1202. mov al,physical_drv ; now we call DELWATCH to
  1203. callf fdos_stub ;  add pending deletes
  1204. mov fdos_pb+8,cx ; return free space adjust value
  1205. endif
  1206. fdos_getdpb10:
  1207. les ax,ss:current_ddsc
  1208. mov fdos_pb+4,ax
  1209. mov fdos_pb+6,es
  1210. ret
  1211. eject
  1212. ; FLUSH BUFFERS
  1213. ; +----+----+
  1214. ; |    49   |
  1215. ; +----+----+
  1216. ; entry:
  1217. ; ------
  1218. ; none
  1219. ; exit:
  1220. ; -----
  1221. ; none
  1222. fdos_flush:
  1223. ;----------
  1224. call local_disk ; be alone...
  1225. fdos_flush_local:
  1226. ; Entry point for people who already have the MX disk
  1227. xor dx,dx ; starting with drive A
  1228. fdos_flush10:
  1229. push dx
  1230. call mark_ldt_unsure ; ask for LDT's to be relogged
  1231. xchg ax,dx ; AL = drive to check
  1232. mov ah,BF_DIRTY
  1233. call buffers_check ; any buffers on this drive?
  1234.  jz fdos_flush20 ; skip flush if none
  1235. call select_physical_drv ; select drive in AL
  1236. call update_fat ; flush all FAT buffers
  1237. ; call update_dir ; dir always up to date
  1238. call update_dat ; flush all data buffers
  1239. fdos_flush20:
  1240. pop dx
  1241. xchg adrive,dl
  1242. call discard_all ; discard all buffers
  1243. xchg adrive,dl
  1244. inc dx ; onto next drive
  1245. cmp dl,phys_drv
  1246.  jb fdos_flush10
  1247. mov al,0FFh ; AL = all drives
  1248. jmp hshdscrd ; forget about our hashing
  1249. ; ret
  1250. eject
  1251. ; SELECT DRIVE
  1252. ; +----+----+----+----+
  1253. ; |    4A   |  drive  |
  1254. ; +----+----+----+----+
  1255. ; entry:
  1256. ; ------
  1257. ; drive: drive (zero based) to select as default drive
  1258. ; exit:
  1259. ; -----
  1260. ; current_dsk: drive (if legal)
  1261. fdos_select:
  1262. ;-----------
  1263. call local_disk ; cheap way to get MX
  1264. mov ax,fdos_pb+WORD ; AL = drive
  1265. call get_ldt ; ES:BX -> LDT for drive A
  1266. mov dx,ax ; DL = logical drive
  1267.  jc fdos_select10 ; no LDT, treat as physical=logical
  1268. mov ax,es:LDT_FLAGS[bx] ; get the LDT_FLAGS
  1269. test ax,LFLG_NETWRKD ; NETWORK drives are OK, but we must
  1270.  jnz fdos_select20 ;  skip physical selection bit
  1271. test ax,LFLG_PHYSICAL
  1272.  jz fdos_select30 ;  skip physical selection bit
  1273. if JOIN
  1274. test ax,LFLG_JOINED ; JOINed drives are bad news
  1275.  jnz fdos_select30 ;  so don't select one
  1276. endif
  1277. mov al,es:LDT_NAME[bx] ; get ASCII drive letter
  1278. call toupper ; it was ascii
  1279. sub al,'A' ;  make it zero based
  1280. fdos_select10:
  1281. call get_ddsc ; ES:BX -> DDSC_ for drive
  1282.  jc fdos_select30 ;  no, don't select
  1283. fdos_select20:
  1284. mov ss:current_dsk,dl ; new logical disk selected
  1285. fdos_select30:
  1286. ret
  1287. eject
  1288. ; EXECUTE CHILD (EXEC)
  1289. ; +----+----+----+----+
  1290. ; |    4B   |  pspseg |
  1291. ; +----+----+----+----+
  1292. ; entry:
  1293. ; ------
  1294. ; pspseg: segment of child PSP
  1295. ; exit:
  1296. ; -----
  1297. ; AX: 0000h
  1298. fdos_exec:
  1299. ;---------
  1300. call local_disk ; get MXdisk, switch stack
  1301. mov cx,fdos_pb+2
  1302.  jcxz exec30 ; no duplicate handles if no new PSP
  1303. mov di,offset PSP_XFT
  1304. mov es,cx ; get child PSP
  1305. mov cx,XFNMAX ; get # of handles in child PSP
  1306. mov PSP_XFNMAX,cx
  1307. mov PSP_XFTOFF,di
  1308. mov PSP_XFTSEG,es
  1309. mov al,0FFh ; assume all handles closed
  1310. rep stosb
  1311. xor si,si ; start with XFN 0
  1312. exec10:
  1313. call get_xftptr ; ES:DI -> XFN table
  1314.  jc exec30 ; stop if none
  1315. add di,si
  1316. mov al,es:[di] ; get IFN of old handle
  1317. call ifn2dhndl ; ES:BX -> DHNDL_
  1318.  jc exec20
  1319. mov cx,es:DHNDL_COUNT[bx] ; skip files that aren't open
  1320.  jcxz exec20
  1321. test es:byte ptr DHNDL_WATTR+1[bx],DHAT_LOCAL/100h
  1322.  jnz exec20 ; don't inherit private files
  1323. test es:byte ptr DHNDL_MODE+1[bx],DHM_FCB/100h
  1324.  jnz exec20 ; don't inherit FCB's
  1325. inc cx
  1326. mov es:DHNDL_COUNT[bx],cx ; increment in-use count
  1327. push ax
  1328. call dup_dev ; inform device driver it's happened
  1329. pop ax
  1330. mov es,fdos_pb+2 ; get child PSP
  1331. mov es:PSP_XFT[si],al ; inherit this IFN
  1332. exec20:
  1333. inc si ; next file handle
  1334. cmp si,XFNMAX
  1335.  jb exec10 ; inherit all file handles
  1336. exec30:
  1337. ret
  1338. eject
  1339. ; FIND FIRST FILE
  1340. ; +----+----+----+----+----+----+----+----+----+----+
  1341. ; |    4E   |        name       |  *****  |  attrib |
  1342. ; +----+----+----+----+----+----+----+----+----+----+
  1343. ; entry:
  1344. ; ------
  1345. ; name: pointer to ASCIIZ file name
  1346. ; attrib: attribute to be used in search
  1347. ; nb. API addition - attrib bit 7 set returns starting cluster
  1348. ;
  1349. ; exit:
  1350. ; -----
  1351. ; AX: 0000 or error code ( < 0)
  1352. ; Note: This call returns matching files in
  1353. ; the current DMA address and also saves
  1354. ; the BDOS state in the there.
  1355. ;
  1356. fdos_first:
  1357. ;----------
  1358. call redir_asciiz_dev_offer ; offer it as a network device
  1359. call asciiz_dev_offer ; offer it as a local device
  1360. call redir_asciiz_file_offer ; offer it as a network file
  1361. call local_disk ; get MXdisk, switch stack
  1362. call path_prep ; parse path, walk down the tree
  1363. call check_device ; if it a device
  1364.  jnc fdos_first10
  1365. mov ax,fdos_pb+8 ; get search attribute
  1366. mov attributes,al ; set for attribute match
  1367. mov dcnt,0FFFFh ; search from beginning
  1368. jmps search_next ; find next matching file
  1369. fdos_first10:
  1370. jmp first_dev ; return device name
  1371. next_deverr: ; NEXT after FIRST on device:
  1372. mov bx,ED_FILE ; "no more files"
  1373. ret
  1374. eject
  1375. ; FIND NEXT FILE
  1376. ; +----+----+
  1377. ; |    4F   |
  1378. ; +----+----+
  1379. ; entry:
  1380. ; ------
  1381. ;
  1382. ; exit:
  1383. ; -----
  1384. ; AX: 0000 or error code ( < 0)
  1385. ; Note: This call returns matching files in
  1386. ; the current DMA address and also saves
  1387. ; the BDOS state in the there.
  1388. ;
  1389. fdos_next:
  1390. ;---------
  1391. push ds
  1392. call lds_si_dmaptr ; DS:SI -> users DMA address
  1393. lodsw
  1394. xchg ax,dx ; DH = local drive
  1395. pop ds
  1396. cmp dh,0FFh ; check if FIRST was character device
  1397.  je next_deverr ; "no more files" if device
  1398. call redir_snext_offer
  1399. call local_disk ; get MXdisk, switch stack
  1400. call select_from_DTA ; prepare for the search
  1401. ; jmp search_next ; now go and look for next file
  1402. search_next:
  1403. ;-----------
  1404. mov chdblk,0 ; don't assume sequential access
  1405. mov al,attributes ; are we looking for a VOL label?
  1406. test al,DA_DIR+DA_SYSTEM+DA_HIDDEN
  1407.  jnz search_n10 ; these bits take precedence
  1408. test al,DA_VOLUME ; searching for label?
  1409.  jz search_n10 ; search for directory label only
  1410. if UNDELETE
  1411. cmp al,DA_DELWATCH+DA_VOLUME
  1412.  jne search_vol ; searching for pending delete entries?
  1413. call find_pending_delete ; did we find it ?
  1414.  jz search_next_err ; No, then skip
  1415. jmps search_n30 ; save search state for user
  1416. search_vol:
  1417. endif
  1418. call find_label ; did we find it ?
  1419.  jnz search_n30 ; save search state for user
  1420. search_next_err:
  1421. jmp fdos_ED_ROOM ; else end of directory
  1422. search_n10:
  1423. call finddfcb ; find next matching entry
  1424.  jz search_next_err ; if not found
  1425. mov al,attributes ; get attributes that we support
  1426. if PASSWORD
  1427. cmp word ptr DPWD[bx],0 ; does it have a password?
  1428.  jz search_n20 ; skip if not
  1429. or al,DA_HIDDEN ; else include hidden files
  1430. search_n20:
  1431. endif
  1432. not al ; attributes we don't support
  1433. and al,DA_DIR+DA_HIDDEN+DA_SYSTEM+DA_VOLUME
  1434. test DATTS[bx],al ; any attributes we don't support
  1435.  jnz search_n10 ; then don't count this one
  1436. search_n30:
  1437. push ss ! pop es
  1438. mov di,offset srch_buf ; ES:DI -> DMA search address
  1439. push di ; save for later
  1440. if JOIN
  1441. mov al,fdos_hds_drv ; save the PHYSICAL drive
  1442. else
  1443. mov al,byte ptr path_drive ; save the specified drive
  1444. endif
  1445. inc al
  1446. stosb
  1447. mov dx,di ; remember start of name field
  1448. mov si,offset info_fcb+1 ; point at search FCB
  1449. mov cx,11
  1450. rep movsb ; save name for search
  1451. mov al,attributes ; get search attribute
  1452. stosb
  1453. mov ax,dcnt
  1454. stosw ; save directory count
  1455. mov ax,fdos_hds_blk ; get the directory block
  1456. stosw ; save the current block
  1457. add di,4 ; skip 4 reserved bytes
  1458. mov si,dirp ; point to directory name
  1459. test attributes,DA_CLUSTER ; is the caller requesting
  1460.  jz search_n35 ; the starting cluster ?
  1461. mov ax,DBLOCK1[si] ; pick it up from dir entry
  1462. dec di ;  and return at offset 13h
  1463. dec di ;  in DTA (WARNING - Lantastic
  1464. stosw ; server uses these bytes too..)
  1465. search_n35:
  1466.     mov cx,32/WORD 
  1467. rep movsw ;  location (also used by FCB search)
  1468. pop si ; SI = offset srch_buf
  1469. call les_di_dmaptr ; ES:DI -> DMA address
  1470. push ss ! pop ds ; DS:SI -> srch_buf
  1471. mov cx,21
  1472. rep movsb ; copy from buffer to user DMA
  1473. mov bx,dirp ; BX -> matching entry
  1474. mov al,DATTS[bx]
  1475. stosb ; return directory attribute
  1476. lea si,DTIME[bx]
  1477. movsw ! movsw ; return time, date
  1478. inc si
  1479. inc si ; skip starting cluster
  1480. movsw ! movsw ; return file size
  1481. jmp unparse ; return file name
  1482. eject
  1483. ; COMMIT FILE (COMMIT)
  1484. ; +----+----+----+----+
  1485. ; |    50   |  handle |
  1486. ; +----+----+----+----+
  1487. ; entry:
  1488. ; ------
  1489. ; handle: open file handle to be flushed
  1490. ; exit:
  1491. ; -----
  1492. ; AX: 0000 or error code ( < 0)
  1493. file_updt20: ; NO-OP for clean files
  1494. commit_dev: ; NO-OP on character devices
  1495. ret
  1496. fdos_commit:
  1497. ;-----------
  1498. call vfy_dhndl_ptr ; check file handle
  1499. call redir_dhndl_offer
  1500. call local_disk ; get MXdisk, switch stack
  1501. call verify_handle ; check if legal file handle
  1502.  jc commit_dev
  1503. ; jmp file_update ; update directory & FAT if written
  1504. ; Update directory & File Allocation Table (partial close)
  1505. ; entry: ES:BX -> DHNDL_
  1506. ; exit: ES:BX preserved
  1507. Public file_update
  1508. file_update:
  1509. ;-----------
  1510. test es:DHNDL_ATTR[bx],DHAT_CLEAN
  1511.  jnz file_updt20 ; skip if file is clean
  1512. mov al,es:DHNDL_DCNTLO[bx] ; get directory count
  1513. mov ah,es:DHNDL_DCNTHI[bx]
  1514. dec ax
  1515. mov dcnt,ax ; set search position
  1516. xor cx,cx ; find any entry
  1517. mov chdblk,cx ; non-sequential access
  1518. push es ! push bx
  1519. call getdir ; read the directory entry
  1520. pop bx ! pop es
  1521. test ax,ax ; did we find something?
  1522.  jz file_updt10 ; skip if directory entry lost
  1523. xchg ax,di ; DI -> directory entry in buffer
  1524. or DATTS[di],DA_ARCHIVE ; mark file as modified
  1525. ;;; call timestamp_dhndl ; record the current time
  1526. mov ax,es:DHNDL_BLK1[bx] ; AX = 1st block in file
  1527. lea di,DTIME[di] ; DI -> [time,date,block1,size]
  1528. push es ! push bx
  1529. push ds
  1530.     lea si,DHNDL_TIME[bx]
  1531. push ds ! push es
  1532. pop ds ! pop es ; swap ES and DS
  1533. movsw ! movsw ; copy time then date
  1534. stosw ; now 1st cluster
  1535. movsw ! movsw ; finally file size
  1536. pop ds
  1537. call update_dir ; update directory
  1538. call update_fat ; flush dirty FAT
  1539. call update_dat ; flush all dirty data buffers
  1540. pop bx ! pop es
  1541. or es:DHNDL_ATTR[bx],DHAT_CLEAN
  1542. ret ; only mark as clean AFTER it's written
  1543. file_updt10:
  1544. mov ax,ED_H_MATCH ; can't find open file
  1545. mov fdos_ret,ax ; save error code
  1546. ret
  1547. eject
  1548. ; CREATE NEW FILE
  1549. ; +----+----+----+----+----+----+----+----+
  1550. ; |    51   |        name       |  mode   |
  1551. ; +----+----+----+----+----+----+----+----+
  1552. ; entry:
  1553. ; ------
  1554. ; name: segmented address of ASCIIZ name
  1555. ;   mode:   attribute for file 
  1556. ; exit:
  1557. ; -----
  1558. ; AX: file handle or error code ( < 0)
  1559. ; Note: The function is identical to CREATE FILE
  1560. ; with the exception that an error is returned
  1561. ; if the specified file already exists.
  1562. fdos_mknew:
  1563. ;----------
  1564. call redir_asciiz_offer
  1565. call local_disk ; get MXdisk, switch stack
  1566. call mustbe_free_handle ; make sure we have spare handle
  1567. call path_prep_chk ; parse path, walk down the tree
  1568. call finddfcbf ; check if we can find this one
  1569.  jnz mknew10
  1570. test byte ptr fdos_pb+8,DA_VOLUME
  1571.  jz mknew_nolbl ; skip if not volume label
  1572. call mustbe_nolbl ; do we have an existing label ?
  1573. mknew_nolbl:
  1574. jmp creat_new_file ; go ahead and create the file
  1575. mknew10:
  1576.     mov ax,ED_EXISTS        
  1577. jmp fdos_error
  1578. eject
  1579. ; LOCK/UNLOCK FILE DATA (LOCK/UNLOCK)
  1580. ; +----+----+----+----+----+----+----+----+
  1581. ; |    52   |  handle |       offset      |
  1582. ; +----+----+----+----+----+----+----+----+
  1583. ; |       length      |   lock  |
  1584. ; +----+----+----+----+----+----+
  1585. ; entry:
  1586. ; ------
  1587. ; handle: open file handle
  1588. ; offset: long integer offset
  1589. ; length: long integer byte count
  1590. ; lock: 0 = lock, 1 = unlock
  1591. ; exit:
  1592. ; -----
  1593. ; AX: byte count or error code ( < 0)
  1594. fdos_lock:
  1595. ;---------
  1596. call vfy_dhndl_ptr ; check file handle #
  1597. test es:DHNDL_WATTR[bx],DHAT_DEV
  1598.  jnz lock_dev ; skip if character device
  1599. call redir_dhndl_offer
  1600. call local_disk ; get MXdisk, switch stack
  1601. call check_handle ; check if legal file handle
  1602. mov ax,ED_ACCESS ; assume a problem
  1603.  jc lock_error ; can't lock/unlock device handles
  1604. mov di,offset fdos_pb
  1605. callf ss:share_stub+S_LOCKS ; call the stub routine
  1606.  jnc lock_ret ; return error if we got one
  1607. lock_error:
  1608. jmp fdos_error ; can't do locking
  1609. lock_dev:
  1610. mov bx,ED_ACCESS
  1611. lock_ret:
  1612. ret
  1613. eject
  1614. ; BUILD DDSC FROM BPB
  1615. ; +----+----+----+----+----+----+----+----+----+----+
  1616. ; |    53   |       bpbptr      !      ddscptr      |
  1617. ; +----+----+----+----+----+----+----+----+----+----+
  1618. ; entry:
  1619. ; ------
  1620. ; bpbptr: address of BPB
  1621. ; ddscptr: address of DDSC to be built
  1622. ; exit:
  1623. ; -----
  1624. ; 0000 or error code ( < 0)
  1625. fdos_mkddsc:
  1626. ;-----------
  1627. push ds
  1628. mov si,2[bp] ; SI -> parameter block
  1629. les di,6[si] ; ES:DI -> DDSC
  1630. lds si,2[si] ; DS:SI -> BPB
  1631. call bpb2ddsc ; convert BPB to DDSC
  1632. xor bx,bx ; no error
  1633. pop ds ; restore segment register
  1634. ret
  1635. bpb2ddsc:
  1636. ;--------
  1637. ; build a DDSC from a BPB, leavinf UNIT, RUNIT, DEVICE, FIRST, and LINK fields
  1638. ; unchanged
  1639. ; On Entry:
  1640. ; DS:SI -> source BPB
  1641. ; ES:DI -> destination DDSC
  1642. ; On Exit:
  1643. ; None
  1644. lodsw ; get sector size in bytes
  1645. mov es:DDSC_SECSIZE[di],ax
  1646. lodsb ; get sectors/allocation unit
  1647. dec ax ; get cluster mask
  1648. mov es:DDSC_CLMSK[di],al ; store cluster mask
  1649. lodsw ; get FAT address
  1650. mov es:DDSC_FATADDR[di],ax
  1651. lodsb ; get # of fats
  1652. mov es:DDSC_NFATS[di],al
  1653. cbw ; make it a word value
  1654. xchg ax,dx ; and keep in DX
  1655. lodsw ; get # of directory entries
  1656. mov es:DDSC_DIRENT[di],ax
  1657. lodsw ; get # of sectors total in image
  1658. push ax ; save disk size for later
  1659. lodsb ; get FAT id byte
  1660. mov es:DDSC_MEDIA[di],al ; set media byte
  1661. lodsw ; get # of sectors in a fat
  1662. if DOS5
  1663. mov es:DDSC_NFATRECS[di],ax ; set FAT size
  1664. else
  1665. mov es:DDSC_NFATRECS[di],al ; set FAT size
  1666. endif
  1667. mul dx ; AX = FAT size
  1668. add ax,es:DDSC_FATADDR[di] ; AX = 1st directory sector
  1669. mov es:DDSC_DIRADDR[di],ax ; set root directory address
  1670. add si,word+word+dword ; skip SPT, NHEADS, BIGHIDDEN
  1671. mov cx,es:DDSC_SECSIZE[di]
  1672. mov ax,32 ; size of single directory entry
  1673. mul es:DDSC_DIRENT[di] ; AX/DX = root directory bytes
  1674. add ax,cx ; round up sector size
  1675. dec ax ;  in case of odd number
  1676. div cx ; convert to whole sectors
  1677. add ax,es:DDSC_DIRADDR[di] ; add in base of root directory
  1678. mov es:DDSC_DATADDR[di],ax ; set this as first cluster address
  1679. pop ax ; recover total disk size
  1680. xor dx,dx ; assume 16 bit number
  1681. test ax,ax ; test for big drive
  1682.  jnz bpb2ddsc10 ; skip if not large drive
  1683. lodsw ; get low word of size
  1684. mov dx,[si] ; get high word of size
  1685. bpb2ddsc10: ; AX/DX = disk size in sectors
  1686. sub ax,es:DDSC_DATADDR[di] ; subtract non-data portion
  1687. sbb dx,0
  1688. xor cx,cx ; CL = cluster shift
  1689. mov ch,es:DDSC_CLMSK[di] ; CH = cluster mask
  1690. bpb2ddsc20: ; count # of 1 bits
  1691. shr ch,1 ; shift right mask
  1692.  jnc bpb2ddsc30 ; skip if all 1 bits shifted out
  1693. inc cx ; count another 1 bit
  1694. shr dx,1
  1695. rcr ax,1 ; div by two
  1696. jmps bpb2ddsc20 ; repeat until all 1's counted
  1697. bpb2ddsc30: ; CL = log2 (CH)
  1698. mov es:DDSC_CLSHF[di],cl ; set cluster shift
  1699. inc ax ; clusters 0/1 reserved (+2), and we
  1700. mov es:DDSC_NCLSTRS[di],ax ;  want max (-1), so +1
  1701. xor ax,ax
  1702. mov es:DDSC_BLOCK[di],ax ; next block = 0
  1703. dec ax
  1704. mov es:DDSC_FREE[di],ax ; free space = -1 (unknown)
  1705. ret
  1706. eject
  1707. ; DIRECT DISK IO
  1708. ; +----+----+----+----+----+----+
  1709. ; |    54   |drv | op |nsectors |
  1710. ; +----+----+----+----+----+----+----+----+
  1711. ; |      startsec     |    dma address    |
  1712. ; +----+----+----+----+----+----+----+----+
  1713. ; entry:
  1714. ; ------
  1715. ; param block set up for direct disk IO 
  1716. ; exit:
  1717. ; -----
  1718. ; AX = 0, or error code
  1719. ;
  1720. DIO_25_READ_OP equ 1
  1721. DIO_26_WRITE_OP equ 2
  1722. fdos_ddio:
  1723. ;---------
  1724. ; Used by emulator for Int 25H/26H disk calls to BIOS
  1725. ;
  1726. ; entry: dio = offset of parameter block in user data segment
  1727. ;
  1728. ; exit: AX = return code from BIOS
  1729. call local_disk ; get the MX
  1730. mov ax,fdos_pb+WORD ; AX = logical drive
  1731. call logical2physical ; AX = physical drive
  1732. call get_ddsc ; make sure this drive is valid
  1733.  jc fdos_ddio30 ; bail if not
  1734. mov adrive,al ; remember this unit
  1735. mov ax,CMD_INPUT+0*256 ; disk read operation of system area
  1736. cmp byte ptr fdos_pb+3,DIO_26_WRITE_OP
  1737.  jne fdos_ddio10
  1738. mov ax,0FFFFh
  1739. mov es:DDSC_FREE[bx],ax ; free space = -1 (unknown)
  1740. call hshdscrd ; discard hashing info for all drives (AL=FF)
  1741. mov ax,CMD_OUTPUT+1*256 ; disk write operation of system area
  1742. fdos_ddio10:
  1743. mov rwmode,ah ; save read/write of system area
  1744. mov req_hdr+5,ah ; (so driver can get the hint)
  1745. mov bx,offset req_hdr ; we will build request here
  1746. mov RH_CMD[bx],al ; save the command
  1747. mov ax,fdos_pb+4 ; AX = # sectors
  1748. mov RH4_COUNT[bx],ax ; set requested sector count
  1749. les ax,dword ptr fdos_pb+6 ; pick up 32-bit record address
  1750. mov word ptr pblock,ax
  1751. mov word ptr pblock+WORD,es
  1752. les ax,dword ptr fdos_pb+10 ; ES:AX -> DMA seg
  1753. mov RH4_BUFOFF[bx],ax
  1754. mov RH4_BUFSEG[bx],es
  1755. call ddioif ; go do it
  1756.  jns fdos_ddio20 ; did we have a problem ?
  1757. cbw ; AX = base error
  1758. add ax,ED_PROTECT ; "add" in BIOS error code
  1759. mov fdos_ret,ax ; save return code
  1760. fdos_ddio20:
  1761. ret
  1762. fdos_ddio30:
  1763. jmp fdos_ED_DRIVE ; return bad drive error
  1764. eject
  1765. ; EXPAND FILE NAME
  1766. ; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+
  1767. ; |    55   |   relative name   |                   |   absolute name   |
  1768. ; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+
  1769. ; entry:
  1770. ; ------
  1771. ; relative name: segmented address of ASCIIZ name
  1772. ; absolute name: segmented address of ASCIIZ name
  1773. ; exit:
  1774. ; -----
  1775. ; AX = BX: 0000 or error code ( < 0)
  1776. fdos_expand:
  1777. ;-----------
  1778. call redir_asciiz_dev_offer ; is it a networked device ?
  1779. call asciiz_dev_offer ; see it we are expanding a device name
  1780. call local_disk ; get MXdisk, switch stack
  1781. push ds
  1782. les si,dword ptr fdos_pb+2 ; get relative name buffer
  1783. mov ax,es:[si] ; get 1st two chars of path
  1784. call check_dslash ; is it a '\' form ?
  1785.  je fdos_expand10
  1786. mov bx,ED_FILE
  1787.     test    al,al           
  1788.  jz fdos_expand60
  1789. call toupper ; work on premise we have drive
  1790. sub al,'A' ; specified in relative name
  1791. sub ah,':' ; did we have ?
  1792.  je fdos_expand20 ; if so use it
  1793. fdos_expand10:
  1794. mov al,current_dsk ; use current drive
  1795. fdos_expand20:
  1796. cmp al,last_drv ; is it a legal drive
  1797.  jae fdos_expand50
  1798. ; we should check for a media change so select_logical_drv seems to be
  1799. ; a better solution
  1800. ; call get_ldt ; ES:BX -> LDT_ for drive
  1801. ;  jc fdos_expand40 ; no LDT at init - copy relative path
  1802. ; mov word ptr current_ldt,bx
  1803. ; mov word ptr current_ldt+WORD,es
  1804. call select_logical_drv
  1805. les bx,current_ldt
  1806. test es:LDT_FLAGS[bx],LFLG_PHYSICAL
  1807.  jz fdos_expand50 ; make sure it's a valid drive
  1808. push ss ! pop es
  1809. mov di,offset pri_pathname ; build name in pathname buffer
  1810. lds si,dword ptr fdos_pb+2
  1811. ; we must trick redir_build_path to find the correct function number -
  1812. ; otherwise we could not get correct (critical) error reporting to work
  1813. push bp
  1814. mov bp,offset fdos_pb+6
  1815. mov 2[bp],bp
  1816. mov byte ptr [bp],FD_EXPAND
  1817. call redir_build_path ; build name from LDT
  1818. pop bp
  1819.  jc fdos_expand60 ; bail out if bad name
  1820. lds di,ss:current_ldt ; we need to append a '' if
  1821. mov bx,ds:LDT_ROOTLEN[di] ;  we are at the root
  1822. test ds:LDT_FLAGS[di],LFLG_SUBST
  1823.  jz fdos_expand30 ; if drive is SUBST'd then
  1824. mov bx,2 ;  only append if real root
  1825. fdos_expand30:
  1826. mov si,offset pri_pathname ; SS:SI -> full path
  1827. push ss ! pop ds ; leave current ldt -> buffer as LAN
  1828. mov word ptr current_ldt,si ;  MAN 2.1 extended edition expects it
  1829. mov word ptr current_ldt+WORD,ds
  1830. mov ax,'' ; get pathchar in AX for checks
  1831. cmp ds:byte ptr [si+bx],ah ; are we at the root ?
  1832.  jne fdos_expand40 ; if so append a ''
  1833. mov ds:word ptr [si+bx],ax
  1834. fdos_expand40:
  1835. les di,ss:dword ptr fdos_pb+10; ES:DI -> destination buffer
  1836. call copy_asciiz ; copy the full pathname
  1837. pop ds
  1838. ret
  1839. fdos_expand50:
  1840. mov bx,ED_DRIVE ; return bad drive error
  1841. fdos_expand60:
  1842. mov ax,bx
  1843. pop ds
  1844. jmp fdos_error
  1845. expand_dev:
  1846. ;----------
  1847. les si,dword ptr fdos_pb+2 ; this is the original source
  1848. lods es:ax ; get the source
  1849. les di,dword ptr fdos_pb+10 ; data will end up here
  1850. cmp ah,':' ; is a drive specified ?
  1851.  je expand_dev10
  1852. mov al,'A'
  1853. add al,ss:current_dsk
  1854. expand_dev10:
  1855. call toupper ; make sure drive letter is upper case
  1856. stosb ; plant an 'd'
  1857. mov ax,':'+256*'/'
  1858. stosw ; make that 'd:/'
  1859. mov bx,offset name_buf ; DS:BX -> name buffer
  1860. jmp unparse ; unparse the device name
  1861. eject
  1862. ; RENAME FILE
  1863. ; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+
  1864. ; |    56   |      old name     |                   |      new name     |
  1865. ; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+
  1866. ; entry:
  1867. ; ------
  1868. ; old name: segmented address of ASCIIZ name
  1869. ; new name: segmented address of ASCIIZ name
  1870. ; exit:
  1871. ; -----
  1872. ; AX: 0000 or error code ( < 0)
  1873. ; Note: R/O files can be renamed.
  1874. ;   ---
  1875. fdos_move:
  1876. ;---------
  1877. call redir_move_offer
  1878. call local_disk ; get MXdisk, switch stack
  1879. call path_prep ; parse the path, go to bottom level
  1880. call chk_no_dev
  1881. cmp ss:remote_call,0 ; wildcards allowed if server/FCB
  1882.  jnz move10
  1883. call chk_no_wild ; make sure not a wild card
  1884. move10:
  1885. call finddfcbf ; else try to locate directory entry
  1886.  jz fdos_ED_FILE ; error if no match occurred
  1887. move20:
  1888. call close_if_same_psp ; make sure not open by other PDs
  1889. if PASSWORD
  1890. call check_pwd_any ; check if password protected
  1891. endif
  1892. mov si,dirp ; get matching directory entry
  1893. mov di,offset save_area ; get a temporary save area
  1894. mov cx,32/WORD ; save it all
  1895. rep movsw ; so we can move it to new entry
  1896. mov si,offset fdos_hds
  1897. mov di,offset saved_hds
  1898. mov cl,HDS_LEN
  1899. rep movsb ; copy current HDS to safe place
  1900. mov ax,dcnt ; also save directory index
  1901. mov saved_dcnt,ax ; so we can release entry later
  1902. les di,dword ptr fdos_pb+10 ; es:di -> path name
  1903. call path_prep_ptr ; find the destination path
  1904. call chk_no_dev ; no devices allowed here
  1905. cmp ss:remote_call,0 ; wildcards allowed if server/FCB
  1906.  jnz move25
  1907. call chk_no_wild ; make sure not a wild card
  1908. move25:
  1909. mov al,fdos_hds_drv ; get the work drive
  1910. cmp al,saved_hds_drv ; make sure same drive for
  1911.  je move30 ;   source and destination
  1912. mov ax,ED_DEVICE ; "not same device" error
  1913. jmps fdos_moverr ; return the error
  1914. fdos_ED_FILE:
  1915. mov ax,ED_FILE ; get error code
  1916. fdos_moverr:
  1917. jmp fdos_error ; return the error
  1918. move30: ; same drive for source & destination
  1919. mov al,byte ptr fdos_pb+8 ; check attributes
  1920. if PASSWORD
  1921. cmp save_area+DPWD,0
  1922.  je move31
  1923. or al,DA_HIDDEN
  1924. move31:
  1925. endif
  1926. not al
  1927. and al,DA_HIDDEN+DA_SYSTEM+DA_DIR+DA_VOLUME
  1928. test save_area+DATTS,al
  1929.  jnz move80
  1930. mov si,offset info_fcb+1 ; SI->new name (possible wildcards)
  1931. mov di,si ; DI->new name
  1932. mov bx,offset save_area ; current name on disk
  1933.     cmp byte ptr DNAME[bx],'.'  
  1934.      je move80          
  1935. mov cx,11
  1936. move40: ; fill in the wild card characters
  1937. lodsb ; get next character from new name
  1938. if KANJI
  1939. call dbcs_lead ; is it the 1st of a kanji pair
  1940.  jne move45
  1941. dec cx ; copied this one
  1942.  jcxz move55 ; discard if no room for kanji char
  1943. stosb ; copy 1st byte of Kanji pair
  1944. inc bx
  1945. lodsb ; copy 2nd byte
  1946. jmps move50
  1947. move45:
  1948. endif
  1949. call toupper ; make it upper case
  1950. cmp al,'?' ; is it just a wild card?
  1951.  jne move50 ; no, put in destination as is
  1952. mov al,[bx] ; else leave original character
  1953. move50: ; AL = next char for destination
  1954. stosb ; store next char in destination
  1955. inc bx ; increment all pointers
  1956. loop move40 ; repeat for all 11 characters
  1957. move55:
  1958. call finddfcbf ; find first non-volume entry
  1959.  jnz move_access ; file already exists, return error
  1960. call move_comp ; source & destination in same dir?
  1961.  jne move60 ; skip if moving to different directory
  1962. call move_seek ; else find old entry again
  1963. jmps move70 ; replace name in old entry
  1964. move60: ; moving to different directory
  1965. test save_area+DATTS,DA_DIR ; can't move directory to new path
  1966.  jnz move_access ; so return error if new path
  1967. call allocdir ; allocate a directory entry
  1968. move70:
  1969. mov si,offset info_fcb+1 ; get pointer to new name
  1970. mov di,dirp ; get pointer to directory entry
  1971. mov cx,11 ; copy new name into buffer
  1972. rep movsb
  1973. mov si,offset save_area+11 ; copy remaining info
  1974. mov cx,32-11
  1975. rep movsb
  1976. call update_dir ; update the disk
  1977. call move_comp ; did we rename across directories?
  1978.  je move80 ; skip if in same directory
  1979. mov si,offset saved_hds
  1980. mov di,offset fdos_hds ; else need to copy HDS back
  1981. mov cx,HDS_LEN ; so we can get old entry again
  1982. rep movsb ;    (time to get rid of it)
  1983. call move_seek ; seek the original entry
  1984. mov bx,dirp
  1985. mov DNAME[bx],0E5h ; and bye, bye! it goes...
  1986. call update_dir ; update the old directory entry
  1987. move80:
  1988. cmp ss:remote_call,0 ; wildcards allowed if server/FCB
  1989.  jz move90 ;  so check for multiple files
  1990. call path_prep ; parse the path, go to bottom level
  1991. mov ax,saved_dcnt ; restore dcnt for remote call
  1992. mov dcnt,ax ; to function properly
  1993. and chdblk,0
  1994. call finddfcb ; try to locate another directory entry
  1995.  jz move90 ; no, return now
  1996. jmp move20 ;  round again if we do
  1997. move_access:
  1998. jmp fdos_ED_ACCESS ; "access denied" if file
  1999. ;     already exists
  2000. move90:
  2001. ; in order to update the current directory in case part of it has been
  2002. ; renamed we call fdos_chdir which does all the work for rebuilding
  2003. ; the LDT_ for the given drive
  2004. push ss
  2005. pop ds
  2006. mov bx,offset sec_pathname
  2007. mov ax,path_drive
  2008. add ax,'A'+(':'*100h)
  2009. mov [bx],ax
  2010. mov word ptr 2[bx],'.'
  2011. mov fdos_pb+4,ds
  2012. mov fdos_pb+2,bx
  2013. mov byte ptr remote_call,0
  2014. jmp fdos_move_chdir
  2015. move_seek: ; re-seek the old directory entry
  2016. mov ax,saved_dcnt ; get saved directory count
  2017. dec ax ; move back one for GETDIR
  2018. mov dcnt,ax ; set search offset
  2019. and chdblk,0 ; follow the chains, not sequential
  2020. mov cl,0 ; return next entry
  2021. jmp getdir ; in current directory
  2022. move_comp:
  2023. mov ax,fdos_hds_blk
  2024. cmp ax,saved_hds_blk
  2025. ret
  2026. eject
  2027. ; GET/SET FILE DATE/TIME
  2028. ; +----+----+----+----+----+----+----+----+----+----+
  2029. ; |    57   |  handle |   mode  |   date  |   time  |
  2030. ; +----+----+----+----+----+----+----+----+----+----+
  2031. ; entry:
  2032. ; ------
  2033. ; handle: open file handle
  2034. ; mode: 0 = get date/time, 1 = set date/time
  2035. ; date: date as in directory FCB
  2036. ; time: time as in directory FCB
  2037. ; exit:
  2038. ; -----
  2039. ; AX: 0000 or error code ( < 0)
  2040. ; date: date of last modification if mode = 0
  2041. ; time: date of last modification if mode = 0
  2042. fdos_dattim:
  2043. ;-----------
  2044. call vfy_dhndl_ptr ; check file handle #
  2045. call redir_dhndl_offer
  2046. call local_disk ; get MXdisk, switch stack
  2047. call check_handle ; check if legal file handle
  2048. cmp fdos_pb+4,0 ; get/set date/time?
  2049.  jne dattim1
  2050. mov ax,es:DHNDL_DATE[bx] ; get date
  2051. mov fdos_pb+6,ax
  2052. mov ax,es:DHNDL_TIME[bx] ; get time
  2053. mov fdos_pb+8,ax
  2054. ret
  2055. dattim1: ; else set date/time stamp
  2056. mov dx,fdos_pb+6 ; set date
  2057. mov ax,fdos_pb+8 ;  and time
  2058. jmps set_timestamp
  2059. Public timestamp_dhndl
  2060. timestamp_dhndl:
  2061. ;---------------
  2062. ; On Entry:
  2063. ; ES:BX -> DHNDL_
  2064. ; On Exit:
  2065. ; ES:BX preserved
  2066. ;
  2067. ; Mark this DHNDL_ with the current time and date
  2068. push es
  2069. push bx
  2070. call ReadTOD ; get TOD in DX/AX
  2071. pop bx
  2072. pop es
  2073. ; jmp set_timestamp
  2074. set_timestamp:
  2075. ;-------------
  2076. ; On Entry:
  2077. ; ES:BX -> DHNDL_
  2078. ; AX = time
  2079. ; DX = date
  2080. ; On Exit:
  2081. ; None
  2082. ;
  2083. and es:DHNDL_ATTR[bx],not DHAT_CLEAN
  2084. mov es:DHNDL_DATE[bx],dx ; remember to update directory
  2085. mov es:DHNDL_TIME[bx],ax ; ask SHARE to record the changes
  2086. callf share_stub+S_RECORD ;  for the benefit of others
  2087. ret
  2088. fdos_reopen_fcb:
  2089. ;---------------
  2090. ; On entry
  2091. ; On exit  on success pb offset 6 set to 0 if device, 1 if disk file
  2092. test byte ptr remote_call+1,DHM_FCB/100h
  2093. jnz fcb_reopen0
  2094. mov ax,ED_FUNCTION
  2095. jmp fdos_error
  2096. fcb_reopen0:
  2097. call local_disk
  2098. call path_prep
  2099.  jc fcb_reopen_error ; any error means reopen is invalid
  2100. call check_device
  2101.  jnc fcb_reopen_error ; we should not find devices here
  2102. mov ax,fdos_pb+6
  2103. mov fdos_hds_blk,ax
  2104. mov ax,fdos_pb+8
  2105. dec ax
  2106. mov dcnt,ax
  2107. xor cx,cx
  2108. mov chdblk,cx
  2109. call getdir
  2110.  jz fcb_reopen_error
  2111. cmp DNAME[bx],0e5h ; has the entry been deleted ?
  2112.  je fcb_reopen_error
  2113. mov fdos_pb+2,ax
  2114. ret
  2115. fcb_reopen_error:
  2116. mov ax,ED_NOFCBS
  2117. jmp fdos_error