home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / dirutl / attrib.arc / ATTRIB.ASM next >
Encoding:
Assembly Source File  |  1986-02-08  |  12.6 KB  |  463 lines

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