home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / ENTERPRS / CPM / UTILS / S / XLINK10.LBR / XLINK.1Z0 / XLINK.180
Text File  |  2000-06-30  |  15KB  |  516 lines

  1. ; XLINK - A routine to display names of files with cross-linked clusters.
  2. ;
  3. ; Written: 03/29/90
  4. ;      By: Tony Newman
  5. ;
  6. ; Written for assembly by SLR Systems: SLR180+.
  7. ; Should assemble under Microsoft's MACRO-80 with no modification.
  8. ;
  9. ; All external references are to SYSLIB (ver. 4) routines.
  10. ;
  11. ; Released for public distribution and modification.
  12. ;
  13. ;============================================================================
  14. ;
  15. ;
  16. ; General operating system equates.
  17. ;
  18. exit    equ    0000H        ;warmstart
  19. bdos    equ    0005H        ;C-function entry point
  20. stack    equ    0006H        ;pointer to first address used by O/S
  21. dbuff    equ    0080H        ;default DMA area
  22. ;
  23. ; Character equates
  24. ;
  25. bel    equ    07H        ;<bell> character
  26. bs    equ    08H        ;backspace
  27. cr    equ    0DH        ;carriage return
  28. lf    equ    0AH        ;linefeed
  29. spc    equ    20H        ;<space> character
  30. ;
  31. ; Current version
  32. ;
  33. major    equ    1
  34. minor    equ    0
  35.  
  36.     jp    setstk        ;skip over user setable bytes
  37.  
  38. qflg:    db    0        ;initially, quiet-flag is off
  39.  
  40. setstk:    ld    sp,(stack)    ;elbow room for stack
  41.  
  42.     ld    de,dbuff
  43.     ld    c,26        ;set DMA address
  44.     call    bdos        ;probably not necessary
  45. ;
  46. ; say hello to the world
  47. ;
  48.     ld    hl,hello    ;address of signon string
  49.     call    pstr##
  50. ;
  51. ; initialize whatever needs it
  52. ;
  53.     ld    hl,($memry##)    ;address of first free byte
  54.     ld    (bmap),hl
  55.     ld    d,h        ;copy into reg-DE
  56.     ld    e,l
  57.     inc    de        ;make DE point to the next byte
  58.     ld    bc,8191        ;number of bytes to clear -1
  59.     ld    (hl),0        ;clear the first byte
  60.     ldir            ;clear the rest
  61.  
  62.     ld    hl,0
  63.     ld    (xclu),hl    ;initialize crosslink count
  64.     ld    (brec),hl    ;initialize current filemap record
  65. ;
  66. ; Get DPB values for various calculations
  67. ;
  68.     ld    c,31        ;get DPB address
  69.     call    bdos
  70.     ld    de,locdpb    ;address of local DPB
  71.     ld    bc,15        ;a DPB is 15 bytes long
  72.     ldir            ;move into local DPB
  73. ;
  74. ; Determine if cluster numbers will be 16 or 8 bits long
  75. ;
  76.     ld    a,(dsm+1)    ;get high byte
  77.     ld    (size),a    ;any non-zero value means 16-bit cluster #'s
  78. ;
  79. ; Save current drive and user.
  80. ;
  81.     call    retud##        ;get drive and user
  82.     ld    (du),bc        ;save it
  83. ;
  84. ; Determine the maximum workfile size.
  85. ;
  86.     ld    hl,(dsm)    ;get highest cluster number
  87.     inc    hl        ;add one to get number of clusters
  88.     srl    h        ;divide by 64 to determine number of
  89.     rr    l        ;kilobytes that might be needed
  90.     srl    h
  91.     rr    l
  92.     srl    h        ;this just needs to be an estimate to allow
  93.     rr    l        ;user to select a drive for the work file
  94.     srl    h
  95.     rr    l
  96.     srl    h
  97.     rr    l
  98.     srl    h
  99.     rr    l
  100.     inc    hl        ;add one to account for any remainder
  101. ;
  102. ; advise user of workfile size possibility
  103. ;
  104.     ex    de,hl        ;save file size for a moment
  105.     ld    hl,sizms    ;first part of message
  106.     call    pstr##
  107.     ex    de,hl        ;get file size back
  108.     call    phlfdc##    ;print it
  109.     ld    hl,sizms1    ;second part of message (and question)
  110.     call    pstr##
  111. ;
  112. ; ask for drive for workfile
  113. ;
  114.     ld    a,0FFH        ;make reg-A non-zero
  115.     call    bbline##    ;get users drive preference
  116.     call    crlf##        ;skip a line
  117.     call    crlf##        ;or two
  118.     or    a        ;any answer?
  119.     jp    z,exit        ;no, bail out
  120.     ld    b,a
  121. lookdr:    ld    a,(hl)        ;get character from answer
  122.     call    isalpha##    ;is it alphabetic?
  123.     jp    z,gotdrv    ;yes, this is the drive letter
  124.     inc    hl        ;point to next character
  125.     djnz    lookdr        ;keep looking
  126.     jp    exit        ;quit if silly answer
  127. gotdrv:    sub    'A'        ;make drive name numeric (0 = A:)
  128.     ld    bc,(du)        ;get current drive and user
  129.     ld    b,a        ;change drive field to workfile drive
  130. ;
  131. ; see if we can actually open a file on specified drive
  132. ;
  133.     ld    (wdu),bc    ;save workfile drive/user
  134.     call    logud##        ;log into workfile drive/user
  135.     ld    de,wrkfcb    ;address of workfile FCB
  136.     call    f$delete##    ;delete any pre-exixting workfile
  137.     call    f$make##    ;make a new file
  138.     inc    a        ;any errors?
  139.     jp    nz,opok        ;no, continue
  140.     ld    hl,wofail
  141.     call    pstr##        ;tell user open of workfile failed
  142.     jp    exit
  143. ;
  144. ; ask user if printed output is desired
  145. ;
  146. opok:
  147.     ld    hl,ptrms1    ;ask if output to printer is wanted
  148.     call    pstr##
  149.     ld    a,0FFH        ;make reg-A non-zero
  150.     call    bbline##    ;get users printer preference
  151.     call    crlf##        ;skip a couple of lines
  152.     call    crlf##
  153.     or    a        ;any answer?
  154.     jp    z,exit        ;no, bail out
  155.     ld    b,a
  156. lookpr:    ld    a,(hl)        ;get character from answer
  157.     cp    'Y'        ;printer output desired
  158.     jp    z,pyes        ;jump if so
  159.     cp    'N'        ;printer output not desired
  160.     jp    z,pno        ;jump if so
  161.     inc    hl        ;point to next character
  162.     djnz    lookpr        ;keep looking
  163.     jp    exit        ;quit if silly answer
  164. pyes:    ld    a,81H        ;set printer flag to 'yes'
  165.     jp    setflg
  166. pno:    ld    a,01H        ;set printer flag to 'no'
  167. setflg:    ld    (sctlfl##),a
  168. ;
  169. ; display 'Cluster: ' message if quiet mode is off
  170. ;
  171.     ld    hl,clstr    ;print "Cluster: " string
  172.     ld    a,(qflg)    ;quiet mode?
  173.     or    a
  174.     call    z,pstr##
  175. ;
  176. ; log back into drive to be tested, and search for first file
  177. ;
  178.     ld    bc,(du)        ;recover current drive/user
  179.     call    logud##        ;log into it
  180.     ld    c,17        ;search for first directory entry
  181.     ld    de,tgtfcb    ;look through all entries
  182.     call    bdos
  183. ;
  184. ; Process found directory entry
  185. ;
  186. proc:    cp    0FFH        ;end of directory?
  187.     jp    z,finish    ;yes, clean-up and get out
  188.     add    a,a        ;multiply directory index by 32
  189.     add    a,a
  190.     add    a,a
  191.     add    a,a
  192.     add    a,a
  193.     ld    hl,dbuff    ;base of DMA area
  194.     ld    e,a        ;put offset into reg-DE
  195.     ld    d,0
  196.     add    hl,de        ;point to found directory entry
  197.     ld    (tfcb),hl    ;save this address
  198.     ld    a,(hl)        ;get first byte of directory entry
  199.     cp    0E5H        ;deleted entry?
  200.     jp    z,skip        ;skip it if so
  201.     ld    de,16        ;offset to allocation information
  202.     add    hl,de        ;point to cluster numbers
  203.  
  204.     ld    a,(size)    ;get cluster number size flag
  205.     or    a        ;8-bit cluster numbers?
  206.     jp    z,cl8        ;yes, use alternate routine
  207. ;
  208. ; This deals with 16-bit cluster numbers
  209. ;
  210.     ld    b,8        ;8 cluster numbers per directory entry
  211. ck16:    ld    e,(hl)        ;get low byte of cluster number
  212.     inc    hl        ;point to high byte
  213.     ld    d,(hl)        ;get high byte of cluster number
  214.     inc    hl        ;point to next cluster number
  215.     call    fmap        ;place into map file
  216.     call    c,xlrpt        ;scream if already in map
  217.     djnz    ck16        ;check other cluster #'s in this dir. entry
  218.     jp    skip        ;search for 'next' directory entry
  219. ;
  220. ; This deals with disks where each cluster number is only 8-bits long
  221. ;
  222. cl8:    ld    b,16        ;16 cluster numbers per directory entry
  223. ck8:    ld    e,(hl)        ;get cluster number
  224.     ld    d,0        ;set high byte to zero
  225.     inc    hl        ;point to next cluster number
  226.     call    fmap        ;place into map file
  227.     call    c,xlrpt        ;scream if already in map
  228.     djnz    ck8        ;check other cluster #'s in this dir. entry
  229.  
  230. skip:    ld    c,18        ;search for next directory entry
  231.     call    bdos
  232.     jp    proc        ;deal with this directory entry
  233. ;
  234. ; no more directory entries, clean-up, print total, and get out
  235. ;
  236. finish:
  237.     ld    bc,(wdu)    ;get workfile drive/user
  238.     call    logud##        ;log into it
  239.     ld    de,wrkfcb    ;address of workfile FCB
  240.     call    f$close##    ;close the file
  241.     call    f$delete##    ;delete the file
  242.     ld    bc,(du)        ;get back to initial drive/user area
  243.     call    logud##        ;log into it
  244.     call    crlf##        ;skip a couple lines
  245.     call    crlf##
  246.     ld    hl,(xclu)    ;get number of crosslinkings found
  247.     call    phlfdc##    ;print it
  248.     ld    hl,str1        ;first part of 'total' message
  249.     call    pstr##
  250.     ld    hl,(xclu)    ;get number again
  251.     dec    hl        ;if only 1, this will make HL = 0
  252.     ld    a,h
  253.     or    l        ;is it zero?
  254.     jp    z,essno        ;yes, do not use plural form
  255.     ld    a,'s'
  256.     call    cout##        ;make plural
  257. essno:    ld    hl,str2        ;print rest of 'total' message
  258.     call    pstr##
  259.     jp    exit
  260. ;
  261. ; Place file name in map file according to cluster number passed in reg-DE
  262. ; Return with carry set if already marked (crosslink).
  263. ;
  264. fmap:
  265.     ld    a,d        ;if cluster #0 just return
  266.     or    e
  267.     ret    z
  268.     push    bc        ;preserve registers
  269.     push    hl
  270.     ex    de,hl        ;swap cluster number into reg-HL
  271.     ld    (clnum),hl    ;save cluster number for possible use later
  272.     ld    a,(qflg)
  273.     or    a        ;'quiet' mode active?
  274.     jp    nz,noscr1    ;yes, jump around cluster number printing
  275.     ld    a,bs        ;load-up a backspace character
  276.     ld    b,5        ;length of cluster number
  277. bakup:    call    cout##        ;backup cursor to start of number
  278.     djnz    bakup
  279.     call    phldc##        ;print cluster number
  280. noscr1:    ld    a,l        ;get low byte of cluster number
  281.     and    00000111B    ;bit number to check
  282.     ld    (roff),a    ;save as index into record
  283.     ld    b,a        ;put in reg-B for countdown
  284.     inc    b        ;add one for fudge factor
  285.     xor    a        ;clear for shifting
  286.     scf            ;make sure there is something to shift in
  287. shft:    rla            ;shift left
  288.     djnz    shft        ;until reg-B is zero
  289.     ld    b,a        ;save mask in reg-B
  290.     srl    h        ;divide HL by eight
  291.     rr    l
  292.     srl    h
  293.     rr    l
  294.     srl    h
  295.     rr    l
  296.     ld    (rcrd),hl    ;save as record number of file map
  297.     ld    de,(bmap)    ;base address of bit-map
  298.     add    hl,de        ;point to coresponding byte
  299.     ld    (bptr),hl    ;save pointer into bitmap
  300.     ld    a,(hl)        ;get byte
  301.     and    b        ;already allocated?
  302.     scf            ;make sure carry is set
  303.     jp    nz,gback    ;fix stack and return
  304.     push    bc        ;save mask (reg-B)
  305.     ld    c,26
  306.     ld    de,wbuff    ;set DMA address to workfile buffer
  307.     call    bdos
  308.     ld    bc,(wdu)    ;get workfile drive/user
  309.     call    logud##        ;log into it
  310.     ld    hl,(rcrd)    ;record number of file map
  311.     ld    de,(brec)    ;record number of current buffer
  312.     call    comphd##    ;proper record already in workfile buffer?
  313.     jp    z,skip2        ;yes, save some time - skip the preread
  314.     ld    (brec),hl    ;save record number of new current buffer
  315.     ld    de,wrkfcb    ;address of workfile FCB
  316.     call    r$read##    ;read record
  317. skip2:    ld    a,(roff)    ;index into record
  318.     add    a,a        ;multiply index by 16
  319.     add    a,a
  320.     add    a,a
  321.     add    a,a
  322.     ld    e,a        ;put offset into DE
  323.     ld    d,0
  324.     ld    hl,wbuff    ;base address of workfile buffer
  325.     add    hl,de        ;add offset (to make pointer)
  326.     ex     de,hl        ;move pointer to reg-DE
  327.     ld    hl,(tfcb)    ;addr of dir entry that owns this cluster
  328.     ld    bc,16        ;length of directory entry (only need first 12)
  329.     ldir            ;put filename into map record
  330.     ld    de,wrkfcb    ;address of workfile FCB
  331.     ld    hl,(rcrd)    ;record number of file map
  332.     call    r$write##    ;write updated record back to workfile
  333.     ld    c,26
  334.     ld    de,dbuff    ;set DMA address to directory buffer
  335.     call    bdos
  336.     ld    bc,(du)        ;get test drive/user
  337.     call    logud##        ;log into it
  338.     pop    bc        ;recover mask (reg-B)
  339.     ld    hl,(bptr)    ;recover pointer into bit-map
  340.     ld    a,(hl)        ;get byte again
  341.     or    b        ;set bit (and clear carry)
  342.     ld    (hl),a        ;update bit-map
  343. gback:    pop    hl        ;restore registers
  344.     pop    bc
  345.     ret
  346. ;
  347. ; Notify world that a cross-link has been detected
  348. ;
  349. xlrpt:
  350.     push    hl        ;preserve registers
  351.     push    bc
  352.     ld    a,(qflg)
  353.     or    a        ;quiet mode active?
  354.     jp    nz,noscr2    ;yes, jump around cluster number seperation
  355.     ld    a,spc        ;get <space> character
  356.     call    cout##
  357.     call    cout##        ;move off from cluster number a bit
  358.     call    cout##
  359. noscr2:    ld    bc,(du)        ;get current drive name
  360.     ld    a,b        ;move drive number to reg-A
  361.     add    a,'A'        ;make it ASCII
  362.     call    sout##        ;print it
  363.     ld    de,(tfcb)    ;get address of current directory entry
  364.     ld    a,(de)        ;get user number
  365.     cp    10        ;less than 10
  366.     jp    nc,nozer    ;no, no leading zero needed
  367.     ld    a,'0'
  368.     call    sout##
  369.     ld    a,(de)        ;get number again
  370. nozer:    call    safdc##        ;print user number
  371.     ld    a,':'
  372.     call    sout##
  373.     inc    de        ;point to file name
  374.     call    sfn3##        ;print it
  375.     ld    hl,xlmsg1    ;get 'crosslinked with' message
  376.     call    spstr##        ;print it
  377.     ld    c,26
  378.     ld    de,xbuff    ;set DMA address to aux file buffer
  379.     call    bdos
  380.     ld    bc,(wdu)    ;get workfile drive/user
  381.     call    logud##        ;log into it
  382.     ld    de,wrkfcb    ;address of workfile FCB
  383.     ld    hl,(rcrd)    ;record number of file map
  384.     call    r$read##    ;read record
  385.     ld    a,(roff)    ;index into record
  386.     add    a,a        ;multiply index by 16
  387.     add    a,a
  388.     add    a,a
  389.     add    a,a
  390.     ld    e,a        ;put offset into DE
  391.     ld    d,0
  392.     ld    hl,xbuff    ;base address of aux file buffer
  393.     add    hl,de        ;add offset (to make pointer)
  394.     ld    (wfcb),hl    ;save address of crossed filename
  395.     ld    c,26
  396.     ld    de,dbuff    ;set DMA address to directory buffer
  397.     call    bdos
  398.     ld    bc,(du)        ;get test drive/user
  399.     call    logud##        ;log into it
  400.     ld    a,b        ;move drive number to reg-A
  401.     add    a,'A'        ;make it ASCII
  402.     call    sout##
  403.     ld    de,(wfcb)    ;get address of crossed directory entry
  404.     ld    a,(de)        ;get user number
  405.     cp    10        ;less than 10
  406.     jp    nc,nozer2    ;no, no leading zero needed
  407.     ld    a,'0'
  408.     call    sout##
  409.     ld    a,(de)        ;get number again
  410. nozer2:    call    safdc##        ;print user number
  411.     ld    a,':'
  412.     call    sout##
  413.     inc    de        ;point to file name
  414.     call    sfn3##        ;print it
  415.     ld    a,(sctlfl##)    ;get switched output flag
  416.     bit    7,a        ;printer active?
  417.     jp    z,nptag        ;nope, don't tag cluster number onto report
  418.     ld    hl,tagstr    ;address of tag string
  419.     call    lpstr##        ;send to printer
  420.     ld    hl,(clnum)    ;get cluster number
  421.     call    lhldc##        ;send to printer
  422.     ld    a,'>'
  423.     call    lout##
  424.     call    lcrlf##        ;newline
  425. nptag:    ld    a,(qflg)
  426.     or    a        ;quiet mode active?
  427.     jp    nz,noscr3    ;yes, jump around cluster string printing
  428.     call    crlf##        ;move to new line first
  429.     ld    hl,clstr    ;print "Cluster: " string again
  430.     call    pstr##
  431.     jp    nctag
  432. noscr3:    ld    hl,tagstr    ;address of tag string
  433.     call    pstr##        ;send to console
  434.     ld    hl,(clnum)    ;get cluster number
  435.     call    phldc##        ;send to console
  436.     ld    a,'>'
  437.     call    cout##
  438.     call    crlf##        ;newline
  439. nctag:    ld    hl,(xclu)    ;get number of crosslinkings
  440.     inc    hl        ;one more now
  441.     ld    (xclu),hl    ;update number
  442.     pop    bc
  443.     pop    hl        ;restore registers
  444.     ret
  445. ;
  446. ; Various strings used within the program
  447. ;
  448. sizms:    db    'Please indicate a drive where a ',0
  449. sizms1:    db    'k temporary file can be placed.',cr,lf
  450.     db    'Do not use the drive being checked out.',cr,lf
  451.     db    'Drive name: ',0
  452.  
  453. ptrms1:    db    'Send crosslink warnings to printer? ',0
  454.  
  455. tagstr:    db    ' <on cluster: ',0
  456.  
  457. str1:    db    ' cross-linked cluster',0
  458. str2:    db    ' detected.',cr,lf,0
  459.  
  460. xlmsg1:    db    ' <crosslinked with> ',0
  461.  
  462. clstr:    db    'Cluster:      ',0
  463.  
  464. wofail:    db    cr,lf,bel,'Unable to open workfile on selected drive.'
  465.     db    cr,lf,cr,lf,0
  466.  
  467. hello:    db    cr,lf,'XLINK v',major+30H,'.',minor+30H,cr,lf,cr,lf,0
  468.  
  469. ;
  470. ; special FCB with '?' in drive select position (see BDOS function 17)
  471. ;
  472. tgtfcb:    db    '????????????',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  473. ;
  474. ; FCB for workfile
  475. ;
  476. wrkfcb:    db    0,'XLNAM   WRK',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  477.  
  478.  
  479.     dseg
  480.  
  481. bmap:    ds    2        ;address of start of bit-map
  482. bptr:    ds    2        ;bitmap pointer
  483. brec:    ds    2        ;number of record in workfile buffer
  484. clnum:    ds    2        ;cluster number
  485. du:    ds    2        ;drive/user of test drive
  486. roff:    ds    1        ;offset index into workfile
  487. rcrd:    ds    2        ;record number of workfile
  488. size:    ds    1        ;flag showing size of cluster numbers
  489. tfcb:    ds    2        ;pointer to head of current directory entry
  490. wdu:    ds    2        ;drive/user of workfile
  491. wfcb:    ds    2        ;pointer to head of crossed directory entry
  492. xclu:    ds    2        ;number of crosslinkings detected
  493.  
  494. wbuff:    ds    128        ;buffer area for workfile
  495.  
  496. xbuff:    ds    128        ;aux file buffer for workfile
  497.  
  498. ;
  499. ; the following storage definitions -must not- be re-arranged.
  500. ;
  501. locdpb:
  502. spt:    ds    2        ;number of 128-byte sectors per track
  503. bsh:    ds    1        ;block shift factor
  504. blm:    ds    1        ;block mask
  505. exm:    ds    1        ;extent mask
  506. dsm:    ds    2        ;higest cluster (block) number
  507. drm:    ds    2        ;maximum number of directory entries
  508. al0:    ds    1        ;directory allocation block map - first byte
  509. al1:    ds    1        ;directory allocation block map - second byte
  510. cks:    ds    2        ;size of directory check vector
  511. off:    ds    2        ;number of reserved tracks
  512. ; --- end of un-re-arrangable area ---
  513.  
  514.  
  515.     end
  516.