        SUBT    > <wini>arm.FileSwitch.FSUtils2 - Delete

 [ haswipe
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;                      W i l d c a r d   D e l e t i o n
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; WipeEntry
; =========

; In    r1 -> path to delete
;       r3 = bitset for delete
;       r4,r5 = optional time (start)
;       r6,r7 = optional time (end)

WipeEntry NewSwiEntry "r0-r10",utils    ; WipeWildObject may destroy all regs
                                        ; Extra large frame for utils

 [ debugwipe
 DLINE "FSControl_Wipe: options '",cc
 TST r3, #util_confirm
 SWINE XOS_WriteI+"C"
 TST r3, #util_force
 SWINE XOS_WriteI+"F"
 TST r3, #util_recurse
 SWINE XOS_WriteI+"R"
 TST r3, #util_verbose
 SWINE XOS_WriteI+"V"
 DREG r3,"' "
 ]
        BL      Util_CommonStart
        BVS     %FA99 ; SwiExit - Nothing allocated

        BL      WipeWildObject

        BL      Util_FreeFileStrings_R7 ; Catch errors from these on SwiExit
                                        ; 'Cos it's nice to print ...
        BL      SFreePassedFilenameAndSpecial ; Ditto

        LDR     r14, globalerror        ; Give 'Not found' if no error below
        CMP     r14, #0                 ; fp is valid, of course ...
        LDREQ   r14, util_ndir          ; and no dirs or files deleted
        CMPEQ   r14, #0
        LDR     r0, util_nfiles         ; r0 useful for below - load always !
        CMPEQ   r0, #0
        LDREQ   r14, util_nskipped      ; Only give error if complete wally
        CMPEQ   r14, #0
        BEQ     %FA98

        LDR     r14, util_bitset
        TST     r14, #util_verbose
        ADR     r1, fsw_space_deleted_nl
        BLNE    Util_FilesDone          ; Say '20 files deleted'

90      BLVS    CopyError

99      SwiExit


98      addr    r0, ErrorBlock_NothingToDelete
        SETV
        B       %BT90


fsw_space_deleted_nl      DCB   " deleted", LF,CR, 0
                          ALIGN

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; WipeWildObject
; ==============

; src *: WipeObject on all that match
; src -: WipeObject given name

; Out   Only r7, wp preserved

WipeWildObject ENTRY

 [ debugwipe
 DLINE "WipeWildObject"
 ]
        LDR     r1, [r7, #copy_leafname] ; If not wild, do single deletion
        BL      Util_CheckWildName
        BNE     %FT90                   ; Single deletion

; ...................... Wild object spec for delete ..........................

        MOV     r9, r1                  ; Remember current leafname

        MOV     r14, #0                 
        STR     r14, util_direntry      ; Start at the beginning of dir
        STR     r14, [r7, #copy_leafname] ; 'Free' leafname !

10 ; Loop over names, match against wildcard. Leafname NewString'ed each time
   ; round loop; fullname explicitly made and freed

        BL      STestEscape             ; Util grade, not copied
        BLVS    CopyError
        BLVC    Util_ReadDirEntry       ; Get a name. Uses + updates util_diren
        BVS     %FT60                   ; Put old leafname back, exit

        CMP     r3, #0                  ; No name xferred ?
        BEQ     %FT60                   ; Means eod

        ADR     r4, util_objectname     ; What we read just now
        STR     r4, [r7, #copy_leafname] ; Use as source leafname if matches
        BL      Util_TryMatch
        BNE     %BT10                   ; Loop - try another name

        MOV     r0, r7                  ; Create fullname of each object
        BL      Util_AppendLeafToDir    ; that matched wildcard
        BVS     %FT60                   ; Put old leafname back, exit

        Push    r9                      ; Preserve wild pattern round call
        BL      WipeObject
        Pull    r9

        LDR     r2, [r7, #copy_name]    ; Deallocate new fullname always
        BL      SFreeArea               ; Accumulate V from Wipe/Free
        BVC     %BT10                   ; Loop - try another name
   
60      STR     r9, [r7, #copy_leafname] ; Put old leafname back
        EXIT


; .......... Single object deletion. Must read object info ourselves ..........

; NB. Don't call WipeObject - if deleting dir, just recurse one level unless
; punter wants more than that

90      MOV     r0, r7                  ; Create fullname of object
        BL      Util_AppendLeafToDir    ; from existing (non-wild) leafname
        EXIT    VS

        BL      Util_SingleObjectSetup  ; Error if not found
        BVS     %FT95                   ; Deallocate error
        BHI     %FT96                   ; Is it a dir ?
        BLEQ    WipeFile                ; If it's a file

95      LDR     r2, [r7, #copy_name]    ; Deallocate fullname
        BL      SFreeArea               ; Accumulate V from Wipe/Free
        EXIT


96      BL      WipeDirectory
        B       %BT95

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; WipeObject
; ==========
;
; Delete object, recursing as necessary/required
; Dirname set up for this level
; Leafname already set up after possible wildcard match
; Fullname = dirname + leafname set up

; In    r7 = source file desc^

; Out   r0-r5 corrupted by calls
;       VC: object deleted, skipped by user, date, or dir & ~recurse
;       VS: failed in deletion, or aborted

WipeObject ENTRY

 [ debugwipe
 DLINE "WipeObject"
 ]
        LDR     r14, util_objecttype    ; What is it ?
        TEQ     r14, #object_directory
        BEQ     %FT50

; Wipe existing file

        BL      WipeFile
        EXIT


50 ; It's a directory. Are we recursing ?

        LDR     r14, util_bitset        ; Recurse set ?
        TST     r14, #util_recurse
        BEQ     %FT70                   ; [no - remember r14 ok]

; Wipe this dir, recursing

        BL      WipeDirectory           ; dir & recurse
        EXIT


70      TST     r14, #util_verbose      ; dir & ~recurse. No need to INC skippd
        EXIT    EQ

        MOV     r0, r7                  ; src
        BL      Util_PrintName
        addr    r0, fsw_space_is_a_dir, VC
        SWIVC   XOS_Write0
        BLVS    CopyError
        EXIT

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; WipeFile
; ========
;
; Wipe single file (which exists)
; Fullname set up in desc^.name; info read

; In    r7 = file desc^, file exists

; Out   r0, r5 corrupt
;       VC: file deleted, or skipped
;       VS: failed to delete file, or aborted

WipeFile ENTRY

 [ debugwipe
 DLINE "WipeFile"
 ]
        LDR     r14, util_attr          ; If locked & ~force, don't present
        TST     r14, #locked_attribute  ; for deletion
        BEQ     %FT10
        LDR     r14, util_bitset
        TST     r14, #util_force
        BEQ     %FT90                   ; Tell punter we're ignoring it

10      BL      WipeFile_Confirm        ; Ask the punter
        EXIT    VS
        BLNE    Util_IncrementSkipped
        EXIT    NE                      ; Don't delete this file

        LDR     r5, util_attr
        TST     r5, #locked_attribute   ; Is it locked ?
        MOVNE   r5, #0                  ; Take out all attributes, esp L
        MOVNE   r0, #fsfile_WriteAttr   ; attr := r5
        BLNE    CallFSFile_Given_R7     ; Only if neccessary

50      MOVVC   r0, #fsfile_Delete
        BLVC    CallFSFile_Given_R7

        BLVC    Util_DecrementDirEntry  ; Must go back one in the dir, 'cos
                                        ; we've just deleted the one we read

        BLVC    WipeFile_Verbose        ; Tell them copy action is complete
        EXIT

90      BL      Util_IncrementSkipped
        BL      WipeFile_VerboseLocked  ; locked & ~force
        EXIT

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; WipeDirectory
; =============

; Wipe whole directory contents then delete the directory itself
; Fullname of dir set up in desc^.name; info read

; In    r7 = dir desc^, directory exists

; Out   r0-r5 corrupt
;       VC: directory deleted, or skipped
;       VS: failed to delete directory, or aborted

WipeDirectory ENTRY

 [ debugwipe
 DLINE "WipeDirectory"
 ]
        BL      WipeDirectory_ConfirmAll
        EXIT    VS
        BLNE    Util_IncrementSkipped
        EXIT    NE

; Delete contents of dir, saving quite a bit of info on stack

        LDR     r0, [r7, #copy_dirprefix] ; Push names
        LDR     r1, [r7, #copy_leafname]
        LDR     r2, [r7, #copy_name]
        LDR     r3, util_direntry       ; Push position in dir
        LDR     r4, util_bitset         ; Push flags
        LDR     r5, util_attr           ; Push locked state
        LDR     r14, util_nskipped
        Push    "r0-r5, r14"

        LDR     r14, [r7, #copy_name]   ; Use fullname as dirprefix
        STR     r14, [r7, #copy_dirprefix]
        addr    r14, fsw_wildstar       ; Leafname := '*'
        STR     r14, [r7, #copy_leafname]
        MOV     r14, #0
        STR     r14, util_nskipped      ; Nothing skipped at this level

        BL      WipeWildObject

        Pull    "r0-r5, r14"            ; Restore names, locked state (to r5)
        STR     r0, [r7, #copy_dirprefix]
        STR     r1, [r7, #copy_leafname]
        STR     r2, [r7, #copy_name]
        STR     r3, util_direntry
        STR     r4, util_bitset

        LDR     r0, util_nskipped
        STR     r14, util_nskipped
        EXIT    VS

; Contents deleted, shall we now delete the dir itself ?

        LDR     r1, [r7, #copy_name]
        BL      Util_SpecialDir
        EXIT    EQ                      ; VClear. Don't try to delete $ etc

        TST     r5, #locked_attribute   ; If locked & ~force, don't present
        BEQ     %FT70                   ; for deletion
        LDR     r14, util_bitset
        TST     r14, #util_force
        BEQ     %FT90

70      CMP     r0, #0                  ; Did we skip any in there ? VClear
        BLEQ    WipeDirectory_ConfirmDir ; Mustn't try to delete (not empty)
        EXIT    VS                      ; And note that we've had to skip at
        BLNE    Util_IncrementSkipped   ; this level too !
        EXIT    NE

        TST     r5, #locked_attribute   ; Is it locked ?
        MOVNE   r5, #0                  ; Take out all attributes, esp L
        MOVNE   r0, #fsfile_WriteAttr
        BLNE    CallFSFile_Given_R7     ; Only if neccessary

        MOVVC   r0, #fsfile_Delete
        BLVC    CallFSFile_Given_R7

        BLVC    Util_DecrementDirEntry  ; Must go back one in the dir, 'cos
                                        ; we've just deleted the one we read

        BLVC    WipeDirectory_Verbose   ; Tell them delete dir complete
        EXIT

90      BL      Util_IncrementSkipped
        CMP     r0, #0                  ; Did we skip any in there ? VClear
                                        ; Don't give 'xxx is locked' if so
        BLEQ    WipeFile_VerboseLocked  ; locked & ~force
        EXIT

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; WipeFile_Confirm
; ================

; If dates allow deletion, maybe ask punter if he wants to do it

; Out   VS: error
;       VC, EQ -> do it
;       VC, NE -> don't do it

WipeFile_Confirm ENTRY "r0, r1"

        BL      Util_DateRange          ; See if dates allow it
        EXIT    NE

        addr    r0, fsw_file_space

10      LDR     r14, util_bitset        ; Entered from below
        TST     r14, #util_confirm
        EXIT    EQ

        SWI     XOS_WriteS
        DCB     "Delete ", 0
        ALIGN
        SWIVC   XOS_Write0              ; Second string
        MOVVC   r0, r7                  ; src
        BLVC    Util_PrintName

        BLVC    Util_GetConfirm
        BLVS    CopyError
        EXIT

; .............................................................................
;
; WipeDirectory_ConfirmAll
; ========================

; Out   VS: error
;       VC, EQ -> do it
;       VC, NE -> don't do it

WipeDirectory_ConfirmAll ALTENTRY

        ADR     r0, fsw_contents_of_dir_space
        B       %BT10

; .............................................................................
;
; WipeDirectory_ConfirmDir
; ========================

; Out   VS: error
;       VC, EQ -> do it
;       VC, NE -> don't do it

WipeDirectory_ConfirmDir ALTENTRY

        addr    r0, fsw_directory_space
        B       %BT10


fsw_contents_of_dir_space DCB   "contents of directory ", 0
fsw_space_is_locked_nl    DCB   " is locked", LF,CR, 0

        ALIGN

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; WipeFile_Verbose
; ================

; Deleted the file, so print copied info if being verbose. nfiles++

; Out   VS: error

WipeFile_Verbose ENTRY "r0"

        BL      Util_IncrementFiles_TestVerbose
        EXIT    EQ                      ; EQ -> ~verbose

        addr    r0, fsw_File_space      ; 'File '


50      SWI     XOS_Write0              ; Entered from below
        MOVVC   r0, r7                  ; object_name
        BLVC    Util_PrintName
        addr    r0, fsw_space_deleted_nl, VC ; ' deleted'
        SWIVC   XOS_Write0

        BLVS    CopyError
        EXIT

; .............................................................................
;
; WipeDirectory_Verbose
; =====================

; Deleted the directory, so print info if being verbose

; Out   VS: error

WipeDirectory_Verbose ALTENTRY

        BL      Util_IncrementDir_TestVerbose
        EXIT    EQ                      ; EQ -> ~verbose

        addr    r0, fsw_Directory_space ; 'Directory '
        B       %BT50

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; WipeFile_VerboseLocked
; ======================

; Didn't delete object because it's locked & ~force

; Out   VS: error

WipeFile_VerboseLocked ENTRY "r0"

        LDR     r14, util_bitset
        TST     r14, #util_verbose
        EXIT    EQ

        MOV     r0, r7                  ; src
        BLVC    Util_PrintName
        addr    r0, fsw_space_is_locked_nl, VC ; ' is locked'
        SWIVC   XOS_Write0

        BLVS    CopyError
        EXIT
 ] ; haswipe

        LNK     $fileprefix.FSUtils3
