home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / dirutl / attribcr.arc / ATTRIBCR.ASM next >
Encoding:
Assembly Source File  |  1986-02-22  |  15.4 KB  |  533 lines

  1.     PAGE    62,132
  2.     TITLE    ATTRIB - a program to alter file attributes
  3.     NAME    ATTRIB
  4. ; attrib.asm  3 Feb 86  Craig Milo Rogers at USC/ISI
  5. ;    I received this program from net.sources in response to an
  6. ; inquiry I sent to Info-IBMPC.  Unfortunately, the program fell
  7. ; short of my goals:  it didn't support the Archive bit.  However,
  8. ; the program was nicely structured and readily extended.
  9. ;
  10. ;    I also made a couple of other minor changes.  I changed the
  11. ; command parser to make '.*' the default when the file name extension
  12. ; is not specified.  I changed the command parser to accept ";" as a
  13. ; delimiter.  I changed the command parser to accept multiple
  14. ; attributes.  In the case of incompatible attributes the last one
  15. ; wins.
  16. ;
  17. ;    The user should be aware that there are some other
  18. ; differences between this program and the DOS 3.10 ATTRIB command.
  19. ; The DOS ATTRIB command lists the entire drive and path when
  20. ; listing files, while this program lists only as much of the
  21. ; path as the user specified.
  22. ;
  23. ; This program was written by Bob Eager, Herne Bay, England.
  24. ; It is placed in the public domain. No part of this program
  25. ; may be copied and sold for gain.
  26. ;
  27. ; There isn't really much in the way of documentation. ATTRIB
  28. ; works like the DOS 3 command of the same name (except that it
  29. ; is a lot smaller and also DOES a lot MORE!)
  30. ;
  31. ; For those unfamiliar with that:
  32. ;    ATTRIB filename     -   reports file attributes as single letters
  33. ;                            (H, S, R, A)
  34. ;    ATTRIB +x filename  -   sets the x attribute (H, S, R or A)
  35. ;    ATTRIB -x filename  -   unsets the x attribute (H, S, R ar A)
  36. ;
  37. ;  The filename may be a wildcard.  Multiple attributes may be specified.
  38. ;
  39. ; Inverse attributes are provided as a friendly touch:
  40. ;
  41. ;      Hidden   <==>   Visible
  42. ;      System   <==>   User
  43. ;      Read     <==>   Write
  44. ;      Archive  <==>   Backed-up
  45. ;
  46. ; So +R is the same as -W, etc.
  47. ;
  48. ;   Enjoy!
  49. ;
  50.     .SALL
  51. ;
  52. ; Values for exit status:
  53. ;    0 - Success
  54. ;    1 - Parameter too long
  55. ;    2 - Incorrect DOS version
  56. ;    3 - File does not exist
  57. ;    4 - Invalid attribute letter
  58. ;
  59. ; Constants
  60. ;
  61. TAB    EQU    09H            ; Tabulate
  62. LF    EQU    0AH            ; Linefeed
  63. CR    EQU    0DH            ; Carriage return
  64. PTHSEP1    EQU    '\'            ; Normal path separator
  65. PTHSEP2    EQU    '/'            ; Alternate path separator
  66. ;
  67. STDOUT    EQU    1            ; Standard output handle
  68. STDERR    EQU    2            ; Standard error handle
  69. MAXFNAM    EQU    63            ; Maximum length of filename
  70. ;
  71. ; Macro definitions
  72. ;
  73. MSG    MACRO    X,Y            ;; define a message
  74. MES&X    DB    Y
  75. LMES&X    EQU    $-MES&X
  76.     ENDM
  77. ;
  78. $MSG    MACRO    X            ;; display a message on standard error
  79.     MOV    BX,STDERR        ;; file handle
  80.     MOV    DX,OFFSET MES&X        ;; location of message
  81.     MOV    CX,LMES&X        ;; length of message
  82.     MOV    AH,40H            ;; write function
  83.     INT    21H
  84.     ENDM
  85. ;
  86. CSEG    SEGMENT
  87. ;
  88.     ORG    100H
  89. ;
  90.     ASSUME    CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG
  91. ;
  92. MAIN    PROC    FAR
  93.     JMP    MAIN10
  94. ;
  95.     SUBTTL    Data areas
  96.     PAGE+
  97. ;
  98. ; Storage
  99. ;
  100. ATT    DW    ?            ; Mask and bits specified by parameter
  101. FIRST    DB    ?            ; Used for 'find first' calls
  102. PARPTR    DW    ?            ; Pointer to next parameter
  103. PSIZE    DW    ?            ; Size of path part of filename
  104. DISP    DB    ?,?,?,?,'    '        ; Attribute display string
  105. LDISP    EQU    $-DISP            ; Length of DISP
  106. FNAME    DB    MAXFNAM+1 DUP (?)    ; Extra byte for terminator
  107. DTA    DB    43 DUP (?)        ; Alternate disk transfer area
  108. ;
  109. ; Table of attribute settings
  110. ;
  111. ; The table ATTC is a list of valid attribute letters
  112. ; The table ATTON corresponds one-to-one with ATTC for setting an attribute
  113. ; The table ATTOFF corresponds one-to-one with ATTC for clearing an attribute
  114. ; ATTON and ATTOFF use the high byte of each entry as a mask to clear
  115. ; unwanted bits, and the low byte to indicate bits to be set.
  116. ;
  117. ATTC    DB    'RWHVSUAB'
  118. NATT    EQU    $-ATTC
  119. ATTON    DW    0FE01H,0FE00H,0FD02H,0FD00H,0FB04H,0FB00H,0DF20H,0DF00H
  120. ATTOFF    DW    0FE00H,0FE01H,0FD00H,0FD02H,0FB00H,0FB04H,0DF00H,0DF20H
  121. ;
  122. CRBUF    DB    CR,LF
  123. ;
  124.     DW    32 DUP (?)        ; Stack
  125. STACK    LABEL    WORD
  126. ;
  127. ; Messages
  128. ;
  129.     MSG    1,<'Parameter too long',CR,LF>
  130.     MSG    2,<'Filename too long - '>
  131.     MSG    3,<'Incorrect DOS version',CR,LF>
  132.     MSG    4,<'No matching file found for '>
  133.     MSG    5,<'Invalid attribute letter',CR,LF>
  134. ;
  135.     SUBTTL    Main code
  136.     PAGE+
  137. ;
  138. MAIN10:    MOV    SP,OFFSET STACK        ; set up stack
  139. ;
  140.     MOV    AH,30H
  141.     INT    21H            ; get DOS version
  142.     XCHG    AH,AL            ; make more useful form
  143.     CMP    AX,0200H        ; version 2 at least?
  144.     JAE    MAIN20            ; j if so - OK
  145.     $MSG    3            ; "Incorrect DOS version"
  146.     MOV    AL,2            ; exit status
  147.     JMP    SHORT MAIN60        ; join common exit code
  148. ;
  149. MAIN20:    MOV    DX,OFFSET DTA        ; set alternate DTA to avoid...
  150.     MOV    AH,1AH            ; ...overwriting parameters
  151.     INT    21H
  152.     MOV    PARPTR,81H        ; start of parameter area
  153.     CALL    GETFLAGS        ; get any attribute flags
  154.     JC    MAIN60            ; j if error (unrecognised flag)
  155. MAIN30:    CALL    GETPAR            ; read next parameter item
  156.     JC    MAIN50            ; j if no more parameters
  157.     CALL    DOTSTR            ; add '.*' if needed
  158.     MOV    BYTE PTR FIRST,0    ; clear 'find first' flag
  159. MAIN40:    CALL    GETNAM            ; get next filename
  160.     JC    MAIN30            ; j if no more names
  161.     CALL    DOATTR            ; handle attribute
  162.     JC    MAIN60            ; j if error (status in AL)
  163.     JMP    MAIN40            ; see if more to do
  164. ;
  165. MAIN50:    XOR    AL,AL            ; zero status
  166. ;
  167. MAIN60:    MOV    AH,4CH            ; exit
  168.     INT    21H
  169. MAIN    ENDP
  170. ;
  171.     SUBTTL    Get attribute flag from command line
  172.     PAGE
  173. ;
  174. ; This routine reads an attribute flag and its sense from the command line.
  175. ; Attribute flags start with '+' or '-' and continue with a letter.
  176. ; Possible letters are:  R  -  read only
  177. ;                        W  -  read and write (inverse of read only)
  178. ;                        H  -  hidden
  179. ;                        V  -  visible (inverse of hidden)
  180. ;                        S  -  system
  181. ;                        U  -  user (inverse of system)
  182. ;             A  -  archive needed
  183. ;             B  -  backed-up (inverse of archive-needed)
  184. ;
  185. ; On entry:  PARPTR points to the first byte of the parameter string
  186. ;
  187. ;  On exit:  PARPTR has been updated past the attribute specification if
  188. ;            one was found
  189. ;
  190. ; Return is made with ATT high containing a mask to remove any unwanted bits,
  191. ; and with ATT low containing any additional bits to be set in the attributes.
  192. ; The value ATT=0FF00H is returned if no attribute flag was found, and carry
  193. ; is set if an unrecognised attribute letter was encountered.
  194. ;
  195. GETFLAGS PROC    NEAR
  196.     MOV    ATT,0FF00H        ; This mask leaves the attributes
  197.                     ; unchanged.
  198.     CLD                ; autoincrement
  199.     MOV    SI,PARPTR        ; point to start of parameter list
  200. GETF10:    LODSB                ; skip leading spaces...
  201.     CMP    AL,' '
  202.     JE    GETF10
  203.     CMP    AL,TAB            ; ...and tabs
  204.     JE    GETF10
  205.     CMP    AL,'+'            ; valid sense?
  206.     JE    GETF20            ; j if so
  207.     CMP    AL,'-'            ; other sense?
  208.     JE    GETF20            ; j if so
  209. GETF15:    DEC    SI            ; Backup the parameter pointer.
  210.     MOV    PARPTR,SI        ; Save the pointer for later use.
  211.     CLC                ; indicate success
  212.     RET                ; return with carry clear
  213. ;
  214. GETF20:    MOV    DL,AL            ; save sense
  215.     LODSB                ; get attribute letter
  216. GETF25:    CALL    UPPER            ; convert to upper case
  217.     MOV    BX,OFFSET ATTC        ; list of valid letters
  218.     MOV    CX,NATT            ; count of valid letters
  219.     XOR    DI,DI            ; pointer into letter table
  220. GETF30:    CMP    AL,[BX+DI]        ; found the letter?
  221.     JE    GETF40            ; j if so
  222.     INC    DI            ; point to next possibility
  223.     LOOP    GETF30            ; keep trying
  224.     $MSG    5            ; "Invalid attribute letter"
  225.     MOV    AL,4            ; exit status
  226.     STC                ; indicate error
  227.     RET
  228. ;
  229. GETF40:    MOV    BX,OFFSET ATTON        ; assume sense 'on'
  230.     CMP    DL,'-'
  231.     JNE    GETF50            ; j if sense 'on' required
  232.     MOV    BX,OFFSET ATTOFF    ; else use different table
  233. GETF50:    ADD    DI,DI            ; form word offset
  234.     MOV    AX,[BX+DI]        ; get mask and attribute word
  235.     MOV    BX,ATT            ; Get the previous mask.
  236.     AND    BL,AH            ; Clear incompatible bits.
  237.     AND    AH,BH            ; Merge the bits-to-keep mask.
  238.     OR    AL,BL            ; Merge the bits-to-set mask.
  239.     MOV    ATT,AX            ; Save the resultant mask.
  240.  
  241. GETF60:    LODSB                ; Get the next command byte.
  242.     CMP    AL,' '            ; Space means end of these flags.
  243.     JE    GETF10            ; Jump to look for next flags.
  244.     CMP    AL,TAB            ; Tab also means end of these flags.
  245.     JE    GETF10            ; Jump to look for next flags.
  246.     CMP    AL,CR            ; CR is premature, treat it
  247.     JE    GETF15            ; as the end of the flags.
  248.     CMP    AL,'+'            ; Plus is another set of flags.
  249.     JE    GETF20            ; Go parse the flags.
  250.     CMP    AL,'-'            ; Minus is another set of flags.
  251.     JE    GETF20            ; Go parse the flags.
  252.     JMP    GETF25            ; Else assume this is another flag.
  253.  
  254. GETFLAGS ENDP
  255. ;
  256.     SUBTTL    Get next parameter
  257.     PAGE
  258. ;
  259. ; This routine reads the next parameter from the command line, converting
  260. ; it to upper case and placing it into the area FNAME.
  261. ; Parameters are delimited by spaces, tabs, commas or the end of the line.
  262. ;
  263. ; On exit:
  264. ;    Carry is clear if a parameter was found
  265. ;    Carry is set if the parameter list is exhausted
  266. ;
  267. GETPAR    PROC    NEAR
  268.     CLD                ; autoincrement
  269.     MOV    SI,PARPTR        ; point to start of possible parameter
  270. GETP10:    LODSB                ; skip leading spaces...
  271.     CMP    AL,' '
  272.     JE    GETP10
  273.     CMP    AL,TAB            ; ...and tabs
  274.     JE    GETP10
  275.     MOV    DI,OFFSET FNAME        ; area to hold item
  276.     MOV    CX,MAXFNAM        ; maximum item size
  277. GETP20:    CMP    AL,CR            ; end of list?
  278.     JNE    GETP30            ; j if not
  279.     DEC    SI            ; must re-read next time
  280.     JMP    SHORT GETP40
  281. GETP30:    CMP    AL,' '            ; other terminators...
  282.     JE    GETP40
  283.     CMP    AL,TAB
  284.     JE    GETP40
  285.     CMP    AL,','
  286.     JE    GETP40            ; ...are space, tab and comma
  287.     CMP    AL,';'
  288.     JE    GETP40            ; ...and semicolon
  289.     CALL    UPPER            ; convert to upper case
  290.     STOSB                ; store character away
  291.     LODSB                ; get next character
  292.     LOOP    GETP20
  293. ;
  294. GETP40:    JCXZ    GETP60            ; j if too long
  295.     XOR    AL,AL            ; add terminator
  296.     STOSB
  297.     MOV    PARPTR,SI        ; save new value
  298.     CMP    CX,MAXFNAM        ; null item?
  299.     JNE    GETP50            ; j if not
  300.     STC                ; indicate no more
  301.     RET
  302. ;
  303. GETP50:    CLC                ; indicate item found
  304.     RET
  305. ;
  306. GETP60:    $MSG    1            ; "Parameter too long"
  307.     MOV    AL,1            ; exit status
  308.     JMP    MAIN60
  309. GETPAR    ENDP
  310. ;
  311.     SUBTTL    Add Dot Star
  312.     PAGE
  313. ;
  314. ; This routine appends '.*' to a file name string when the
  315. ; extension is not explicitly specified.  The file name is
  316. ; taken from and changed in FNAME.
  317. ;
  318. DOTSTR    PROC    NEAR
  319.     CLD                ; autoincrement
  320.     MOV    SI,OFFSET FNAME        ; point to start of file name
  321.     MOV    CX,MAXFNAM        ; maximum item size
  322. DOTS10:    MOV    BL,0            ; Clear the dot-seen flag.
  323. DOTS20:    LODSB                ; Get the next character.
  324.     DEC    CX            ; Count another character parsed.
  325.     CMP    AL,0            ; Is this the end?
  326.     JE    DOTS30            ; Jump if it is.
  327.     CMP    AL,':'            ; Is this a device delimiter?
  328.     JE    DOTS10            ; Jump and clear dot seen flag.
  329.     CMP    AL,'\'            ; Is this a directory delimiter?
  330.     JE    DOTS10            ; Jump and clear dot seen flag.
  331.     CMP    AL,'.'            ; Is this a dot?
  332.     JNE    DOTS20            ; Jump if it is not.
  333.     INC    BL            ; Note that we have seen a dot.
  334.     JMP    DOTS20            ; Go check the next character.
  335. DOTS30:    CMP    BL,0            ; Did we see a file extension?
  336.     JNE    DOTS50            ; Jump if we did.
  337.     CMP    CX,2            ; Is there enough space left?
  338.     JL    DOTS60            ; Jump if there is not.
  339.     MOV    SI,DI            ; Prepare to append the '.*'.
  340.     DEC    DI            ; Back up to terminator.
  341.     MOV    AL,'.'            ; Get a dot.
  342.     STOSB                ; Store it.
  343.     MOV    AL,'*'            ; Get a star.
  344.     STOSB                ; Store it.
  345.     XOR    AL,AL            ; ASCIIZ terminator
  346.     STOSB                ; Store it.
  347. DOTS50:    RET                ; All done.
  348. ;
  349. DOTS60:    $MSG    1            ; "Parameter too long"
  350.     MOV    AL,1            ; exit status
  351.     JMP    MAIN60
  352. DOTSTR    ENDP
  353. ;
  354.     SUBTTL    Get next filename
  355.     PAGE
  356. ;
  357. ; This routine gets the next filename matching the parameter.
  358. ; The filename is left in FNAME.
  359. ;
  360. ; On exit:
  361. ;    Carry is clear if a match was found
  362. ;    Carry is set if no further matches exist
  363. ;
  364. GETNAM    PROC    NEAR
  365.     CLD                ; autoincrement
  366.     CMP    FIRST,0            ; first time with this parameter item?
  367.     JNE    GETN60            ; j if not
  368.     INC    FIRST            ; mark not first any more
  369. ;
  370.     MOV    SI,OFFSET FNAME        ; find last separator
  371. GETN10:    MOV    BX,SI            ; initial value
  372. GETN20:    LODSB                ; get next byte of name
  373.     OR    AL,AL            ; end of name?
  374.     JZ    GETN30            ; j if so
  375.     CMP    AL,PTHSEP1        ; normal separator?
  376.     JE    GETN10            ; j if so, and update pointer
  377.     CMP    AL,PTHSEP2        ; alternate separator?
  378.     JE    GETN10            ; j if so, and update pointer
  379.     CMP    AL,':'            ; drive name?
  380.     JE    GETN10            ; j if so; this counts as separator
  381.     JMP    GETN20
  382. ;
  383. ; BX now points at first character of last component of filename
  384. ;
  385. GETN30:    SUB    BX,OFFSET FNAME        ; derive length of path part
  386.     MOV    PSIZE,BX
  387.     MOV    DX,OFFSET FNAME
  388.     MOV    CX,07H            ; get read only, system and hidden
  389.                     ; files too
  390.     MOV    AH,4EH            ; find first matching file
  391.     INT    21H
  392.     JNC    GETN40            ; j if match found
  393.     $MSG    4            ; "No matching file found for "
  394.     MOV    BX,STDERR
  395.     CALL    PRNAME
  396.     MOV    BX,STDERR
  397.     CALL    CRLF
  398.     STC                ; indicate error
  399.     RET
  400. ;
  401. GETN40:    MOV    SI,OFFSET DTA+30    ; terminal filename
  402.     MOV    DI,OFFSET FNAME
  403.     ADD    DI,PSIZE        ; point to filename part of path
  404.     MOV    CX,MAXFNAM
  405. GETN50:    LODSB
  406.     STOSB
  407.     OR    AL,AL
  408.     LOOPNE    GETN50            ; copy name and terminator
  409.     JCXZ    GETN70            ; j if name too long
  410.     CLC
  411.     RET                ; return with carry clear
  412. ;
  413. GETN60:    MOV    AH,4FH            ; find next matching file
  414.     INT    21H
  415.     JNC    GETN40            ; j if match found
  416.     RET                ; return with carry still set
  417. ;
  418. GETN70:    $MSG    2            ; "Filename too long - "
  419.     MOV    BX,STDERR
  420.     CALL    PRNAME
  421.     MOV    BX,STDERR
  422.     CALL    CRLF
  423.     STC                ; indicate error
  424.     RET
  425. GETNAM    ENDP
  426. ;
  427.     SUBTTL    Actual attribute alteration and display code
  428.     PAGE
  429. ;
  430. DOATTR    PROC    NEAR
  431.     CMP    ATT,0FF00H        ; just display required?
  432.     JE    DOA100            ; j if so
  433. ;
  434.     MOV    AX,4300H        ; first get existing attributes
  435.     MOV    DX,OFFSET FNAME
  436.     INT    21H            ; attribute to CX (just CL really)
  437.     JC    DOA200            ; j if error (should not happen)
  438.     AND    CL,BYTE PTR ATT+1    ; remove unwanted bits
  439.     OR    CL,BYTE PTR ATT        ; add new bits
  440.     MOV    AX,4301H        ; set attributes now
  441.     MOV    DX,OFFSET FNAME
  442.     INT    21H
  443.     JC    DOA200            ; j if error (should not happen)
  444.     RET
  445. ;
  446. DOA100:    MOV    AX,4300H        ; get attribute
  447.     MOV    DX,OFFSET FNAME
  448.     INT    21H            ; returns attribute in CX
  449.     JC    DOA200            ; j if error (should not happen)
  450. ;
  451.     MOV    DI,OFFSET DISP        ; point to output area
  452.     CLD                ; autoincrement
  453.     MOV    AH,' '
  454.     MOV    AL,AH            ; assume space initially
  455.     TEST    CL,01H            ; read only attribute?
  456.     JZ    DOA110            ; j if not
  457.     MOV    AL,'R'            ; else set character
  458. DOA110:    STOSB                ; set up for output
  459.     MOV    AL,AH            ; restore space
  460.     TEST    CL,02H            ; hidden attribute?
  461.     JZ    DOA120            ; j if not
  462.     MOV    AL,'H'            ; else set character
  463. DOA120:    STOSB                ; set up for output
  464.     MOV    AL,AH            ; restore space
  465.     TEST    CL,04H            ; system attribute?
  466.     JZ    DOA130            ; j if not
  467.     MOV    AL,'S'            ; else set character
  468. DOA130:    STOSB                ; set up for output
  469.     MOV    AL,AH            ; restore space
  470.     TEST    CL,20H            ; archive-needed attribute?
  471.     JZ    DOA140            ; j if not
  472.     MOV    AL,'A'            ; else set character
  473. DOA140:    STOSB                ; set up for output
  474.     MOV    BX,STDOUT        ; handle
  475.     MOV    CX,LDISP        ; byte count for message
  476.     MOV    DX,OFFSET DISP
  477.     MOV    AH,40H            ; write function
  478.     INT    21H
  479. ;    JC    DOA200            ; j if error
  480.     MOV    BX,STDOUT        ; handle
  481.     CALL    PRNAME            ; follow up with filename
  482.     MOV    BX,STDOUT
  483.     CALL    CRLF            ; finish off line
  484. DOA200:    RET
  485. DOATTR    ENDP
  486. ;
  487.     SUBTTL    Miscellaneous subroutines
  488.     PAGE
  489. ;
  490. ; Routine to convert the letter in AL to upper case.
  491. ;
  492. UPPER    PROC    NEAR
  493.     CMP    AL,'a'            ; check lower range
  494.     JB    UPP10            ; j if out of range
  495.     CMP    AL,'z'            ; check upper range
  496.     JA    UPP10            ; j if out of range
  497.     SUB    AL,'a'-'A'        ; do the conversion
  498. UPP10:    RET
  499. UPPER    ENDP
  500. ;
  501. ; Routine to write a carriage return and linefeed to the file specified
  502. ; by the handle in BX.
  503. ;
  504. CRLF    PROC    NEAR
  505.     MOV    CX,2            ; byte count
  506.     MOV    DX,OFFSET CRBUF
  507.     MOV    AH,40H            ; write function
  508.     INT    21H
  509.     RET
  510. CRLF    ENDP
  511. ;
  512. ; Routine to output the filename in FNAME to the file specified by the
  513. ; handle in BX.
  514. ;
  515. PRNAME    PROC    NEAR
  516.     MOV    DI,OFFSET FNAME
  517.     PUSH    DI            ; save for later
  518.     CLD                ; autoincrement
  519.     XOR    AL,AL            ; search for zero byte
  520.     MOV    CX,0FFFFH        ; very long loop!
  521.     REPNE    SCASB
  522.     MOV    CX,DI
  523.     POP    DX            ; initial pointer
  524.     SUB    CX,DX            ; derive length
  525.     MOV    AH,40H            ; write function
  526.     INT    21H
  527.     RET
  528. PRNAME    ENDP
  529. ;
  530. CSEG    ENDS
  531. ;
  532.     END    MAIN
  533.