; ATTR.ASM -- File Attribute Utility ; ================================== CSEG Segment Assume CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG Org 0080h Parameter Label Byte ; Parameter is here Org 0100h Entry: Jmp Begin ; Entry Point ; Most Data (some more at end of program) ; --------------------------------------- db "ATTR (C) 1986, Ziff-Davis Publishing Co.",1Ah db " Programmed by Charles Petzold ",1Ah SyntaxMsg db "Syntax: ATTR [+A|-A] [+S|-S] [+H|-H] [+R|-R] " db "[drive:][path]filename",13,10 db " Archive System Hidden Read-Only$" DosVersMsg db "ATTR: Needs DOS 2.0 +$" FlagErrMsg db "ATTR: Incorrect flag$" FileSpecMsg db "ATTR: Incorrect File Spec$" Delimiters db 9,' ,;=',13 FlagList db "ASHR", 20h, 04h, 02h, 01h AllFlagList db " $Arc $Dir $$$$$$Sys $Hid $R-O$" ChangeFlag db 0 AndAttrBits db 0 OrAttrBits db 0 SearchString dw ? AppendFileName dw ? ; Check DOS Version ; ----------------- Begin: Mov AH, 30h ; Check for DOS Version Int 21h ; through DOS call Cmp AL, 2 ; See if it's 2.0 or above Jae DosVersOK ; If so, continue Mov DX, Offset DosVersMsg ; Error message ErrorExit: Mov AH, 9 ; Print String function call Int 21h ; Do it Int 20h ; And exit prematurely ; Parse Command Line to get file specification ; -------------------------------------------- DosVersOK: Mov SI, 1+Offset Parameter ; Parameter string pointer Cld ; Directions forward FlagSearch: Lodsb ; Get Byte Mov DI, Offset Delimiters ; Check if delimiter Mov CX, 5 ; Five delimiters to check Repne Scasb ; Scan the string Je FlagSearch ; If delimiter, circle back Mov DX, Offset SyntaxMsg ; Possible error msg Cmp AL, 13 ; If carriage return, no file Je ErrorExit ; so exit with message Mov DI, Offset OrAttrBits ; Pointer to plus flag saver Cmp AL, '+' ; See if plus sign Je PlusOrMinus ; If so, save the bit Mov DI, Offset AndAttrBits ; Pointer to minus flag saver Cmp AL, '-' ; See if minus sign Jne MustBeFile ; If not, it must be file name PlusOrMinus: Mov [ChangeFlag],-1 ; Set for changing Lodsb ; Get the next byte And AL, 0DFh ; Capitalize it Mov BX, Offset FlagList ; List for scanning Mov CX, 4 ; Scan for A, S, H, and R SearchList: Cmp AL, [BX] ; See if a match Jz FoundFlag ; If so, proceed to save Inc BX ; Kick up pointer Loop SearchList ; And loop around for next Mov DX, Offset FlagErrMsg ; Otherwise, set message Jmp ErrorExit ; And terminate FoundFlag: Mov AL, [BX + 4] ; Get bit mask Or [DI], AL ; Turn saved bit on Jmp FlagSearch ; And continue looking MustBeFile: Not [AndAttrBits] ; Invert bits for turn off Mov [SearchString], SI ; Save file name pointer Dec [SearchString] ; Actually one byte lower EndSearch: Lodsb ; Get Byte Mov DI, Offset Delimiters ; Check if delimiter Mov CX, 6 ; Six delimiters including CR Repne Scasb ; Scan the string Jne EndSearch ; If not delimiter, keep going ; Transfer Search String down at end of program ; --------------------------------------------- Dec SI ; Points after file spec Mov Byte Ptr [SI], 0 ; Make it ASCIIZ string Mov CX, SI ; CX points to end Mov SI, [SearchString] ; SI points to beginning Sub CX, SI ; Now CX is length of it Mov DI, Offset PathAndFile ; Destination of string Mov [AppendFileName], DI ; Save it here also SearchTrans: Lodsb ; Get byte of search string Stosb ; And save it down below Cmp AL, ':' ; See if drive marker Je PossibleEnd ; If so, take note of it Cmp AL, '\' ; See if path separator Jne NextCharacter ; If not, skip next code PossibleEnd: Mov [AppendFileName], DI ; This is the new end NextCharacter: Loop SearchTrans ; Do it again until done ; Find Files from Search String ; ----------------------------- Mov DX, Offset DTABuffer ; Set File Find buffer Mov AH, 1Ah ; by calling DOS Int 21h Mov DX, [SearchString] ; Search string Mov CX, 16h ; Search Everything Mov AH, 4Eh ; Find first file FindFile: Int 21h ; Call DOS to find file Jnc Continue ; If no error continue Cmp AX, 18 ; If not "no more files" error Jnz FindError ; print error message Jmp NoMoreFiles ; Now get out of the loop FindError: Mov DX, Offset FileSpecMsg ; Error message for file spec Jmp ErrorExit ; Exit and print message Continue: Mov SI, 30+Offset DTABuffer ; Points to filename Cmp Byte Ptr [SI], '.' ; See if "dot" entry Jnz FileIsOK ; If not, continue Jmp FindNextFile ; If so, skip it FileIsOK: Mov DI, [AppendFileName] ; Destination of file name Mov CX, 14 ; Number of bytes to display TransferName: Lodsb ; Get the byte in file name Stosb ; Save it Or AL, AL ; See if terminating zero Jz PadWithBlanks ; If so, display blanks Call DisplayChar ; Display the character Loop TransferName ; And loop back around PadWithBlanks: Mov AL, ' ' ; Pad names with blanks Call DisplayChar Loop PadWithBlanks ; And loop until CX is zero ; Change And Display File Attributes ; ---------------------------------- Mov DX, Offset PathAndFile ; Points to ASCIIZ string Test [ChangeFlag], -1 ; See if changing attributes Jz DisplayIt ; If not, just display them Mov AX, 4300h ; Get file attribute Int 21h ; by calling DOS And CL, 27h ; Zero out some bits And CL, [AndAttrBits] ; Turn off some bits Or CL, [OrAttrBits] ; Turn on some bits Mov AX, 4301h ; Set file attribute Int 21h ; by calling DOS DisplayIt: Mov AX, 4300h ; Get file attribute Int 21h ; by calling DOS Mov BL, CL ; BL is attributes Or BL, 08h ; Turn on Volume bit Shl BL, 1 ; Shift to get rid of Shl BL, 1 ; unused bits Mov CX, 6 ; Number of bits left Mov DX, 5+Offset AllFlagList; Storage of abbreviations AttrListLoop: Push DX ; Save abbreviation pointer Shl BL, 1 ; Shift bit into carry Jc FlagIsOn ; See if it's on Mov DX, Offset AllFlagList ; If not, print blanks FlagIsOn: Mov AH, 9 ; Print string Int 21h ; by calling DOS Pop DX ; Get back abbreviation ptr Add DX, 5 ; Kick up for next bit Loop AttrListLoop ; And loop around Mov AL, 13 ; Print carriage return Call DisplayChar Mov AL, 10 ; Print line feed Call DisplayChar FindNextFile: Mov AH, 4Fh ; Find next file Jmp FindFile ; By looping around NoMoreFiles: Int 20h ; Terminate ; SUBROUTINE: Display Character in AL ; ----------------------------------- DisplayChar: Push AX Push DX Mov DL, AL ; Move character to DL Mov AH, 2 ; Display it Int 21h ; by calling DOS Pop DX Pop AX Ret ; Some data stored at end to cut down COM size ; -------------------------------------------- DTABuffer Label Byte ; For file find calls PathAndFile equ DTABuffer + 43 ; For file path and name CSEG EndS ; End of the segment End Entry ; Denotes entry point