FUNCS.FDO
资源名称:drdossrc.zip [点击查看]
上传用户:xiaogehua
上传日期:2007-01-08
资源大小:1183k
文件大小:66k
源码类别:
操作系统开发
开发平台:
Asm
- ; File : $FUNCS.FDO$
- ;
- ; Description :
- ;
- ; Original Author : DIGITAL RESEARCH
- ;
- ; Last Edited By : $CALDERA$
- ;
- ;-----------------------------------------------------------------------;
- ; Copyright Work of Caldera, Inc. All Rights Reserved.
- ;
- ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
- ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
- ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
- ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
- ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
- ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
- ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
- ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
- ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
- ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
- ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
- ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
- ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
- ; CIVIL LIABILITY.
- ;-----------------------------------------------------------------------;
- ;
- ; *** Current Edit History ***
- ; *** End of Current Edit History ***;
- ; $Log$;
- ; ENDLOG
- ; General function include module for FDOS.A86
- BDOS_CODE cseg
- public fdos_entry
- ;==========
- fdos_entry: ; FDOS module entry point
- ;==========
- ; On Entry:
- ; DS:DX -> parameter block
- ; On exit:
- ; AX = BX = return code
- ; (DS/ES corrupted)
- ; entry: DS:DX = argument
- ;
- ; exit: AX,BX = return code
- mov si,dx
- lodsw ; AX = FDOS number
- sub ax,39h ; base it at zero
- jc fd_error ; stop if too low
- cmp ax,FDOS_MAX ; check if function in range
- jae fd_error ; yes, continue
- push ds ; save parameter segment
- push dx ; save parameter offset
- push ax ; save sub-function
- mov bp,sp ; SS:BP -> working variables
- mov bx,ax
- add bx,ax
- add bx,ax
- call fdos_tbl[bx]
- add sp,3*WORD ; clean up stack
- mov ax,bx
- ret
- fd_error:
- mov ax,ED_FUNCTION ; return "invalid function"
- mov bx,ax
- ret
- fdos_tbl dw fdos_mkdir ; 39-make directory
- db 2
- dw fdos_rmdir ; 3A-remove directory
- db 2
- dw fdos_chdir ; 3B-change directory
- db 2
- dw fdos_creat ; 3C-create file
- db 4
- dw fdos_open ; 3D-open file
- db 4
- dw fdos_close ; 3E-close file
- db 1
- dw fdos_read ; 3F-read from file
- db 4
- dw fdos_write ; 40-write to file
- db 4
- dw fdos_unlink ; 41-delete file
- db 4
- dw fdos_lseek ; 42-set file pointer
- db 4
- dw fdos_chmod ; 43-get/set file attributes
- db 6
- dw fdos_ioctl ; 44-IOCTL emulation
- db 3
- dw fdos_dup ; 45-duplicate handle
- db 2
- dw fdos_fdup ; 46-force duplicate handle
- db 2
- dw fdos_curdir ; 47-get current directory
- db 3
- dw fdos_getdpb ;*48*disk information
- db 4
- dw fdos_flush ;*49*flush buffers
- db 0
- dw fdos_select ;*4A*drive select
- db 1
- dw fdos_exec ;*4B*create child PSP
- db 1
- dw fdos_exit ;*4C*close child PSP
- db 0
- dw fdos_fcb ;*4D*generic FCB call
- db 5
- dw fdos_first ; 4E-find first matching file
- db 4
- dw fdos_next ; 4F-find next matching file
- db 0
- dw fdos_commit ;*50*commit file
- db 1
- dw fdos_mknew ;*51*make new file
- db 4
- dw fdos_lock ;*52*lock/unlock block
- db 6
- dw fdos_mkddsc ; 53 build DDSC from BPB
- db 4
- dw fdos_ddio ;*54*Int 25/26 emulation
- db 6
- dw fdos_expand ;*55*expand file name
- db 6
- dw fdos_move ; 56-rename file
- db 6
- dw fdos_dattim ; 57-get/set file name
- db 4
- dw fdos_reopen_fcb ; 58-FCB reopen support function
- db 5
- FDOS_MAX equ (offset $ - offset fdos_tbl) / 3
- Public local_disk
- local_disk: ; continue execution within MXdisk semaphore
- ;----------
- ; This function will make local copies of the parameters
- ; and continue
- callf ss:lock_tables
- pop fdos_addr ; return address
- add sp,2*WORD ; discard return from call fdos_tbl[bx]
- ; and function #
- pop si ; get parameter offset
- pop ax ; get parameter segment
- mov sp_save,sp ; save for re-entry/errors
- mov ds,ax ; DS:SI -> paremeter block
- fdos_reenter:
- push ss ! pop es ; ES = local data segment
- mov di,offset fdos_pb ; ES:DI -> local parameter block copy
- lodsw ! stosw ; load subfunction number
- mov es:fdos_info,si ; save it for BDOS return
- mov es:fdos_info+WORD,ds ; save parameter segment for return
- mov bx,ax
- add bx,ax
- add bx,ax ; BX = function # * 3
- mov cl,byte ptr fdos_tbl-(39h*(WORD+BYTE))+WORD[bx]
- mov ch,0
- ; get table of # of parameters
- mov es:fdos_info+2*WORD,cx ; save the parameter count
- rep movsw ; copy parameter block
- push es ! pop ds ; DS = SYSDAT
- mov ioexerr,0FFh ; assume default error code
- mov rwmode,0
- mov finddfcb_mask,DA_VOLUME*256
- xor ax,ax
- mov fdos_ret,ax ; assume success unless proven otherwise
- call fdos_addr ; call code following "call local_disk"
- mov ax,fdos_ret ; get return code, fall thru to exit
- Public fdos_error
- fdos_error:
- ;----------
- ; AX = return code
- mov sp,sp_save ; stack to entry value (for errors)
- mov si,offset fdos_pb+2 ; get local copy
- les di,dword ptr fdos_info ; get parameter block address
- mov cx,fdos_info+2*WORD ; get parameter block size
- rep movsw ; copy return values
- mov bx,ax
- callf ss:unlock_tables
- ret ; return to BDOS, which copies BX to AX
- Public fdos_restart
- fdos_restart: ; we want to restart the function after an error
- ;------------ ; we already have MXdisk
- ;
- mov sp,sp_save ; break out from low levels
- lds si,dword ptr fdos_info
- dec si ! dec si ; DS:SI -> parameter block
- jmps fdos_reenter ; try from scratch
- fdos_ED_ROOM:
- ;-----------
- mov ax,ED_ROOM ; no more files
- jmps fdos_error
- fdos_ED_DRIVE:
- ;-----------
- mov ax,ED_DRIVE ; bad drive
- jmps fdos_error
- fdos_ED_PATH:
- mov ax,ED_PATH ; invalid path or drive
- jmps fdos_error
- fdos_ED_PROTECT:
- mov ax,ED_PROTECT ; write protect error
- jmps fdos_error
- Public fdos_ED_ACCESS
- fdos_ED_ACCESS:
- mov ax,ED_ACCESS ; access denied error
- jmps fdos_error
- eject
- ; MAKE DIRECTORY (MKDIR)
- ; +----+----+----+----+----+----+
- ; | 39 | name |
- ; +----+----+----+----+----+----+
- ; entry:
- ; ------
- ; name: segmented address of ASCIIZ name
- ; exit:
- ; -----
- ; AX: 0000 or error code ( < 0)
- fdos_mkdir:
- ;----------
- call redir_asciiz_offer
- call local_disk ; get MXdisk, switch stack
- call path_prep_chk ; parse path, walk down the tree
- call finddfcbf ; find matching FCB
- jnz mkdir_access ; file/dir exists, "access denied"
- call allocdir ; allocate a directory entry
- push ax ; save pointer to directory entry
- lea si,info_fcb+1 ; SI -> file name
- xchg ax,di ; DI -> DNAME
- mov cx,11
- rep movsb ; copy file name into directory buffer
- ; lea di,DATTS[si]
- mov al,DA_DIR
- stosb ; mark it as a directory
- xor ax,ax
- mov cx,(32-12)
- rep stosb ; zero remainder of new FCB
- pop si ; SI -> directory
- call stamp_dir_entry ; set time and date in FCB
- xor ax,ax
- call alloc_cluster ; Allocate a block
- jc mkdir_err ; Report Error(no room on disk)
- mov si,dirp
- mov DBLOCK1[si],ax ; Initialize 1st block of fcb
- push ax ; save block
- call update_fat ; Write the fat to disk
- call update_dir ; Write the directory to disk
- pop ax ; now initialise the sub-directory
- call mkdir_init ; '.' and '..' entries
- call update_dir ; update directory entry
- mov ax,5 ; return a magic value for some
- mov fdos_ret,ax ; PD expansion program
- ret
- mkdir_err:
- ;---------
- mov bx,dirp ; can't make dir, no data space
- mov DNAME[bx],0E5h ; so release our directory entry
- call update_dir ; release this entry
- mkdir_access:
- jmp fdos_ED_ACCESS ; return "access denied" error
- chk_no_dot: ; reject "." and ".." names
- cmp info_fcb+1,'.'
- je mkdir_access
- ret
- eject
- ; REMOVE DIRECTORY (RMDIR)
- ; +----+----+----+----+----+----+
- ; | 3A | name |
- ; +----+----+----+----+----+----+
- ; entry:
- ; ------
- ; name: segmented address of ASCIIZ name
- ; exit:
- ; -----
- ; AX: 0000 or error code ( < 0)
- fdos_rmdir:
- ;----------
- call redir_asciiz_offer
- call local_disk ; get MXdisk, switch stack
- call path_prep_chk ; parse path to bottom level
- call finddfcbf ; try to locate directory entry
- jz fdos_rmdir20 ; skip if we can't find it
- test DATTS[bx],DA_DIR ; check directory attribute
- jz fdos_rmdir30 ; O.K. if a directory
- call chkcds ; make sure no-where current
- jnc fdos_rmdir40
- call path_prep ; redo as rmdir_ok may destroy info
- call finddfcbf ; find the entry again
- call rmdir_ok ; make sure not in use
- call finddfcbf ; find the entry again
- if PASSWORD
- call check_pwd_any
- endif
- kill_entry:
- call kill_file ; actually delete entry
- update_dir_fat:
- call update_dir ; update directory entry
- jmp update_fat ; update file allocation table
- fdos_rmdir20:
- jmp fdos_ED_PATH ; "invalid path"
- fdos_rmdir30:
- jmp fdos_ED_ACCESS ; "access denied"
- fdos_rmdir40:
- mov ax,ED_DIR
- jmp fdos_error
- eject
- ; CHANGE DIRECTORY (CHDIR)
- ; +----+----+----+----+----+----+
- ; | 3B | name |
- ; +----+----+----+----+----+----+
- ; entry:
- ; ------
- ; name: segmented address of ASCIIZ name
- ; exit:
- ; -----
- ; AX: 0000 or error code ( < 0)
- chdir_ED_PATH:
- jmp fdos_ED_PATH ; all logical errors give "no path"
- chdir_ED_DRIVE:
- mov ax,ED_DRIVE ; bad drive error message
- chdir_err:
- jmp fdos_error
- fdos_chdir:
- ;----------
- call redir_asciiz_offer
- call local_disk ; get MXdisk, switch stack
- fdos_move_chdir:
- ;---------------
- mov orig_drive,0FFFFh ; set drive to invalid
- les di,dword ptr fdos_pb+2 ; get string address
- call get_path_drive ; from asciiz or default
- jc chdir_ED_DRIVE ; continue if drive A: - Z:
- call islocal ; reject networked drives
- jc chdir_ED_DRIVE ; as bad drives
- call path_prep_cont ; continue if drive legal
- jc chdir_err ; return error to application
- call chk_no_dev ; no devices allowed
- call chk_no_wild ; no wild cards allowed here
- cmp orig_drive,0FFFFh ; check if assign to specified drive
- jne chdir10 ; skip drive specified
- mov ax,path_drive ; else same as path drive
- mov orig_drive,ax
- chdir10:
- if JOIN
- call offer_join ; are we opening a JOIN'd drive ?
- jnc chdir30 ; if so move to it and skip open_dir
- endif
- call chk_for_root ; check if we are in the root
- je chdir30 ; if so, just skip the open_dir
- call finddfcbf ; try to locate directory entry
- jz chdir_ED_PATH ; skip if no valid directory
- test DATTS[bx],DA_DIR ; check directory attribute
- jz chdir_ED_PATH ; return if not a directory
- if PASSWORD
- call check_pwd_any ; check if PW prot'd & wrong PW
- endif
- call open_dir ; else open last directory
- jc chdir_ED_PATH ; return an error if we can't
- chdir30:
- mov ax,orig_drive ; get logical drive
- call get_ldt ; ES:BX -> LDT_
- jc chdir10 ; no LDT_, must be init time...
- mov si,es:LDT_FLAGS[bx] ; normally we inherit parents
- mov cx,es:LDT_ROOTLEN[bx] ; root block and drive
- mov dx,es:word ptr LDT_NAME[bx]
- mov bx,es:LDT_ROOT[bx] ; if it's a "SUBST I: C:PATH" form
- cmp ax,path_drive ; we pick up new root and drive
- je chdir50 ; like this
- mov ax,path_drive ; ASCII drive from path drive
- mov dx,'A'+256*':' ; make it into ASCII "C:"
- add dx,ax ; in case LDT does not exist
- call get_ldt ; get LDT_ in case it's subst'd
- jc chdir40
- mov dx,es:word ptr LDT_NAME[bx]
- chdir40:
- mov bx,fdos_hds_blk ; root block from fdos_hds
- chdir50:
- mov di,offset pri_pathname ; build new LDT_ here
- or si,LFLG_PHYSICAL ; drive is always physical
- mov LDT_FLAGS[di],si
- mov LDT_ROOTLEN[di],cx ; inherit rootlen from parent
- mov LDT_ROOT[di],bx ; root as above
- mov ax,fdos_hds_blk ; current block from HDS
- mov LDT_BLK[di],ax
- mov al,fdos_hds_drv ; current drive we from HDS
- mov LDT_DRV[di],al
- mov ax,word ptr current_ddsc
- mov word ptr LDT_PDT[di],ax
- mov ax,word ptr current_ddsc+WORD
- mov word ptr LDT_PDT+WORD[di],ax
- push ss ! pop es ; now build ASCII path
- ; lea di,LDT_NAME[di] ; ES:DI -> name
- xchg ax,dx
- stosw ; plant 'A:'
- mov ax,''
- stosw ; make that 'A:',0
- dec di ; point at NUL
- mov fdos_hds_root,0 ; we want to go back to root
- mov fdos_pb+6,di ; rebuild into LDT_ at the address
- mov fdos_pb+8,es
- push ds ! pop es
- chdir60:
- call hdsblk ; get current block
- if JOIN
- jnz chdir65 ; if not at root unparse
- call check_join ; check if drive is joined to another
- jz chdir80 ; at root, unJOIN'd, so exit
- ; we are at the root of this drive
- xchg al,fdos_hds_drv ; update HDS drive so we can force
- push es ; an exit next time round
- call get_ldt ; now copy the JOIN'd name
- push ds ! push es ! pop ds ! pop es
- lea si,LDT_NAME+3[bx] ; point to my JOIN data
- mov di,offset save_area
- call copy_asciiz
- push es ! pop ds
- pop es
- jmps chdir70 ; copy this into place
- chdir65:
- else
- jz chdir80 ; if at root, we're done
- endif
- call parent2save_area ; parental name written in save_area
- chdir70:
- dec di ; DI -> ' ' at end
- mov al,'' ! stosb ; add a trailing backslash
- sub di,offset save_area+1
- mov dx,di ; DX = length of name
- push es ; insert name into user buffer
- les di,dword ptr fdos_pb+6
- mov al,0 ! scasb ; check if first directory
- je chdir75 ; if not 1st in path
- inc dx ; we need space for ''
- chdir75:
- dec di ; adjust for scan
- call mkspace_parent ; move ES:DI up by DX bytes
- mov di,fdos_pb+6 ; ES:DI -> user buffer
- rep movsb ; copy directory into user buffer
- pop es ; ES = local segment again
- jmp chdir60 ; try again til root
- chdir80: ; arrive here when root reached
- mov ax,orig_drive ; get logical drive
- call get_ldt ; ES:BX -> LDT_
- jc chdir85 ; no LDT_, what happended ?
- push ds
- mov di,bx ; ES:DI -> destination LDT_
- push ss ! pop ds
- mov si,offset pri_pathname ; DS:SI -> new LDT_ we just built
- mov cx,LDT_LEN
- rep movsb ; copy the new LDT_ into place
- pop ds
- cmp ax,path_drive ; if the drive's are same
- je chdir85 ; "CD" or "SUBST d:=d:path"
- or es:LDT_FLAGS[bx],LFLG_SUBST
- lea di,LDT_NAME[bx] ; ES:DI -> name
- xor ax,ax
- mov cx,LDT_FLAGS-LDT_NAME ; name can be this long
- repne scasb ; look for terminating NUL
- sub di,bx ; get # chars skipped
- dec di ; forget the NUL
- cmp di,3 ; root is special case again !
- jbe chdir85
- mov es:LDT_ROOTLEN[bx],di ; set new root position
- chdir85:
- ret
- eject
- ; CREATE FILE (CREAT)
- ; +----+----+----+----+----+----+----+----+----+----+
- ; | 3C | name | mode | attrib |
- ; +----+----+----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; name: segmented address of ASCIIZ name
- ; mode: open mode for handle
- ; attrib: attribute for file
- ; exit:
- ; -----
- ; AX: file handle or error code ( < 0)
- fdos_creat:
- ;----------
- call redir_asciiz_dev_offer ; offer it as a network device
- call asciiz_dev_offer ; offer it as a local device
- call redir_asciiz_file_offer ; offer it as a network file
- call local_disk ; get MXdisk, switch stack
- call mustbe_free_handle ; make sure we have spare handle
- call path_prep ; parse path, walk down the tree
- call check_device ; is it a device ?
- jc creat_disk
- jmp open_dev ; open as a device handle
- creat_disk:
- call chk_no_dot_or_wild
- test byte ptr fdos_pb+8,DA_VOLUME
- jz creat_nolbl ; skip if not volume label
- call mustbe_nolbl ; do we have an existing label ?
- jmps creat_new_file ; no, create one
- creat_nolbl:
- call finddfcbf ; find entry, ignore labels
- jz creat_new_file ; skip if it doesn't exist yet
- call check_no_dir ; make sure not a directory
- call check_ro ; check if file is read/only
- call close_if_open ; make sure not open by any process
- if PASSWORD
- call check_pwd_d ; check if PW req'd & supplied
- endif
- mov bx,dirp
- mov ax,DBLOCK1[bx] ; release all blocks of the file
- call delfat ; so it is truncated to zero size
- call update_fat ; update file allocation table
- jmps creat2 ; reinitialize directory entry
- creat_new_file: ; create new file - shared by MKNEW
- call allocdir ; allocate a directory entry
- creat2:
- mov bx,dirp ; BX -> directory entry
- lea di,DNAME[bx] ; DI -> name offset in dir buffer
- mov si,offset info_fcb+1 ; SI -> name offset in FCB
- mov cx,11
- rep movsb ; copy name into directory
- mov ax,fdos_pb+8 ; get creation file attribute
- mov dx,fdos_pb+6 ; open in r/w, compatibilty mode
- test al,not (DA_RO+DA_SYSTEM+DA_HIDDEN+DA_ARCHIVE)
- jz creat5 ; allow r/o, hidden, system, archive
- test al,DA_VOLUME ; failure as file, creating a label?
- jz creat_access_err ; no, then it's really a problem
- mov dl,DHM_RO+DHM_LOCAL ; open in compatibility mode
- creat5:
- or al,DA_ARCHIVE ; always create as new file
- stosb ; update directory attributes
- sub ax,ax ; zero out remainder of entry
- mov cx,32-12
- rep stosb ; zero remainder of entry
- push bx ; save dirp
- push dx ; save the open mode
- call stamp_dir_entry ; set time and date in FCB
- call update_dir ; update directory
- pop ax ; restore open mode
- pop bx ; restore dirp
- jmp creat_handle ; now allocate file handle
- creat_access_err:
- jmp fdos_ED_ACCESS ; return "access denied"
- eject
- ; OPEN FILE (OPEN)
- ; +----+----+----+----+----+----+----+----+----+----+
- ; | 3D | name | mode | attrib |
- ; +----+----+----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; name: segmented address of ASCIIZ name
- ; mode: open mode
- ; attrib: file attrib for search (default = 16h)
- ; exit:
- ; -----
- ; AX: file handle or error code ( < 0)
- fdos_open:
- ;---------
- call redir_asciiz_dev_offer ; offer it as a network device
- call asciiz_dev_offer ; offer it as a local device
- call redir_asciiz_file_offer ; offer it as a network file
- call local_disk ; get MXdisk, switch stack
- call mustbe_free_handle ; make sure we have spare handle
- call path_prep ; parse the path, go to bottom level
- call check_device
- jc open_disk
- jmp open_dev ; open as a device
- open_disk:
- call chk_no_wild ; we don't allow no wild cards here
- call finddfcbf ; search by name
- jz open8 ; bail out if not found
- mov al,byte ptr fdos_pb+8 ; check requested attributes
- if PASSWORD
- cmp word ptr DPWD[bx],0
- je open1
- or al,DA_HIDDEN
- open1:
- endif
- not al
- and al,DA_HIDDEN+DA_SYSTEM
- or al,DA_DIR+DA_VOLUME
- test DATTS[bx],al
- jnz open9 ; error if attrib not as requested
- mov ax,fdos_pb+6 ; determine open mode
- if PASSWORD
- sub dx,dx ; assume no PW conflicts
- endif
- test al,DHM_RW+DHM_WO ; test if read/only access
- jz open2
- if PASSWORD ; if write or r/w check writes
- or dx,PWM_W ; check for write password
- endif
- ; mov bx,dirp ; get directory pointer
- test DATTS[bx],DA_RO ; read/only file?
- jz open2 ; no, skip FCB check
- test ax,DHM_FCB ; if FCB open of read-only file
- jz open9 ; allow it, but adjust to read-only
- and al,not DHM_RWMSK ; open mode and proceed
- open2:
- if PASSWORD
- test al,DHM_WO ; will we try to read?
- jnz open3 ; skip if not open for reading
- or dx,PWM_R + PWM_E ; else check for read/exec password
- open3:
- push ax ; save the open mode
- xchg ax,dx ; AX = password modes to check for
- call check_pwd ; check for r/w passwords
- pop ax
- endif
- jmp open_handle ; now allocate file handle
- open8:
- jmp fdos_ED_FILE ; "file not found"
- open9:
- jmp fdos_ED_ACCESS ; return "access denied" error
- eject
- ; CLOSE FILE (CLOSE)
- ; +----+----+----+----+
- ; | 3E | handle |
- ; +----+----+----+----+
- ; entry:
- ; ------
- ; handle: open file handle to be closed
- ; exit:
- ; -----
- ; AX: 3Exx (where xx = # time it was open) or error code ( < 0)
- fdos_close:
- ;----------
- call vfy_dhndl_ptr ; check file handle #
- call redir_dhndl_offer
- call local_disk ; get MXdisk, switch stack
- call check_handle ; check if legal file handle
- mov ax,es:DHNDL_COUNT[bx] ; return # times file WAS open
- mov ah,3Eh ; AH = MS_X_CLOSE
- mov fdos_ret,ax ; return 3Exx if successful
- jc close20 ; skip if character device close
- close_dhndl:
- call release_handle ; release file handle into pool
- callf ss:share_stub+S_CLOSE ; call the fdos stub routine
- dec es:DHNDL_COUNT[bx] ; one less XFN refers to this IFN
- test es:DHNDL_WATTR[bx],DHAT_REMOTE+DHAT_CLEAN
- jnz close10 ; skip update if not dirty local file
- call select_handle ; select the disk
- call file_update ; update directory & FAT if written
- close10:
- ret
- close20: ; handle refers to character device
- jmp close_dev ; close the device handle
- eject
- ; READ FROM FILE (READ)
- ; +----+----+----+----+----+----+----+----+----+----+
- ; | 3F | handle | buffer | count |
- ; +----+----+----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; handle: open file handle
- ; buffer: buffer to read into
- ; count: max. number of bytes to read
- ; exit:
- ; -----
- ; AX: byte count or error code ( < 0)
- fdos_read:
- ;---------
- call vfy_dhndl_ptr ; check file handle #
- test es:DHNDL_MODE[bx],DHM_WO
- jnz rw_ED_ACCESS ; fail if open write only
- call redir_dhndl_offer
- test es:DHNDL_WATTR[bx],DHAT_DEV
- jnz fdos_read_dev ; skip if character device
- call local_disk ; get MXdisk, switch stack
- call verify_handle ; check if legal file handle
- mov cx,fdos_pb+8 ; get requested transfer length
- mov ax,es:DHNDL_POSLO[bx] ; If we get an error we want to have
- mov dx,es:DHNDL_POSHI[bx] ; xfer len adjusted for EOF (CopyIIpc)
- sub ax,es:DHNDL_SIZELO[bx] ; are we beyond EOF ?
- sbb dx,es:DHNDL_SIZEHI[bx]
- ; jb read2 ; beyond EOF already, no action required
- ; ja read2 ; more the 64K to go, no problems
- jnz read2
- cmp ax,cx ; do we want more than there is?
- jae read2 ; yes, shorten the fdos_pb count
- sub fdos_pb+8,ax ; in case of a critical error
- read2:
- mov fdrwflg,1 ; we're reading
- les di,dword ptr fdos_pb+4 ; get disk transfer address
- call fdosrw ; read from file
- xor ax,ax ; return OK
- xchg ax,fdos_ret ; get returned byte count
- mov fdos_pb+8,ax ; return in requested count
- ret
- fdos_read_dev:
- jmp read_dev ; read from character device
- rw_ED_ACCESS:
- mov bx,ED_ACCESS ; return access denied
- ret
- eject
- ; WRITE TO FILE (WRITE)
- ; +----+----+----+----+----+----+----+----+----+----+
- ; | 40 | handle | buffer | count |
- ; +----+----+----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; handle: open file handle
- ; buffer: buffer to be wriiten
- ; count: max. number of bytes to write
- ; exit:
- ; -----
- ; AX: byte count or error code ( < 0)
- fdos_write:
- ;----------
- call vfy_dhndl_ptr ; check file handle #
- test es:DHNDL_MODE[bx],DHM_WO+DHM_RW
- jz rw_ED_ACCESS ; fail if not open in r/w or w mode?
- call redir_dhndl_offer
- test es:DHNDL_WATTR[bx],DHAT_DEV
- jnz fdos_write_dev ; skip if not character device
- call local_disk ; get MXdisk, switch stack
- call verify_handle ; check if legal file handle
- mov fdrwflg,0 ; we're writing
- les di,dword ptr fdos_pb+4 ; get disk transfer address
- mov cx,fdos_pb+8 ; get requested transfer length
- call fdosrw ; write to file file
- xor ax,ax ; return OK
- xchg ax,fdos_ret ; get returned byte count
- mov fdos_pb+8,ax ; return in requested count
- ret
- fdos_write_dev:
- jmp write_dev ; write to character device
- eject
- ; DELETE FILE (UNLINK)
- ; +----+----+----+----+----+----+----+----+----+----+
- ; | 41 | name | ***** | attrib |
- ; +----+----+----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; name: segmented address of ASCIIZ name
- ; attrib: delete mask (FCB only..)
- ; exit:
- ; -----
- ; AX: 0000 or error code ( < 0)
- fdos_unlink:
- ;-----------
- call redir_asciiz_offer
- call local_disk ; get MXdisk, switch stack
- call path_prep ; parse the path, go to bottom level
- call chk_no_dev ; can't be a device
- ; look to see is the call is a remote
- cmp ss:remote_call,0 ; a 21/5D00 one or a local FCB one
- jz unlink1 ; neither, no wild cards allowed
- jns unlink2 ; if it's an FCB call we need to check
- test fdos_pb+8,DA_VOLUME ; for deleting a VOLUME label
- jz unlink2
- call find_labelf ; lets find the volume label
- jz unlink4 ; reporting error if we don't match
- jmp kill_entry ; found it - delete it
- unlink4:
- jmp fdos_ED_FILE ; return "file not found"
- unlink1:
- call chk_no_wild ; make sure not a wild card
- unlink2:
- call setenddir ; search from the start
- ; We now skip any labels/dirs, returning ED_FILE if no other matches
- unlink3:
- call finddfcb ; try to locate directory entry
- jz unlink4 ; returning an error on failure
- test DATTS[bx],DA_DIR+DA_VOLUME
- jnz unlink3 ; make sure it isn't a label/directory
- unlink5:
- ; we have a match, so return ED_ACCESS if we can't find a file we can delete
- call unlink_attribs ; AL = attribs we can't delete
- jz unlink7 ; yes, go for it
- call finddfcb ; look for another entry
- jnz unlink5 ; try this one instead
- jmp fdos_ED_ACCESS ; "access denied" if nothing deleted
- ; since we found at least 1 file
- ; we will delete at least one file, so now we succeed
- unlink6:
- call unlink_attribs ; AL = attribs we can't delete
- jnz unlink8 ; yes, go for it
- unlink7:
- call close_if_same_psp ; make sure not open by any process
- if PASSWORD
- call check_pwd_d ; check for password
- endif
- call kill_file ; delete file
- unlink8:
- call finddfcb ; look for another entry
- jnz unlink6 ; try and delete it if we find one
- jmp update_dir_fat ; write out dirty directories/FAT
- unlink_attribs:
- ; On Entry:
- ; BX -> directory entry
- ; On Exit:
- ; AL = attribute mask which prevents deletion
- ; ZF = 1 if delete OK, ZF = 0 if file should be skipped
- ;
- mov al,byte ptr fdos_pb+8 ; check attributes
- if PASSWORD
- cmp word ptr DPWD[bx],0
- je unlink_attribs10
- or al,DA_HIDDEN
- unlink_attribs10:
- endif
- not al
- and al,DA_HIDDEN+DA_SYSTEM+DA_RO
- or al,DA_DIR+DA_VOLUME
- test DATTS[bx],al ; should we delete this entry ?
- ret
- eject
- ; GET/SET FILE POSITION (LSEEK)
- ; +----+----+----+----+----+----+----+----+----+----+
- ; | 42 | handle | offset ! method |
- ; +----+----+----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; handle: open file handle
- ; offset: long integer offset
- ; method: 0 = begin, 1 = current, 2 = end of file
- ; exit:
- ; -----
- ; AX: 0000 or error code ( < 0)
- ; offset: new offset
- fdos_lseek:
- ;----------
- call vfy_dhndl_ptr ; check file handle #
- call redir_dhndl_offer
- test es:DHNDL_ATTR[bx],DHAT_DEV
- jnz lseek_dev ; skip if character device
- call local_disk ; get MXdisk, switch stack
- call check_handle ; check if legal file handle
- mov ax,fdos_pb+4 ; get 32-bit file offset
- mov dx,fdos_pb+6 ; into AX,DX
- mov cx,fdos_pb+8 ; get seek mode
- jcxz lseek4 ; seek from beginning
- dec cx
- jz lseek2 ; seek from current position
- dec cx
- jz lseek3 ; seek from end
- mov ax,ED_DATA ; else invalid seek mode
- jmp fdos_error ; return error code
- lseek1:
- ret ; return error code
- lseek2: ; seek mode 1: relative to position
- add ax,es:DHNDL_POSLO[bx]
- adc dx,es:DHNDL_POSHI[bx]
- jmps lseek4 ; update new position
- lseek3: ; seek mode 2: relative to end
- add ax,es:DHNDL_SIZELO[bx]
- adc dx,es:DHNDL_SIZEHI[bx] ; add file size + offset
- lseek4: ; seek mode 0: set absolute position
- mov es:DHNDL_POSLO[bx],ax
- mov es:DHNDL_POSHI[bx],dx
- mov fdos_pb+4,ax ; set return values
- mov fdos_pb+6,dx
- ret
- lseek_dev: ; jump here if character device
- mov si,2[bp] ; SI -> parameter block
- xor bx,bx
- mov 4[si],bx ; always return result of 0000h
- mov 6[si],bx
- ret
- eject
- ; GET/SET FILE ATTRIBUTES (CHMOD)
- ; +----+----+----+----+----+----+----+----+----+----+
- ; | 43 | name | flag | attrib |
- ; +----+----+----+----+----+----+----+----+----+----+
- ; | size |
- ; +----+----+----+----+
- ; entry:
- ; ------
- ; name: pointer to ASCIIZ file name
- ; flag: 00 = get attrib/size
- ; 01 = set attrib
- ; attrib: file attribute if flag=1
- ;
- ; exit:
- ; -----
- ; AX: 0000 or error code ( < 0)
- ; attrib: file attribute if flag=0
- ; size: file size if flag=0
- ;
- if PASSWORD
- ; entry:
- ; ------
- ; name: pointer to ASCIIZ file name
- ; flag: 02 = get password mode
- ; 03 = set pw mode/password
- ; 04 = get encrypted password
- ; 05 = set encrypted password
- ; attrib: password mode if flag = 3,5
- ; dma: ascii password if flag = 3
- ; encrypted password if flag = 5
- ;
- ; exit:
- ; -----
- ; AX: 0000 or error code ( < 0)
- ; attrib: file's attribute if flag = 0
- ; password mode if flag = 2
- ; encrypted password if flag = 4
- endif
- if UNDELETE
- ; entry:
- ; ------
- ; name: pointer to ASCIIZ file name
- ; flag: 80 = undelete file
- ; 81 = purge file
- ; dma: result of sucessful search
- ;
- ; exit:
- ; -----
- ; AX: 0000 or error code ( < 0)
- ;
- endif
- fdos_chmod:
- ;----------
- if UNDELETE
- mov si,2[bp] ; SI -> parameter block
- mov al,6[si] ; AX = flag
- sub al,80h ; is it undelete or purge
- jb fdos_chmod_path ; if so set
- cmp al,1
- ja fdos_chmod_path
- call local_disk ; get MXdisk, switch stack
- call select_from_DTA ; prepare for the search
- mov chdblk,0 ; don't assume sequential access
- dec dcnt ; retract so we find the same entry
- call find_pending_delete ; did we find it ?
- jz chmod_notfound ; No, then skip
- call hdsblk ; AX = directory root cluster
- xchg ax,dx ; DX = dir cluster
- mov cx,dcnt ; CX = directory index for entry
- mov ax,fdos_pb+6 ; get operation type
- mov ah,DELW_UNDEL ; assume we are about to undelete
- cmp al,80h ; is it undelete ?
- je fdos_undelete_purge
- mov ah,DELW_PURGE ; no, it must be purge entry
- fdos_undelete_purge:
- mov al,physical_drv ; give delwatch a chance to do it
- callf ss:fdos_stub
- jc fdos_ED_FUNCTION ; return error if DELWATCH not there
- mov fdos_ret,ax ; else return result
- ret
- fdos_chmod_path:
- endif
- call redir_asciiz_offer
- call local_disk ; get MXdisk, switch stack
- call path_prep ; parse the path, go to bottom level
- call chk_no_wild ; can't have wildcards
- call finddfcbf ; find first matching FCB
- jnz chmod10 ; if we can't find a file/dir
- call chk_for_root ; check if we are in the root
- jnz chmod_notfound ; if so return directory attribute
- mov cx,fdos_pb+6 ; but only for get attributes
- jcxz chmod_root ; other fall through to not found
- chmod_notfound:
- jmp fdos_ED_FILE
- chmod_root:
- mov fdos_pb+8,DA_DIR ; return directory attribute
- ret
- fdos_ED_FUNCTION:
- mov ax,ED_FUNCTION ; invalid subfunction
- jmp fdos_error
- chmod10:
- mov bx,dirp ; BX -> matching directory entry
- mov ax,DSIZE[bx]
- mov fdos_pb+10,ax
- mov ax,DSIZE+WORD[bx]
- mov fdos_pb+12,ax
- xor ax,ax
- mov al,DATTS[bx] ; get directory attributes
- mov cx,fdos_pb+6 ; get function #
- jcxz chmod30 ; always allow get attribs
- if PASSWORD
- cmp cl,5 ; validate sub-function number
- ja chmod15
- mov ax,DPWM[bx] ; assume return password mode
- and ax,PWM_ANY ; isolate password mode bits
- cmp cl,2 ; is it get mode ?
- je chmod30 ; yes, just return it
- push ax
- push cx
- call check_pwd_any ; check the password
- pop cx
- pop ax
- mov dx,fdos_pb+8 ; DX = new attributes
- cmp cl,2 ; is it get mode ?
- ja chmod20 ; how about other password functions?
- else
- cmp cl,1 ; validate sub-function number
- ja chmod15
- mov dx,fdos_pb+8 ; DX = new attributes
- endif
- ; Set new file attrib
- ; BX = DIRP
- ; DX = attrib
- ;
- test dl,DA_DIR ; directory bit not allowed
- jnz chmod12
- xor dl,DATTS[bx] ; check which bits are changed
- and dl,not DA_DIR ; don't check or flip directory bit
- test dl,DA_FIXED ; trying to change the unchangeable?
- jz chmod13
- chmod12:
- jmp fdos_ED_ACCESS ; return "access denied"
- chmod13:
- xor DATTS[bx],dl ; set new attributes
- if PASSWORD
- jmps chmod90
- else
- jmp update_dir ; update directory
- endif
- chmod15:
- mov ah,PASSWD_CHMOD ; call out to SECURITY TSR
- callf ss:fdos_stub
- jc fdos_ED_FUNCTION
- jmps chmod90
- if PASSWORD
- chmod20:
- ; Password support for functions 3-5
- ; BX = DIRP
- ; CX = flag
- ; DX = attrib
- ;
- push bx
- push cx
- push dx
- mov di,S_DENY_IF_OPEN ; check if file already open
- call check_with_share ; and stop if it is
- pop dx
- pop cx
- pop bx
- mov ax,DPWD[bx] ; assume get encrypted password
- cmp cl,4 ; was it ?
- jne chmod50
- endif ; yes, return encrypted password
- chmod30:
- mov fdos_pb+8,ax
- ret
- if PASSWORD
- ; Password support for functions 3/5
- ; BX = DIRP
- ; CX = flag
- ; DX = attrib
- ;
- chmod50: ; set password/password mode
- test dh,80h ; assign new password?
- jz chmod70 ; skip if mode change only
- mov di,offset save_area ; ES:DI -> local structure
- push ds
- call lds_si_dmaptr ; DS:SI -> users DMA address
- lodsw ; AX = possible encrypted password
- cmp cl,5 ; was it set encrypted password ?
- je chmod60
- dec si ; no, the DMA buffer contains
- dec si ; an 8 character password so we
- call hash_pwd ; compute password hash code
- chmod60:
- pop ds
- or DATTS[bx],DA_HIDDEN ; file will be hidden
- mov DPWD[bx],ax ; set new file password
- test ax,ax ; null password?
- jnz chmod70
- xor dx,dx ; can't be protected....
- chmod70:
- mov ax,not PWM_ANY ; clear existing file
- and DPWM[bx],ax ; password mode bits
- not ax ; isolate password mode bits
- and dx,ax ; in new password mode
- jz chmod80 ; if no protection, leave them off
- test DATTS[bx],DA_DIR ; directories protected in all modes
- jz chmod80 ; skip if not a directory
- xchg ax,dx ; force all modes on
- chmod80:
- or DPWM[bx],dx ; set password mode bits
- test dx,dx ; test if protection enabled
- jnz chmod90 ; skip if any protection still active
- mov DPWD[bx],dx ; remove the password and hidden bit
- and DATTS[bx],not DA_HIDDEN ; as file is no longer protected
- endif
- chmod90:
- jmp update_dir ; now update the directory
- eject
- ; DUPLICATE FILE HANDLE (DUP)
- ; +----+----+----+----+----+----+
- ; | 45 | handle | newhnd |
- ; +----+----+----+----+----+----+
- ; entry:
- ; ------
- ; handle: open file handle
- ; exit:
- ; -----
- ; newhnd: new file handle
- ; AX: duplicate file handle or error code ( < 0)
- fdos_dup:
- ;--------
- call find_xfn ; find new external file #
- mov si,2[bp] ; SI -> parameter block
- mov ds:4[si],di ; save new handle #
- jnc fdos_fdup ; share the code with DUP2
- mov bx,ED_HANDLE ; can't find a handle
- ret
- eject
- ; FORCE DUPLICATE FILE HANDLE (DUP2)
- ; +----+----+----+----+----+----+
- ; | 46 | handle | newhnd |
- ; +----+----+----+----+----+----+
- ; entry:
- ; ------
- ; handle: open file handle
- ; newhnd: new file handle
- ; exit:
- ; -----
- ; AX: duplicate file handle or error code ( < 0)
- fdos_fdup:
- ;---------
- call vfy_dhndl_ptr ; check file handle #
- call local_disk ; get critical section locks
- call get_xftptr ; ES:DI -> XFN table
- jc dup_err ; we need one..
- mov bx,fdos_pb+4 ; get user file number (0-19)
- cmp bx,cx ; is it sensible ?
- jae dup_err
- cmp es:byte ptr [di+bx],0FFh
- jne dup_err ; handle should be closed by PCMODE..
- call check_handle ; check if legal file handle
- inc es:DHNDL_COUNT[bx] ; another user
- call dup_dev ; inform device driver it's happened
- call get_xftptr ; ES:DI -> XFT's
- mov bx,fdos_pb+2 ; get XFN to dup from
- mov al,es:[di+bx] ; get it's IFN
- mov bx,fdos_pb+4 ; BX = XFN to dup to
- mov es:[di+bx],al ; it gets same IFN
- mov fdos_ret,bx ; return XFN to caller
- ret
- dup_err: ; complain someone stole my handle
- jmp fdos_ED_H_MATCH
- eject
- ; GET CURRENT DIRECTORY
- ;
- ; +----+----+----+----+----+----+----+----+
- ; | 47 | drive | path |
- ; +----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; drive: drive to get path for
- ; path: address of 64 byte path buffer to be
- ; filled in with current path
- ; exit:
- ; -----
- ; BX: 0100 or error code
- fdos_curdir:
- ;-----------
- call local_disk ; it's a disk function
- call get_pb2_drive ; get specified drive in AL
- call get_ldt ; ES:BX -> LDT_ for drive
- jc fdos_curdir30
- mov dx,es:LDT_FLAGS[bx]
- test dx,LFLG_NETWRKD
- jnz fdos_curdir10
- test dx,LFLG_PHYSICAL
- jz fdos_curdir30
- call select_unique ; select the drive for media changes
- les bx,ss:current_ldt ; ES:BX -> LDT_ for this drive
- cmp es:LDT_BLK[bx],0FFFFh ; is LDT valid
- jne fdos_curdir10
- call rebuild_ldt_curdir ; no, better rebuild it
- fdos_curdir10:
- push ds
- push es ! push bx ; save LDT
- les di,dword ptr fdos_pb+4 ; ES:DI -> destination buffer
- pop si ! pop ds ; DS:SI -> LDT
- add si,ds:LDT_ROOTLEN[si] ; skip the '\serverdir'
- lodsb ; eat the slash
- call check_slash ; if it is one..
- je fdos_curdir20
- dec si ; I didn't mean it!
- fdos_curdir20:
- call copy_asciiz ; copy the string
- pop ds
- mov fdos_ret,100h ; return 100h for success
- ret
- fdos_curdir30:
- jmp fdos_ED_DRIVE ; naughty - it's a bad drive
- eject
- ; GET DISK PARAMETER BLOCK
- ; +----+----+----+----+----+----+----+----+----+----+
- ; | 48 | drive | dpb | adjust |
- ; +----+----+----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; drive: drive to get information about
- ; (top bit of word set if free space not required)
- ; exit:
- ; -----
- ; AX: 0000 or error code ( < 0)
- ; dpb: address of DOS DPB (offset/segment)
- ; adjust: delwatch adjustment of free space
- fdos_getdpb:
- ;-----------
- call redir_drv_offer
- call local_disk ; get MXdisk, switch stack
- call get_pb2_drive ; get drive from parameter block
- call logical2physical ; AX = physical drive
- call select_physical_drv
- test fdos_pb+2,8000h ; free space required ?
- jnz fdos_getdpb10
- call update_ddsc_free ; then make sure it is up to date
- if DELWATCH
- xor cx,cx ; assume no adjustment
- mov ah,DELW_SPACE
- mov al,physical_drv ; now we call DELWATCH to
- callf fdos_stub ; add pending deletes
- mov fdos_pb+8,cx ; return free space adjust value
- endif
- fdos_getdpb10:
- les ax,ss:current_ddsc
- mov fdos_pb+4,ax
- mov fdos_pb+6,es
- ret
- eject
- ; FLUSH BUFFERS
- ; +----+----+
- ; | 49 |
- ; +----+----+
- ; entry:
- ; ------
- ; none
- ; exit:
- ; -----
- ; none
- fdos_flush:
- ;----------
- call local_disk ; be alone...
- fdos_flush_local:
- ; Entry point for people who already have the MX disk
- xor dx,dx ; starting with drive A
- fdos_flush10:
- push dx
- call mark_ldt_unsure ; ask for LDT's to be relogged
- xchg ax,dx ; AL = drive to check
- mov ah,BF_DIRTY
- call buffers_check ; any buffers on this drive?
- jz fdos_flush20 ; skip flush if none
- call select_physical_drv ; select drive in AL
- call update_fat ; flush all FAT buffers
- ; call update_dir ; dir always up to date
- call update_dat ; flush all data buffers
- fdos_flush20:
- pop dx
- xchg adrive,dl
- call discard_all ; discard all buffers
- xchg adrive,dl
- inc dx ; onto next drive
- cmp dl,phys_drv
- jb fdos_flush10
- mov al,0FFh ; AL = all drives
- jmp hshdscrd ; forget about our hashing
- ; ret
- eject
- ; SELECT DRIVE
- ; +----+----+----+----+
- ; | 4A | drive |
- ; +----+----+----+----+
- ; entry:
- ; ------
- ; drive: drive (zero based) to select as default drive
- ; exit:
- ; -----
- ; current_dsk: drive (if legal)
- fdos_select:
- ;-----------
- call local_disk ; cheap way to get MX
- mov ax,fdos_pb+WORD ; AL = drive
- call get_ldt ; ES:BX -> LDT for drive A
- mov dx,ax ; DL = logical drive
- jc fdos_select10 ; no LDT, treat as physical=logical
- mov ax,es:LDT_FLAGS[bx] ; get the LDT_FLAGS
- test ax,LFLG_NETWRKD ; NETWORK drives are OK, but we must
- jnz fdos_select20 ; skip physical selection bit
- test ax,LFLG_PHYSICAL
- jz fdos_select30 ; skip physical selection bit
- if JOIN
- test ax,LFLG_JOINED ; JOINed drives are bad news
- jnz fdos_select30 ; so don't select one
- endif
- mov al,es:LDT_NAME[bx] ; get ASCII drive letter
- call toupper ; it was ascii
- sub al,'A' ; make it zero based
- fdos_select10:
- call get_ddsc ; ES:BX -> DDSC_ for drive
- jc fdos_select30 ; no, don't select
- fdos_select20:
- mov ss:current_dsk,dl ; new logical disk selected
- fdos_select30:
- ret
- eject
- ; EXECUTE CHILD (EXEC)
- ; +----+----+----+----+
- ; | 4B | pspseg |
- ; +----+----+----+----+
- ; entry:
- ; ------
- ; pspseg: segment of child PSP
- ; exit:
- ; -----
- ; AX: 0000h
- fdos_exec:
- ;---------
- call local_disk ; get MXdisk, switch stack
- mov cx,fdos_pb+2
- jcxz exec30 ; no duplicate handles if no new PSP
- mov di,offset PSP_XFT
- mov es,cx ; get child PSP
- mov cx,XFNMAX ; get # of handles in child PSP
- mov PSP_XFNMAX,cx
- mov PSP_XFTOFF,di
- mov PSP_XFTSEG,es
- mov al,0FFh ; assume all handles closed
- rep stosb
- xor si,si ; start with XFN 0
- exec10:
- call get_xftptr ; ES:DI -> XFN table
- jc exec30 ; stop if none
- add di,si
- mov al,es:[di] ; get IFN of old handle
- call ifn2dhndl ; ES:BX -> DHNDL_
- jc exec20
- mov cx,es:DHNDL_COUNT[bx] ; skip files that aren't open
- jcxz exec20
- test es:byte ptr DHNDL_WATTR+1[bx],DHAT_LOCAL/100h
- jnz exec20 ; don't inherit private files
- test es:byte ptr DHNDL_MODE+1[bx],DHM_FCB/100h
- jnz exec20 ; don't inherit FCB's
- inc cx
- mov es:DHNDL_COUNT[bx],cx ; increment in-use count
- push ax
- call dup_dev ; inform device driver it's happened
- pop ax
- mov es,fdos_pb+2 ; get child PSP
- mov es:PSP_XFT[si],al ; inherit this IFN
- exec20:
- inc si ; next file handle
- cmp si,XFNMAX
- jb exec10 ; inherit all file handles
- exec30:
- ret
- eject
- ; FIND FIRST FILE
- ; +----+----+----+----+----+----+----+----+----+----+
- ; | 4E | name | ***** | attrib |
- ; +----+----+----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; name: pointer to ASCIIZ file name
- ; attrib: attribute to be used in search
- ; nb. API addition - attrib bit 7 set returns starting cluster
- ;
- ; exit:
- ; -----
- ; AX: 0000 or error code ( < 0)
- ; Note: This call returns matching files in
- ; the current DMA address and also saves
- ; the BDOS state in the there.
- ;
- fdos_first:
- ;----------
- call redir_asciiz_dev_offer ; offer it as a network device
- call asciiz_dev_offer ; offer it as a local device
- call redir_asciiz_file_offer ; offer it as a network file
- call local_disk ; get MXdisk, switch stack
- call path_prep ; parse path, walk down the tree
- call check_device ; if it a device
- jnc fdos_first10
- mov ax,fdos_pb+8 ; get search attribute
- mov attributes,al ; set for attribute match
- mov dcnt,0FFFFh ; search from beginning
- jmps search_next ; find next matching file
- fdos_first10:
- jmp first_dev ; return device name
- next_deverr: ; NEXT after FIRST on device:
- mov bx,ED_FILE ; "no more files"
- ret
- eject
- ; FIND NEXT FILE
- ; +----+----+
- ; | 4F |
- ; +----+----+
- ; entry:
- ; ------
- ;
- ; exit:
- ; -----
- ; AX: 0000 or error code ( < 0)
- ; Note: This call returns matching files in
- ; the current DMA address and also saves
- ; the BDOS state in the there.
- ;
- fdos_next:
- ;---------
- push ds
- call lds_si_dmaptr ; DS:SI -> users DMA address
- lodsw
- xchg ax,dx ; DH = local drive
- pop ds
- cmp dh,0FFh ; check if FIRST was character device
- je next_deverr ; "no more files" if device
- call redir_snext_offer
- call local_disk ; get MXdisk, switch stack
- call select_from_DTA ; prepare for the search
- ; jmp search_next ; now go and look for next file
- search_next:
- ;-----------
- mov chdblk,0 ; don't assume sequential access
- mov al,attributes ; are we looking for a VOL label?
- test al,DA_DIR+DA_SYSTEM+DA_HIDDEN
- jnz search_n10 ; these bits take precedence
- test al,DA_VOLUME ; searching for label?
- jz search_n10 ; search for directory label only
- if UNDELETE
- cmp al,DA_DELWATCH+DA_VOLUME
- jne search_vol ; searching for pending delete entries?
- call find_pending_delete ; did we find it ?
- jz search_next_err ; No, then skip
- jmps search_n30 ; save search state for user
- search_vol:
- endif
- call find_label ; did we find it ?
- jnz search_n30 ; save search state for user
- search_next_err:
- jmp fdos_ED_ROOM ; else end of directory
- search_n10:
- call finddfcb ; find next matching entry
- jz search_next_err ; if not found
- mov al,attributes ; get attributes that we support
- if PASSWORD
- cmp word ptr DPWD[bx],0 ; does it have a password?
- jz search_n20 ; skip if not
- or al,DA_HIDDEN ; else include hidden files
- search_n20:
- endif
- not al ; attributes we don't support
- and al,DA_DIR+DA_HIDDEN+DA_SYSTEM+DA_VOLUME
- test DATTS[bx],al ; any attributes we don't support
- jnz search_n10 ; then don't count this one
- search_n30:
- push ss ! pop es
- mov di,offset srch_buf ; ES:DI -> DMA search address
- push di ; save for later
- if JOIN
- mov al,fdos_hds_drv ; save the PHYSICAL drive
- else
- mov al,byte ptr path_drive ; save the specified drive
- endif
- inc al
- stosb
- mov dx,di ; remember start of name field
- mov si,offset info_fcb+1 ; point at search FCB
- mov cx,11
- rep movsb ; save name for search
- mov al,attributes ; get search attribute
- stosb
- mov ax,dcnt
- stosw ; save directory count
- mov ax,fdos_hds_blk ; get the directory block
- stosw ; save the current block
- add di,4 ; skip 4 reserved bytes
- mov si,dirp ; point to directory name
- test attributes,DA_CLUSTER ; is the caller requesting
- jz search_n35 ; the starting cluster ?
- mov ax,DBLOCK1[si] ; pick it up from dir entry
- dec di ; and return at offset 13h
- dec di ; in DTA (WARNING - Lantastic
- stosw ; server uses these bytes too..)
- search_n35:
- mov cx,32/WORD
- rep movsw ; location (also used by FCB search)
- pop si ; SI = offset srch_buf
- call les_di_dmaptr ; ES:DI -> DMA address
- push ss ! pop ds ; DS:SI -> srch_buf
- mov cx,21
- rep movsb ; copy from buffer to user DMA
- mov bx,dirp ; BX -> matching entry
- mov al,DATTS[bx]
- stosb ; return directory attribute
- lea si,DTIME[bx]
- movsw ! movsw ; return time, date
- inc si
- inc si ; skip starting cluster
- movsw ! movsw ; return file size
- jmp unparse ; return file name
- eject
- ; COMMIT FILE (COMMIT)
- ; +----+----+----+----+
- ; | 50 | handle |
- ; +----+----+----+----+
- ; entry:
- ; ------
- ; handle: open file handle to be flushed
- ; exit:
- ; -----
- ; AX: 0000 or error code ( < 0)
- file_updt20: ; NO-OP for clean files
- commit_dev: ; NO-OP on character devices
- ret
- fdos_commit:
- ;-----------
- call vfy_dhndl_ptr ; check file handle
- call redir_dhndl_offer
- call local_disk ; get MXdisk, switch stack
- call verify_handle ; check if legal file handle
- jc commit_dev
- ; jmp file_update ; update directory & FAT if written
- ; Update directory & File Allocation Table (partial close)
- ; entry: ES:BX -> DHNDL_
- ; exit: ES:BX preserved
- Public file_update
- file_update:
- ;-----------
- test es:DHNDL_ATTR[bx],DHAT_CLEAN
- jnz file_updt20 ; skip if file is clean
- mov al,es:DHNDL_DCNTLO[bx] ; get directory count
- mov ah,es:DHNDL_DCNTHI[bx]
- dec ax
- mov dcnt,ax ; set search position
- xor cx,cx ; find any entry
- mov chdblk,cx ; non-sequential access
- push es ! push bx
- call getdir ; read the directory entry
- pop bx ! pop es
- test ax,ax ; did we find something?
- jz file_updt10 ; skip if directory entry lost
- xchg ax,di ; DI -> directory entry in buffer
- or DATTS[di],DA_ARCHIVE ; mark file as modified
- ;;; call timestamp_dhndl ; record the current time
- mov ax,es:DHNDL_BLK1[bx] ; AX = 1st block in file
- lea di,DTIME[di] ; DI -> [time,date,block1,size]
- push es ! push bx
- push ds
- lea si,DHNDL_TIME[bx]
- push ds ! push es
- pop ds ! pop es ; swap ES and DS
- movsw ! movsw ; copy time then date
- stosw ; now 1st cluster
- movsw ! movsw ; finally file size
- pop ds
- call update_dir ; update directory
- call update_fat ; flush dirty FAT
- call update_dat ; flush all dirty data buffers
- pop bx ! pop es
- or es:DHNDL_ATTR[bx],DHAT_CLEAN
- ret ; only mark as clean AFTER it's written
- file_updt10:
- mov ax,ED_H_MATCH ; can't find open file
- mov fdos_ret,ax ; save error code
- ret
- eject
- ; CREATE NEW FILE
- ; +----+----+----+----+----+----+----+----+
- ; | 51 | name | mode |
- ; +----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; name: segmented address of ASCIIZ name
- ; mode: attribute for file
- ; exit:
- ; -----
- ; AX: file handle or error code ( < 0)
- ; Note: The function is identical to CREATE FILE
- ; with the exception that an error is returned
- ; if the specified file already exists.
- fdos_mknew:
- ;----------
- call redir_asciiz_offer
- call local_disk ; get MXdisk, switch stack
- call mustbe_free_handle ; make sure we have spare handle
- call path_prep_chk ; parse path, walk down the tree
- call finddfcbf ; check if we can find this one
- jnz mknew10
- test byte ptr fdos_pb+8,DA_VOLUME
- jz mknew_nolbl ; skip if not volume label
- call mustbe_nolbl ; do we have an existing label ?
- mknew_nolbl:
- jmp creat_new_file ; go ahead and create the file
- mknew10:
- mov ax,ED_EXISTS
- jmp fdos_error
- eject
- ; LOCK/UNLOCK FILE DATA (LOCK/UNLOCK)
- ; +----+----+----+----+----+----+----+----+
- ; | 52 | handle | offset |
- ; +----+----+----+----+----+----+----+----+
- ; | length | lock |
- ; +----+----+----+----+----+----+
- ; entry:
- ; ------
- ; handle: open file handle
- ; offset: long integer offset
- ; length: long integer byte count
- ; lock: 0 = lock, 1 = unlock
- ; exit:
- ; -----
- ; AX: byte count or error code ( < 0)
- fdos_lock:
- ;---------
- call vfy_dhndl_ptr ; check file handle #
- test es:DHNDL_WATTR[bx],DHAT_DEV
- jnz lock_dev ; skip if character device
- call redir_dhndl_offer
- call local_disk ; get MXdisk, switch stack
- call check_handle ; check if legal file handle
- mov ax,ED_ACCESS ; assume a problem
- jc lock_error ; can't lock/unlock device handles
- mov di,offset fdos_pb
- callf ss:share_stub+S_LOCKS ; call the stub routine
- jnc lock_ret ; return error if we got one
- lock_error:
- jmp fdos_error ; can't do locking
- lock_dev:
- mov bx,ED_ACCESS
- lock_ret:
- ret
- eject
- ; BUILD DDSC FROM BPB
- ; +----+----+----+----+----+----+----+----+----+----+
- ; | 53 | bpbptr ! ddscptr |
- ; +----+----+----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; bpbptr: address of BPB
- ; ddscptr: address of DDSC to be built
- ; exit:
- ; -----
- ; 0000 or error code ( < 0)
- fdos_mkddsc:
- ;-----------
- push ds
- mov si,2[bp] ; SI -> parameter block
- les di,6[si] ; ES:DI -> DDSC
- lds si,2[si] ; DS:SI -> BPB
- call bpb2ddsc ; convert BPB to DDSC
- xor bx,bx ; no error
- pop ds ; restore segment register
- ret
- bpb2ddsc:
- ;--------
- ; build a DDSC from a BPB, leavinf UNIT, RUNIT, DEVICE, FIRST, and LINK fields
- ; unchanged
- ; On Entry:
- ; DS:SI -> source BPB
- ; ES:DI -> destination DDSC
- ; On Exit:
- ; None
- lodsw ; get sector size in bytes
- mov es:DDSC_SECSIZE[di],ax
- lodsb ; get sectors/allocation unit
- dec ax ; get cluster mask
- mov es:DDSC_CLMSK[di],al ; store cluster mask
- lodsw ; get FAT address
- mov es:DDSC_FATADDR[di],ax
- lodsb ; get # of fats
- mov es:DDSC_NFATS[di],al
- cbw ; make it a word value
- xchg ax,dx ; and keep in DX
- lodsw ; get # of directory entries
- mov es:DDSC_DIRENT[di],ax
- lodsw ; get # of sectors total in image
- push ax ; save disk size for later
- lodsb ; get FAT id byte
- mov es:DDSC_MEDIA[di],al ; set media byte
- lodsw ; get # of sectors in a fat
- if DOS5
- mov es:DDSC_NFATRECS[di],ax ; set FAT size
- else
- mov es:DDSC_NFATRECS[di],al ; set FAT size
- endif
- mul dx ; AX = FAT size
- add ax,es:DDSC_FATADDR[di] ; AX = 1st directory sector
- mov es:DDSC_DIRADDR[di],ax ; set root directory address
- add si,word+word+dword ; skip SPT, NHEADS, BIGHIDDEN
- mov cx,es:DDSC_SECSIZE[di]
- mov ax,32 ; size of single directory entry
- mul es:DDSC_DIRENT[di] ; AX/DX = root directory bytes
- add ax,cx ; round up sector size
- dec ax ; in case of odd number
- div cx ; convert to whole sectors
- add ax,es:DDSC_DIRADDR[di] ; add in base of root directory
- mov es:DDSC_DATADDR[di],ax ; set this as first cluster address
- pop ax ; recover total disk size
- xor dx,dx ; assume 16 bit number
- test ax,ax ; test for big drive
- jnz bpb2ddsc10 ; skip if not large drive
- lodsw ; get low word of size
- mov dx,[si] ; get high word of size
- bpb2ddsc10: ; AX/DX = disk size in sectors
- sub ax,es:DDSC_DATADDR[di] ; subtract non-data portion
- sbb dx,0
- xor cx,cx ; CL = cluster shift
- mov ch,es:DDSC_CLMSK[di] ; CH = cluster mask
- bpb2ddsc20: ; count # of 1 bits
- shr ch,1 ; shift right mask
- jnc bpb2ddsc30 ; skip if all 1 bits shifted out
- inc cx ; count another 1 bit
- shr dx,1
- rcr ax,1 ; div by two
- jmps bpb2ddsc20 ; repeat until all 1's counted
- bpb2ddsc30: ; CL = log2 (CH)
- mov es:DDSC_CLSHF[di],cl ; set cluster shift
- inc ax ; clusters 0/1 reserved (+2), and we
- mov es:DDSC_NCLSTRS[di],ax ; want max (-1), so +1
- xor ax,ax
- mov es:DDSC_BLOCK[di],ax ; next block = 0
- dec ax
- mov es:DDSC_FREE[di],ax ; free space = -1 (unknown)
- ret
- eject
- ; DIRECT DISK IO
- ; +----+----+----+----+----+----+
- ; | 54 |drv | op |nsectors |
- ; +----+----+----+----+----+----+----+----+
- ; | startsec | dma address |
- ; +----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; param block set up for direct disk IO
- ; exit:
- ; -----
- ; AX = 0, or error code
- ;
- DIO_25_READ_OP equ 1
- DIO_26_WRITE_OP equ 2
- fdos_ddio:
- ;---------
- ; Used by emulator for Int 25H/26H disk calls to BIOS
- ;
- ; entry: dio = offset of parameter block in user data segment
- ;
- ; exit: AX = return code from BIOS
- call local_disk ; get the MX
- mov ax,fdos_pb+WORD ; AX = logical drive
- call logical2physical ; AX = physical drive
- call get_ddsc ; make sure this drive is valid
- jc fdos_ddio30 ; bail if not
- mov adrive,al ; remember this unit
- mov ax,CMD_INPUT+0*256 ; disk read operation of system area
- cmp byte ptr fdos_pb+3,DIO_26_WRITE_OP
- jne fdos_ddio10
- mov ax,0FFFFh
- mov es:DDSC_FREE[bx],ax ; free space = -1 (unknown)
- call hshdscrd ; discard hashing info for all drives (AL=FF)
- mov ax,CMD_OUTPUT+1*256 ; disk write operation of system area
- fdos_ddio10:
- mov rwmode,ah ; save read/write of system area
- mov req_hdr+5,ah ; (so driver can get the hint)
- mov bx,offset req_hdr ; we will build request here
- mov RH_CMD[bx],al ; save the command
- mov ax,fdos_pb+4 ; AX = # sectors
- mov RH4_COUNT[bx],ax ; set requested sector count
- les ax,dword ptr fdos_pb+6 ; pick up 32-bit record address
- mov word ptr pblock,ax
- mov word ptr pblock+WORD,es
- les ax,dword ptr fdos_pb+10 ; ES:AX -> DMA seg
- mov RH4_BUFOFF[bx],ax
- mov RH4_BUFSEG[bx],es
- call ddioif ; go do it
- jns fdos_ddio20 ; did we have a problem ?
- cbw ; AX = base error
- add ax,ED_PROTECT ; "add" in BIOS error code
- mov fdos_ret,ax ; save return code
- fdos_ddio20:
- ret
- fdos_ddio30:
- jmp fdos_ED_DRIVE ; return bad drive error
- eject
- ; EXPAND FILE NAME
- ; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+
- ; | 55 | relative name | | absolute name |
- ; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; relative name: segmented address of ASCIIZ name
- ; absolute name: segmented address of ASCIIZ name
- ; exit:
- ; -----
- ; AX = BX: 0000 or error code ( < 0)
- fdos_expand:
- ;-----------
- call redir_asciiz_dev_offer ; is it a networked device ?
- call asciiz_dev_offer ; see it we are expanding a device name
- call local_disk ; get MXdisk, switch stack
- push ds
- les si,dword ptr fdos_pb+2 ; get relative name buffer
- mov ax,es:[si] ; get 1st two chars of path
- call check_dslash ; is it a '\' form ?
- je fdos_expand10
- mov bx,ED_FILE
- test al,al
- jz fdos_expand60
- call toupper ; work on premise we have drive
- sub al,'A' ; specified in relative name
- sub ah,':' ; did we have ?
- je fdos_expand20 ; if so use it
- fdos_expand10:
- mov al,current_dsk ; use current drive
- fdos_expand20:
- cmp al,last_drv ; is it a legal drive
- jae fdos_expand50
- ; we should check for a media change so select_logical_drv seems to be
- ; a better solution
- ; call get_ldt ; ES:BX -> LDT_ for drive
- ; jc fdos_expand40 ; no LDT at init - copy relative path
- ; mov word ptr current_ldt,bx
- ; mov word ptr current_ldt+WORD,es
- call select_logical_drv
- les bx,current_ldt
- test es:LDT_FLAGS[bx],LFLG_PHYSICAL
- jz fdos_expand50 ; make sure it's a valid drive
- push ss ! pop es
- mov di,offset pri_pathname ; build name in pathname buffer
- lds si,dword ptr fdos_pb+2
- ; we must trick redir_build_path to find the correct function number -
- ; otherwise we could not get correct (critical) error reporting to work
- push bp
- mov bp,offset fdos_pb+6
- mov 2[bp],bp
- mov byte ptr [bp],FD_EXPAND
- call redir_build_path ; build name from LDT
- pop bp
- jc fdos_expand60 ; bail out if bad name
- lds di,ss:current_ldt ; we need to append a '' if
- mov bx,ds:LDT_ROOTLEN[di] ; we are at the root
- test ds:LDT_FLAGS[di],LFLG_SUBST
- jz fdos_expand30 ; if drive is SUBST'd then
- mov bx,2 ; only append if real root
- fdos_expand30:
- mov si,offset pri_pathname ; SS:SI -> full path
- push ss ! pop ds ; leave current ldt -> buffer as LAN
- mov word ptr current_ldt,si ; MAN 2.1 extended edition expects it
- mov word ptr current_ldt+WORD,ds
- mov ax,'' ; get pathchar in AX for checks
- cmp ds:byte ptr [si+bx],ah ; are we at the root ?
- jne fdos_expand40 ; if so append a ''
- mov ds:word ptr [si+bx],ax
- fdos_expand40:
- les di,ss:dword ptr fdos_pb+10; ES:DI -> destination buffer
- call copy_asciiz ; copy the full pathname
- pop ds
- ret
- fdos_expand50:
- mov bx,ED_DRIVE ; return bad drive error
- fdos_expand60:
- mov ax,bx
- pop ds
- jmp fdos_error
- expand_dev:
- ;----------
- les si,dword ptr fdos_pb+2 ; this is the original source
- lods es:ax ; get the source
- les di,dword ptr fdos_pb+10 ; data will end up here
- cmp ah,':' ; is a drive specified ?
- je expand_dev10
- mov al,'A'
- add al,ss:current_dsk
- expand_dev10:
- call toupper ; make sure drive letter is upper case
- stosb ; plant an 'd'
- mov ax,':'+256*'/'
- stosw ; make that 'd:/'
- mov bx,offset name_buf ; DS:BX -> name buffer
- jmp unparse ; unparse the device name
- eject
- ; RENAME FILE
- ; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+
- ; | 56 | old name | | new name |
- ; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; old name: segmented address of ASCIIZ name
- ; new name: segmented address of ASCIIZ name
- ; exit:
- ; -----
- ; AX: 0000 or error code ( < 0)
- ; Note: R/O files can be renamed.
- ; ---
- fdos_move:
- ;---------
- call redir_move_offer
- call local_disk ; get MXdisk, switch stack
- call path_prep ; parse the path, go to bottom level
- call chk_no_dev
- cmp ss:remote_call,0 ; wildcards allowed if server/FCB
- jnz move10
- call chk_no_wild ; make sure not a wild card
- move10:
- call finddfcbf ; else try to locate directory entry
- jz fdos_ED_FILE ; error if no match occurred
- move20:
- call close_if_same_psp ; make sure not open by other PDs
- if PASSWORD
- call check_pwd_any ; check if password protected
- endif
- mov si,dirp ; get matching directory entry
- mov di,offset save_area ; get a temporary save area
- mov cx,32/WORD ; save it all
- rep movsw ; so we can move it to new entry
- mov si,offset fdos_hds
- mov di,offset saved_hds
- mov cl,HDS_LEN
- rep movsb ; copy current HDS to safe place
- mov ax,dcnt ; also save directory index
- mov saved_dcnt,ax ; so we can release entry later
- les di,dword ptr fdos_pb+10 ; es:di -> path name
- call path_prep_ptr ; find the destination path
- call chk_no_dev ; no devices allowed here
- cmp ss:remote_call,0 ; wildcards allowed if server/FCB
- jnz move25
- call chk_no_wild ; make sure not a wild card
- move25:
- mov al,fdos_hds_drv ; get the work drive
- cmp al,saved_hds_drv ; make sure same drive for
- je move30 ; source and destination
- mov ax,ED_DEVICE ; "not same device" error
- jmps fdos_moverr ; return the error
- fdos_ED_FILE:
- mov ax,ED_FILE ; get error code
- fdos_moverr:
- jmp fdos_error ; return the error
- move30: ; same drive for source & destination
- mov al,byte ptr fdos_pb+8 ; check attributes
- if PASSWORD
- cmp save_area+DPWD,0
- je move31
- or al,DA_HIDDEN
- move31:
- endif
- not al
- and al,DA_HIDDEN+DA_SYSTEM+DA_DIR+DA_VOLUME
- test save_area+DATTS,al
- jnz move80
- mov si,offset info_fcb+1 ; SI->new name (possible wildcards)
- mov di,si ; DI->new name
- mov bx,offset save_area ; current name on disk
- cmp byte ptr DNAME[bx],'.'
- je move80
- mov cx,11
- move40: ; fill in the wild card characters
- lodsb ; get next character from new name
- if KANJI
- call dbcs_lead ; is it the 1st of a kanji pair
- jne move45
- dec cx ; copied this one
- jcxz move55 ; discard if no room for kanji char
- stosb ; copy 1st byte of Kanji pair
- inc bx
- lodsb ; copy 2nd byte
- jmps move50
- move45:
- endif
- call toupper ; make it upper case
- cmp al,'?' ; is it just a wild card?
- jne move50 ; no, put in destination as is
- mov al,[bx] ; else leave original character
- move50: ; AL = next char for destination
- stosb ; store next char in destination
- inc bx ; increment all pointers
- loop move40 ; repeat for all 11 characters
- move55:
- call finddfcbf ; find first non-volume entry
- jnz move_access ; file already exists, return error
- call move_comp ; source & destination in same dir?
- jne move60 ; skip if moving to different directory
- call move_seek ; else find old entry again
- jmps move70 ; replace name in old entry
- move60: ; moving to different directory
- test save_area+DATTS,DA_DIR ; can't move directory to new path
- jnz move_access ; so return error if new path
- call allocdir ; allocate a directory entry
- move70:
- mov si,offset info_fcb+1 ; get pointer to new name
- mov di,dirp ; get pointer to directory entry
- mov cx,11 ; copy new name into buffer
- rep movsb
- mov si,offset save_area+11 ; copy remaining info
- mov cx,32-11
- rep movsb
- call update_dir ; update the disk
- call move_comp ; did we rename across directories?
- je move80 ; skip if in same directory
- mov si,offset saved_hds
- mov di,offset fdos_hds ; else need to copy HDS back
- mov cx,HDS_LEN ; so we can get old entry again
- rep movsb ; (time to get rid of it)
- call move_seek ; seek the original entry
- mov bx,dirp
- mov DNAME[bx],0E5h ; and bye, bye! it goes...
- call update_dir ; update the old directory entry
- move80:
- cmp ss:remote_call,0 ; wildcards allowed if server/FCB
- jz move90 ; so check for multiple files
- call path_prep ; parse the path, go to bottom level
- mov ax,saved_dcnt ; restore dcnt for remote call
- mov dcnt,ax ; to function properly
- and chdblk,0
- call finddfcb ; try to locate another directory entry
- jz move90 ; no, return now
- jmp move20 ; round again if we do
- move_access:
- jmp fdos_ED_ACCESS ; "access denied" if file
- ; already exists
- move90:
- ; in order to update the current directory in case part of it has been
- ; renamed we call fdos_chdir which does all the work for rebuilding
- ; the LDT_ for the given drive
- push ss
- pop ds
- mov bx,offset sec_pathname
- mov ax,path_drive
- add ax,'A'+(':'*100h)
- mov [bx],ax
- mov word ptr 2[bx],'.'
- mov fdos_pb+4,ds
- mov fdos_pb+2,bx
- mov byte ptr remote_call,0
- jmp fdos_move_chdir
- move_seek: ; re-seek the old directory entry
- mov ax,saved_dcnt ; get saved directory count
- dec ax ; move back one for GETDIR
- mov dcnt,ax ; set search offset
- and chdblk,0 ; follow the chains, not sequential
- mov cl,0 ; return next entry
- jmp getdir ; in current directory
- move_comp:
- mov ax,fdos_hds_blk
- cmp ax,saved_hds_blk
- ret
- eject
- ; GET/SET FILE DATE/TIME
- ; +----+----+----+----+----+----+----+----+----+----+
- ; | 57 | handle | mode | date | time |
- ; +----+----+----+----+----+----+----+----+----+----+
- ; entry:
- ; ------
- ; handle: open file handle
- ; mode: 0 = get date/time, 1 = set date/time
- ; date: date as in directory FCB
- ; time: time as in directory FCB
- ; exit:
- ; -----
- ; AX: 0000 or error code ( < 0)
- ; date: date of last modification if mode = 0
- ; time: date of last modification if mode = 0
- fdos_dattim:
- ;-----------
- call vfy_dhndl_ptr ; check file handle #
- call redir_dhndl_offer
- call local_disk ; get MXdisk, switch stack
- call check_handle ; check if legal file handle
- cmp fdos_pb+4,0 ; get/set date/time?
- jne dattim1
- mov ax,es:DHNDL_DATE[bx] ; get date
- mov fdos_pb+6,ax
- mov ax,es:DHNDL_TIME[bx] ; get time
- mov fdos_pb+8,ax
- ret
- dattim1: ; else set date/time stamp
- mov dx,fdos_pb+6 ; set date
- mov ax,fdos_pb+8 ; and time
- jmps set_timestamp
- Public timestamp_dhndl
- timestamp_dhndl:
- ;---------------
- ; On Entry:
- ; ES:BX -> DHNDL_
- ; On Exit:
- ; ES:BX preserved
- ;
- ; Mark this DHNDL_ with the current time and date
- push es
- push bx
- call ReadTOD ; get TOD in DX/AX
- pop bx
- pop es
- ; jmp set_timestamp
- set_timestamp:
- ;-------------
- ; On Entry:
- ; ES:BX -> DHNDL_
- ; AX = time
- ; DX = date
- ; On Exit:
- ; None
- ;
- and es:DHNDL_ATTR[bx],not DHAT_CLEAN
- mov es:DHNDL_DATE[bx],dx ; remember to update directory
- mov es:DHNDL_TIME[bx],ax ; ask SHARE to record the changes
- callf share_stub+S_RECORD ; for the benefit of others
- ret
- fdos_reopen_fcb:
- ;---------------
- ; On entry
- ; On exit on success pb offset 6 set to 0 if device, 1 if disk file
- test byte ptr remote_call+1,DHM_FCB/100h
- jnz fcb_reopen0
- mov ax,ED_FUNCTION
- jmp fdos_error
- fcb_reopen0:
- call local_disk
- call path_prep
- jc fcb_reopen_error ; any error means reopen is invalid
- call check_device
- jnc fcb_reopen_error ; we should not find devices here
- mov ax,fdos_pb+6
- mov fdos_hds_blk,ax
- mov ax,fdos_pb+8
- dec ax
- mov dcnt,ax
- xor cx,cx
- mov chdblk,cx
- call getdir
- jz fcb_reopen_error
- cmp DNAME[bx],0e5h ; has the entry been deleted ?
- je fcb_reopen_error
- mov fdos_pb+2,ax
- ret
- fcb_reopen_error:
- mov ax,ED_NOFCBS
- jmp fdos_error