home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 22 / AACD 22.iso / AACD / Utilities / MountDos12 / MountDos.e < prev    next >
Encoding:
Text File  |  2000-12-02  |  20.2 KB  |  738 lines

  1. OPT REG=5
  2. OPT PREPROCESS
  3. OPT OSVERSION=37
  4.  
  5. /*
  6.  * MS-Dos partitiontable lister and Cross-Dos mounter for PC-HD's.
  7.  *
  8.  *
  9.  * v1.0: (c) K.P. van Beem (patrick@aobh.xs4all.nl or 2:280/464.2)
  10.  * v1.1 - v1.2: (c) Harry "Piru" Sintonen (sintonen@iki.fi)
  11.  *
  12.  * Based on information gained from the source of the Linux FDisk, by
  13.  * A. V. Le Blanc (LeBlanc@mcc.ac.uk).
  14.  * This program is free software.  You can redistribute it and/or
  15.  * modify it under the terms of the GNU General Public License as
  16.  * published by the Free Software Foundation.
  17.  *
  18.  * Version 1.0, 28-1-96, Initial version.
  19.  * Version 1.1, 31-7-00, Fixed tempfile problems. Fixed QUIET-option
  20.  * related memory loss. Blindly assumed String() always succeed,
  21.  * crashed if it didn't. Added custom error message for
  22.  * 'No disk in the drive' and 'Block len not supported' ioerr cases.
  23.  * Version 1.2, 2-12-00, Added dozens of new partition identifiers.
  24.  * Compacted the list output a bit. Now always add 'maxtransfer' to
  25.  * mountlist to prevent problems, default $fffe00. Added 32-bit FAT
  26.  * support with fat95. Changed BufMemType from MEMF_ANY to MEMF_PUBLIC.
  27.  * Added 'buffers' to mountlist, default 20. Added MAXTRANSFER,
  28.  * BUFFERS, FAT95 and INCLHIDDEN options. Fixed a deadly bug from
  29.  * Workbench startup I introduced in v1.1, oops.
  30.  */
  31.  
  32. #define VERSION '$VER: MountDos 1.2 (2.12.00) PD, (c) Harry "Piru" Sintonen.\n'
  33.  
  34. MODULE 'devices/trackdisk', 'exec/io', 'exec/ports'
  35. MODULE 'dos/dos', 'dos/dostags'
  36. MODULE 'utility/tagitem'
  37. MODULE 'icon', 'workbench/workbench', 'workbench/startup'
  38.  
  39.  
  40.  
  41. /******************* Globals **********************/
  42.  
  43. #define TEMPLATE       'DEVICE,UNIT/N,PREFIX,MAXTRANSFER,BUFFERS/N,FAT95/S,INCLHIDDEN/S,LIST/S,GENERATE/S,MOUNT/S,QUIET/S'
  44. #define ARG_DEVICE      arg_ptrs[0]
  45. #define ARG_UNIT        arg_ptrs[1]
  46. #define ARG_PREFIX      arg_ptrs[2]
  47. #define ARG_MAXTRANSFER arg_ptrs[3]
  48. #define ARG_BUFFERS     arg_ptrs[4]
  49. #define ARG_FAT95       arg_ptrs[5]
  50. #define ARG_INCLHIDDEN  arg_ptrs[6]
  51. #define ARG_LIST        arg_ptrs[7]
  52. #define ARG_GENERATE    arg_ptrs[8]
  53. #define ARG_MOUNT       arg_ptrs[9]
  54. #define ARG_QUIET       arg_ptrs[10]
  55. #define NUMARGS                  11
  56.  
  57. #define EXTENDED          $5
  58. #define EXTENDED32        $f
  59. #define SECTOR_SIZE       512
  60. #define PART_TABLE_FLAG   $55AA
  61. -> Actually $AA55, but ix86's are little endian and we're not.
  62.  
  63. -> Byte values. Highest two bits of sector are added to cylinder.
  64. #define SECTOR(s)     (s AND $3F)
  65. #define CYLINDER(s,c) (c OR Shl(s AND $C0,2))
  66.  
  67.  
  68. -> This is how an MS-Dos partition entry looks like:
  69. OBJECT partition
  70.   boot_ind    :CHAR   -> 0x80 - active
  71.   head        :CHAR   -> starting head
  72.   sector      :CHAR   -> starting sector
  73.   cyl         :CHAR   -> starting cylinder
  74.   sys_ind     :CHAR   -> What partition type
  75.   end_head    :CHAR   -> end head
  76.   end_sector  :CHAR   -> end sector
  77.   end_cyl     :CHAR   -> end cylinder
  78.   start_sect  :LONG   -> starting sector counting from 0
  79.   nr_sects    :LONG   -> nr of sectors in partition
  80. ENDOBJECT
  81.  
  82. -> Global return-code
  83. DEF rc       = RETURN_OK            -> Exceptionhandler will correct this.
  84.  
  85. -> Program arguments
  86. DEF rargs      = NIL
  87. DEF arg_ptrs   = NIL : PTR TO LONG
  88. DEF device, unit                    -> Device and unit we work on
  89. DEF prefix
  90. DEF maxtransfer, buffers
  91.  
  92. -> Device handling
  93. DEF tio      = NIL :PTR TO ioexttd  -> Trackdisk io blok.
  94.  
  95. -> Count number of partitions found, for unique naming of mount-entries
  96. DEF dosparts, ndosparts
  97.  
  98.  
  99. /****************** Automatic exceptions **********************/
  100. -> What can go wrong...
  101. RAISE "CTLC"  IF CtrlC()             = TRUE,
  102.       "DEV"   IF OpenDevice()       <> NIL,
  103.       "DOS"   IF ReadArgs()          = NIL,
  104.       "IO"    IF DoIO()             <> NIL,
  105.       "LIB"   IF OpenLibrary()       = NIL,
  106.       "RES"   IF CreateIORequest()   = NIL,
  107.       "RES"   IF CreateMsgPort()     = NIL,
  108.       "STAC"  IF FreeStack()         < 1000
  109.  
  110.  
  111.  
  112. /****************** Main prog **********************/
  113.  
  114. PROC main() HANDLE
  115.  
  116.   -> Device handling
  117.   DEF msgport = NIL                 -> MsgPort for the trackdisk.device
  118.   DEF topen   = FALSE               -> Flag if the trackdisk.device is opened.
  119.  
  120.   -> WB args
  121.   DEF arg :PTR TO wbarg, dobj :PTR TO diskobject, wm :PTR TO wbstartup
  122.   DEF olddir, item
  123.  
  124.   DEF tmp
  125.  
  126.   -> Check the parameters we got, first, initial and default values.
  127.   NEW arg_ptrs[NUMARGS]
  128.   device := 'scsi.device'
  129.   prefix := ''
  130.   maxtransfer := $fffe00
  131.   buffers := 20
  132.  
  133.   IF wbmessage
  134.     -> Started from workbench
  135.     iconbase  := OpenLibrary('icon.library', 37)
  136.     wm        := wbmessage
  137.     arg       := wm.arglist
  138.     IF wm.numargs > 1 THEN arg++        -> We are called with a project.
  139.     olddir    := CurrentDir(arg.lock)
  140.     dobj      := GetDiskObject(arg.name)
  141.     IF dobj
  142.       IF FindToolType(dobj.tooltypes,'FAT95')      THEN ARG_FAT95      := TRUE
  143.       IF FindToolType(dobj.tooltypes,'INCLHIDDEN') THEN ARG_INCLHIDDEN := TRUE
  144.       IF FindToolType(dobj.tooltypes,'LIST')       THEN ARG_LIST       := TRUE
  145.       IF FindToolType(dobj.tooltypes,'GENERATE')   THEN ARG_GENERATE   := TRUE
  146.       IF FindToolType(dobj.tooltypes,'MOUNT')      THEN ARG_MOUNT      := TRUE
  147.       IF FindToolType(dobj.tooltypes,'QUIET')      THEN ARG_QUIET      := TRUE
  148.  
  149.       item := FindToolType(dobj.tooltypes,'DEVICE')
  150.       IF item
  151.         tmp := String(StrLen(item))
  152.         IF tmp
  153.           StrCopy(tmp, item)
  154.           device := tmp
  155.         ELSE
  156.           device := 'out_of_memory'
  157.         ENDIF
  158.       ENDIF
  159.  
  160.       item := FindToolType(dobj.tooltypes,'UNIT')
  161.       IF item THEN unit := eVal(item)
  162.  
  163.       item := FindToolType(dobj.tooltypes,'MAXTRANSFER')
  164.       IF item THEN maxtransfer := eVal(item)
  165.  
  166.       item := FindToolType(dobj.tooltypes,'BUFFERS')
  167.       IF item THEN buffers := eVal(item)
  168.  
  169.       item := FindToolType(dobj.tooltypes,'PREFIX')
  170.       IF item
  171.         tmp := String(StrLen(item))
  172.         IF tmp
  173.           StrCopy(tmp, item)
  174.           prefix := tmp
  175.         ENDIF
  176.       ENDIF
  177.  
  178.       FreeDiskObject(dobj)
  179.     ENDIF
  180.     CurrentDir(olddir)
  181.     -> be careful, code above must not throw exception
  182.     CloseLibrary(iconbase)
  183.   ELSE
  184.     -> Started from CLI
  185.     rargs  := ReadArgs(TEMPLATE, arg_ptrs, NIL)
  186.     IF ARG_DEVICE      THEN device := ARG_DEVICE
  187.     IF ARG_UNIT        THEN unit   := Long(ARG_UNIT)
  188.     IF ARG_PREFIX      THEN prefix := ARG_PREFIX
  189.     IF ARG_MAXTRANSFER THEN maxtransfer := eVal(ARG_MAXTRANSFER)
  190.     IF ARG_BUFFERS     THEN buffers := Long(ARG_BUFFERS)
  191.   ENDIF
  192.  
  193.   -> No options?
  194.   IF (ARG_GENERATE=0) AND (ARG_MOUNT=0) AND (ARG_LIST=0)
  195.     PrintF(VERSION+6)
  196.     PrintF('Type: ''MountDos ?'' for an option summary.\n')
  197.     Raise(0)
  198.   ENDIF
  199.  
  200.   -> Validate options
  201.   IF (buffers < 20) THEN buffers := 20
  202.   IF (maxtransfer < $200) THEN maxtransfer := $200
  203.  
  204.   -> Redirect output if option quiet is specified
  205.   IF (ARG_QUIET = TRUE)
  206.     tmp := Open('NIL:', MODE_NEWFILE)
  207.     IF tmp
  208.       -> bugfix: Old conout was never closed in v1.0
  209.       Close(conout)
  210.       conout := stdout := tmp
  211.     ENDIF
  212.   ENDIF
  213.  
  214.   -> Trackdisk initialisation
  215.   msgport := CreateMsgPort()
  216.   tio     := CreateIORequest(msgport, SIZEOF ioexttd)
  217.   OpenDevice(device, unit, tio, 0)
  218.   topen := TRUE
  219.  
  220.   -> Actions to perform <-
  221.  
  222.   IF ARG_LIST
  223.     list_table()
  224.   ENDIF
  225.  
  226.   IF ARG_GENERATE
  227.     dosparts := ndosparts := 0
  228.     generate(stdout)
  229.   ENDIF
  230.  
  231.   IF ARG_MOUNT
  232.     mount()
  233.   ENDIF
  234.  
  235.  
  236. EXCEPT DO
  237.  
  238.   /* Inspect the error (if any) */
  239.   IF exception
  240.     rc := RETURN_FAIL
  241.     SELECT exception
  242.       CASE "DEV"
  243.         PrintF('Unable to open device ''\s'', unit \d.\n', device, unit)
  244.       CASE "DOS"
  245.         PrintFault(IoErr(), NIL)
  246.       CASE "CTLC"
  247.         PrintF('Ctrl-C detected.\n')
  248.       CASE "IO"
  249.         tmp := tio.iostd.error
  250.         SELECT tmp
  251.           CASE $fc  -> -4
  252.             PrintF('Block len not supported (CD-ROM?)\n')
  253.           CASE TDERR_DISKCHANGED
  254.             PrintF('No disk in the drive\n')
  255.             rc := RETURN_WARN
  256.           DEFAULT
  257.             PrintF('Device IO-error $\h.\n', tio.iostd.error)
  258.         ENDSELECT
  259.       CASE "LIB"
  260.         PrintF('Unable to open a needed library.\n')
  261.       CASE "MEM"
  262.         PrintF('Unable to allocate memory.\n')
  263.       CASE "RES"
  264.         PrintF('Unable to allocate needed resources.\n')
  265.       CASE "STAC"
  266.         PrintF('Stack overflow.\n')
  267.       DEFAULT
  268.         PrintF('Unknown exception: $\h.\n', exception)
  269.     ENDSELECT
  270.   ENDIF
  271.  
  272.   /* Clean-up */
  273.   IF topen          THEN CloseDevice    (tio)
  274.   IF tio            THEN DeleteIORequest(tio)
  275.   IF msgport        THEN DeleteMsgPort  (msgport)
  276.  
  277.   IF rargs          THEN FreeArgs       (rargs)
  278.  
  279. ENDPROC rc
  280.  
  281.  
  282. /************ Allow 0x and 0X hex notation with Val() *************/
  283. PROC eVal(str)
  284.   DEF len, tstr
  285.  
  286.   str := TrimStr(str)
  287.   len := StrLen(str)
  288.   IF len > 2
  289.     IF (str[0] = "0") AND ((str[1] = "x") OR (str[1] = "X"))
  290.       IF (tstr := String(len))
  291.         StringF(tstr, '$\s', str + 2)
  292.         len := Val(tstr)
  293.         Dispose(tstr)
  294.         RETURN len
  295.       ENDIF
  296.     ENDIF
  297.   ENDIF
  298. ENDPROC Val(str)
  299.  
  300.  
  301. /************ Read a partition-table block from disk *************/
  302. PROC readblock(buffer, block)
  303.  
  304.   tio.iostd.command   := CMD_READ
  305.   tio.iostd.data      := buffer
  306.   tio.iostd.length    := SECTOR_SIZE
  307.   tio.iostd.offset    := Mul(block,SECTOR_SIZE)
  308.   tio.iostd.flags     := IOF_QUICK
  309.   DoIO(tio)
  310.  
  311.   -> Check table ID
  312.   IF Int(buffer + $01FE) <> PART_TABLE_FLAG
  313.     PrintF('WARNING: Invalid table flag $\z\h[4].\n', Int(buffer + $01FE))
  314.     rc := RETURN_WARN
  315.   ENDIF
  316.  
  317. ENDPROC
  318.  
  319.  
  320.  
  321. /************ Auto-mount dos-partitions ************
  322.  * Generate the mountlist-entries in a file and call the mount
  323.  * command to mount each dos-partition in it.
  324.  */
  325. PROC mount() HANDLE
  326.   DEF cnt, tmpfh = 0, tmp, tmpname[20] :STRING
  327.   DEF command[80] :STRING
  328.  
  329.   -> Generate `random' temp filename. Prevent clash if
  330.   -> multiple mountdos instances are run simultanously.
  331.   StringF(tmpname, 'T:MDTML\h', FindTask(NIL))
  332.  
  333.   tmpfh := Open(tmpname, MODE_NEWFILE)
  334.   IF tmpfh = NIL
  335.     PrintF('Unable to create a temporary mountlist.\n')
  336.     rc := RETURN_ERROR
  337.     RETURN
  338.   ENDIF
  339.  
  340.   dosparts := ndosparts := 0
  341.   generate(tmpfh, 0, TRUE)
  342.   Close(tmpfh)
  343.   tmpfh:=0
  344.  
  345.   FOR cnt := 1 TO dosparts
  346.     CtrlC()                       -> User may want to cancel the mount-procedure
  347.     PrintF('Mounting \sMD\d\d:\n', prefix, unit, cnt)
  348.     StringF(command,'Mount \sMD\d\d: FROM \s', prefix, unit, cnt, tmpname)
  349.     tmp := SystemTagList(command, [SYS_OUTPUT, stdout, TAG_DONE])
  350.     IF tmp > rc THEN rc := tmp    -> Copy highest return-code
  351.   ENDFOR
  352.  
  353. EXCEPT DO
  354.  
  355.   -> bugfix: In v1.0 if exception was raised inside generate()
  356.   -> the temporaty mountlist filehandle was left unclosed. This
  357.   -> prevented the DeleteFile() call from succeeding, and
  358.   -> additionally caused further MountDos MOUNT calls to fail
  359.   -> since Open('T:MountDosTmpMountlist',MODE_NEWFILE) failed.
  360.   IF tmpfh
  361.     Close(tmpfh)
  362.   ENDIF
  363.  
  364.   DeleteFile(tmpname)
  365.   ReThrow()
  366.  
  367. ENDPROC
  368.  
  369.  
  370.  
  371. /************ Generate mountlist-entries for partition chain ************/
  372. -> 'dosonly' indicates only dos-partitions should be generated.
  373.  
  374. PROC generate(fh, block=0, dosonly=FALSE)
  375.   DEF cnt, bpt, lowcyl, highcyl, isdos, ind
  376.  
  377.   -> Partition table
  378.   DEF buffer[SECTOR_SIZE] : ARRAY OF CHAR
  379.   DEF p:PTR TO partition   -> Pointer to the partition table
  380.  
  381.   -> Recursive function, check Ctrl-C and stack (uses auto-exceptions).
  382.   FreeStack()
  383.   CtrlC()
  384.  
  385.   -> Read partition-table block
  386.   readblock(buffer, block)
  387.   p := buffer + $01BE
  388.  
  389.   FOR cnt := 1 TO 4
  390.  
  391.     -> Swap 'Intel'-values:
  392.     p.start_sect := swapL(p.start_sect)
  393.     p.nr_sects   := swapL(p.nr_sects)
  394.  
  395.  
  396.     ind := p.sys_ind
  397.     IF ARG_INCLHIDDEN
  398.       -> "Make" hidden partitions visible.
  399.       ind := ind AND $EF
  400.     ENDIF
  401.  
  402.  
  403.     -> Can this partition be mounted or not ?
  404.  
  405.     IF ARG_FAT95
  406.  
  407.       -> fat95 support $1, $4, $6, $b, $c, $e
  408.       IF (ind = $1) OR (ind = $4) OR (ind = $6) OR
  409.       (ind = $b) OR (ind = $c) OR (ind = $e)
  410.  
  411.         INC dosparts
  412.         isdos := TRUE
  413.       ELSE
  414.         INC ndosparts
  415.         isdos := FALSE
  416.       ENDIF
  417.  
  418.     ELSE
  419.  
  420.       -> crossdosfilesystem support $1, $4 and $6
  421.       IF (ind = $1) OR (ind = $4) OR (ind = $6)
  422.         INC dosparts
  423.         isdos := TRUE
  424.       ELSE
  425.         INC ndosparts
  426.         isdos := FALSE
  427.       ENDIF
  428.  
  429.     ENDIF
  430.  
  431.     lowcyl  := p.start_sect + block
  432.     highcyl := lowcyl + p.nr_sects + block
  433.     lowcyl, highcyl, bpt := smaller(lowcyl, highcyl)
  434.  
  435.     -> Note: Extended cannot be hidden.
  436.     IF  (p.sys_ind <> 0) AND (p.sys_ind <> EXTENDED) AND
  437.     (p.sys_ind <> EXTENDED32) AND
  438.     ( (dosonly AND isdos) OR Not(dosonly) )
  439.  
  440.       IF ARG_FAT95
  441.  
  442.         VfPrintf(fh,
  443.           '\s\s\d\d:\n'+
  444.           'FileSystem       = \s\n'+
  445.           'Device           = \s\n'+
  446.           'Unit             = \d\n'+
  447.           'Flags            = 1\n'+
  448.           'Surfaces         = 1\n'+
  449.           'BlocksPerTrack   = \d\n'+
  450.           'MaxTransfer      = 0x\h\n'+
  451.           'Reserved         = 0\n'+
  452.           'LowCyl           = \d\n'+
  453.           'HighCyl          = \d\n'+
  454.           'Buffers          = \d\n'+
  455.           'BufMemType       = 1\n'+
  456.           'StackSize        = 2048\n'+
  457.           'Priority         = 10\n'+
  458.           'GlobVec          = -1\n'+
  459.           'DosType          = \s\n'+
  460.           'Activate         = 1\n'+
  461.           '#\n\n',
  462.           [
  463.           prefix,
  464.           IF isdos THEN 'MD'         ELSE 'ND', unit,
  465.           IF isdos THEN dosparts     ELSE ndosparts,
  466.           IF isdos THEN 'L:fat95' ELSE systype(p.sys_ind),  -> Show real type, even if INCLHIDEN!
  467.           device, unit, bpt,
  468.           maxtransfer,
  469.           lowcyl, highcyl - 1,
  470.           buffers,
  471.           IF isdos THEN '0x46415401' ELSE '?'
  472.           ]:LONG
  473.         )
  474.  
  475.       ELSE
  476.  
  477.         VfPrintf(fh,
  478.           '\s\s\d\d:\n'+
  479.           'FileSystem       = \s\n'+
  480.           'Device           = \s\n'+
  481.           'Unit             = \d\n'+
  482.           'Surfaces         = 1\n'+
  483.           'BlocksPerTrack   = \d\n'+
  484.           'MaxTransfer      = 0x\h\n'+
  485.           'Reserved         = 0\n'+
  486.           'LowCyl           = \d\n'+
  487.           'HighCyl          = \d\n'+
  488.           'Buffers          = \d\n'+
  489.           'BufMemType       = 1\n'+
  490.           'StackSize        = 2048\n'+
  491.           'Priority         = 10\n'+
  492.           'GlobVec          = -1\n'+
  493.           'DosType          = \s\n'+
  494.           'Activate         = 1\n'+
  495.           '#\n\n',
  496.           [
  497.           prefix,
  498.           IF isdos THEN 'MD'         ELSE 'ND', unit,
  499.           IF isdos THEN dosparts     ELSE ndosparts,
  500.           IF isdos THEN 'L:CrossDOSFileSystem' ELSE systype(p.sys_ind),  -> Show real type, even if INCLHIDEN!
  501.           device, unit, bpt,
  502.           maxtransfer,
  503.           lowcyl, highcyl - 1,
  504.           buffers,
  505.           IF isdos THEN '0x4D534400' ELSE '?'
  506.           ]:LONG
  507.         )
  508.       ENDIF
  509.  
  510.     ENDIF
  511.  
  512.     -> Note: Extended cannot be hidden.
  513.     IF ((p.sys_ind = EXTENDED) OR (p.sys_ind = EXTENDED32)) AND
  514.     (p.start_sect <> 0)
  515.       -> Recursive call of this funtion.
  516.       generate(fh, p.start_sect + block, dosonly)
  517.     ENDIF
  518.  
  519.     p++
  520.   ENDFOR
  521.  
  522. ENDPROC
  523.  
  524.  
  525.  
  526. /************ Shows the contents of an partition chain. ************/
  527.  
  528. PROC list_table(block=0)
  529.   DEF cnt
  530.  
  531.   -> Partition table
  532.   DEF buffer[SECTOR_SIZE] : ARRAY OF CHAR
  533.   DEF p:PTR TO partition   -> Pointer to the partition table
  534.   DEF megs, size[8]:STRING
  535.  
  536.   -> Recursive function, check Ctrl-C and stack (uses auto-exceptions).
  537.   FreeStack()
  538.   CtrlC()
  539.  
  540.   -> Read partition-table block
  541.   readblock(buffer, block)
  542.   p := buffer + $01BE
  543.  
  544.   PrintF('     Start:         End:             Start  Number of\n'+
  545.          'boot Head Cyl. Sect Head Cyl. Sect   Sector Sectors     MB System\n')
  546.   FOR cnt := 1 TO 4
  547.     -> Swap 'Intel'-values:
  548.     p.start_sect := swapL(p.start_sect)
  549.     p.nr_sects   := swapL(p.nr_sects)
  550.  
  551.     megs := Div(p.nr_sects, ($100000/SECTOR_SIZE))
  552.     IF (megs < 10000)
  553.       StringF(size, '\d[4]', megs)
  554.     ELSE
  555.       -> at least 9GB
  556.       StringF(size, '\d[2]GB', Shr(megs, 10))
  557.     ENDIF
  558.  
  559.     PrintF('\d[1] \s \d[4]\d[5]\d[5] \d[4]\d[5]\d[5] \d[8] \d[9] \s \s\n',
  560.       cnt,        IF (p.boot_ind) THEN 'y ' ELSE 'n ',
  561.       p.head,     CYLINDER(p.sector, p.cyl),         SECTOR(p.sector),
  562.       p.end_head, CYLINDER(p.end_sector, p.end_cyl), SECTOR(p.end_sector),
  563.       IF p.start_sect = 0 THEN 0 ELSE p.start_sect + block, p.nr_sects,
  564.       size, systype(p.sys_ind)
  565.       )
  566.     p++
  567.   ENDFOR
  568.  
  569.   -> Check for extended partitions.
  570.   p := buffer + $01BE
  571.   FOR cnt := 1 TO 4
  572.  
  573.     IF (p.sys_ind = EXTENDED) OR (p.sys_ind = EXTENDED32)
  574.       IF p.start_sect = 0
  575.         PrintF('Bad offset in extended partition number \d.\n', cnt)
  576.       ELSE
  577.         -> Recursive call of this funtion.
  578.         PrintF('\nExtended partition at sector \d:\n', p.start_sect + block)
  579.         list_table(p.start_sect + block)
  580.       ENDIF
  581.     ENDIF
  582.  
  583.     p++
  584.   ENDFOR
  585.  
  586. ENDPROC
  587.  
  588.  
  589.  
  590. /********** System types of partitions *****************/
  591. PROC systype(t)
  592.   DEF stypes: PTR TO LONG
  593.  
  594.   stypes := [
  595.     $0, 'Empty',
  596.     $1, 'DOS FAT12',
  597.     $2, 'XENIX root',
  598.     $3, 'XENIX /usr',
  599.     $4, 'DOS FAT16 <32M',
  600.     EXTENDED, 'DOS Extended Partition',
  601.     $6, 'DOS FAT16 >=32M',
  602.     $7, 'OS/2 HPFS / Windows NT NTFS',         -> or QNX?
  603.     $8, 'AIX boot',
  604.     $9, 'AIX data',
  605.     $a, 'OS/2 Boot / OPUS',
  606.     $b, 'FAT32',
  607.     $c, 'FAT32, LBA',
  608.     $e, 'FAT16, LBA',
  609.     EXTENDED32, 'Extended Partition, LBA',
  610.     $10, 'OPUS',
  611.     $11, 'Hidden DOS FAT12',
  612.     $12, 'Compaq config partition',
  613.     $14, 'Hidden DOS FAT16 <32M',
  614.     $16, 'Hidden DOS FAT16 >=32M',
  615.     $17, 'Hidden OS/2 HPFS',
  616.     $18, 'AST Windows swapfile',
  617.     $1b, 'Hidden FAT32',
  618.     $1c, 'Hidden FAT32, LBA',
  619.     $1e, 'Hidden FAT16, LBA',
  620.     $24, 'NEC DOS 3.x',
  621.     $38, 'THEOS v3 2gb',
  622.     $39, 'THEOS v4 spanned',
  623.     $3a, 'THEOS v4 4gb',
  624.     $3b, 'THEOS v4 extended',
  625.     $3c, 'PartitionMagic recovery',
  626.     $40, 'Venix 80286',
  627.     $41, 'Linux / Personal RISC',
  628.     $42, 'Linux swap / Secure Filesystem',
  629.     $43, 'Linux native',
  630.     $4d, 'QNX4.x 2nd part',
  631.     $4e, 'QNX4.x 2nd part',
  632.     $4f, 'QNX4.x 3rd part',
  633.     $50, 'OnTrack Disk Manager',
  634.     $51, 'OnTrack Disk Manager / Novell',
  635.     $52, 'CP/M / Microport',
  636.     $53, 'Disk Manager 6.0 Aux3',
  637.     $54, 'Disk Manager 6.0 DDO',
  638.     $55, 'EZ-Drive',
  639.     $56, 'Golden Bow VFeature',
  640.     $5c, 'Priam EDisk',
  641.     $61, 'SpeedStor',
  642.     $63, 'Unix System V / Mach / GNU HURD',
  643.     $64, 'Novell Netware',
  644.     $65, 'Novell Netware',
  645.     $67, 'Novell',
  646.     $68, 'Novell',
  647.     $69, 'Novell',
  648.     $70, 'DiskSecure Multi-Boot',
  649.     $75, 'IBM PC/IX',
  650.     $80, 'Old MINIX',       -> Minix 1.4a and earlier
  651.     $81, 'Linux/MINIX',     -> Minix 1.4b and later
  652.     $82, 'Linux swap',
  653.     $83, 'Linux native',
  654.     $84, 'OS/2 hidden / Hibernation',
  655.     $85, 'Linux extended',
  656.     $86, 'NTFS volume set',
  657.     $87, 'NTFS volume set',
  658.     $93, 'Amoeba',
  659.     $94, 'Amoeba BBT',      -> (bad block table)
  660.     $99, 'DCE376 logical drive',
  661.     $a0, 'IBM Thinkpad hibernation / Phoenix NoteBIOS PM',
  662.     $a5, 'NetBSD, FreeBSD',
  663.     $a6, 'OpenBSD',
  664.     $a7, 'NEXTSTEP',
  665.     $aa, 'Olivetti FAT12 1.44Mb Service',
  666.     $b7, 'BSDI fs',
  667.     $b8, 'BSDI swap',
  668.     $c0, 'CTOS',
  669.     $c1, 'DRDOS/secured FAT16',
  670.     $c4, 'DRDOS/secured FAT16 <32M',
  671.     $c6, 'DRDOS/secured FAT16 >=32M / WinNT corrupted FAT16',
  672.     $c7, 'WinNT corrupted NTFS / Syrinx boot',
  673.     $d8, 'CP/M-86',
  674.     $db, 'CP/M',            -> or Concurrent DOS
  675.     $e1, 'DOS access / SpeedStor FAT12 extended',
  676.     $e3, 'DOS R/O / SpeedStor',
  677.     $e4, 'SpeedStor FAT16 extended',
  678.     $eb, 'BeOS',
  679.     $f1, 'SpeedStor',
  680.     $f2, 'DOS secondary',
  681.     $f4, 'SpeedStor large partition',
  682.     $fe, 'SpeedStor / LANstep / IBM PS/2 IML',
  683.     $ff, 'BBT'              -> (bad track table)
  684.   ]
  685.  
  686.   WHILE (t <= $FF) AND (t > stypes[])
  687.     stypes++
  688.     stypes++
  689.   ENDWHILE
  690.  
  691. ENDPROC IF (t = stypes[]) THEN stypes[1] ELSE 'Unknown'
  692.  
  693.  
  694.  
  695. /*** Some assembler routines for convenience... ***/
  696.  
  697.  
  698.  
  699. /******** Lower the values of lowcyl and highcyl. ********
  700.  * Some file-systems/devices can't handle high values for the cylinders
  701.  * (probably higher than 65536). So we try to keep them low, by increasing
  702.  * the number of cylinders.
  703.  */
  704.  
  705. PROC smaller(lowcyl, highcyl)
  706.   DEF     bpt
  707.  
  708.   MOVE.L  lowcyl,D0
  709.   MOVE.L  highcyl,D1
  710.  
  711.   MOVEQ   #1,D2           -> Sectors per track.
  712. smaller_iterate:
  713.   BTST    #0,D0
  714.   BNE.B   smaller_end
  715.   BTST    #0,D1
  716.   BNE.B   smaller_end
  717.   ADD.W   D2,D2
  718.   LSR.L   #1,D0
  719.   LSR.L   #1,D1
  720.   CMP.W   #$0800,D2       -> Don't overreact (or hang).
  721.   BLT.B   smaller_iterate
  722. smaller_end:
  723.  
  724.   MOVE.L  D0,lowcyl
  725.   MOVE.L  D1,highcyl
  726.   MOVE.L  D2,bpt
  727.  
  728. ENDPROC lowcyl, highcyl, bpt
  729.  
  730.  
  731. /****** Swap nibbles. Stupid Intel things... *********/
  732. PROC swapL(l)
  733.   MOVE.L  l,D0
  734.   ROR.W   #8,D0
  735.   SWAP    D0
  736.   ROR.W   #8,D0
  737. ENDPROC D0
  738.