home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 316.lha / frag / free.c < prev    next >
C/C++ Source or Header  |  1989-12-05  |  11KB  |  377 lines

  1. #include <exec/types.h>
  2. #include <exec/io.h>
  3. #include <libraries/dos.h>
  4. #include <libraries/dosextens.h>
  5. #include <libraries/filehandler.h>
  6. #include <intuition/intuition.h>
  7. #include <workbench/startup.h>
  8. #include <devices/trackdisk.h>
  9.  
  10. #include <proto/exec.h>
  11. #include <proto/dos.h>
  12. #include <proto/graphics.h>
  13. #include <proto/intuition.h>
  14.  
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18.  
  19. #define error(s) { if (cli) Write(_Backstdout, (s), strlen(s)); }
  20.  
  21. /* border sizes, shouldn't be hard coded ... */
  22. #define XLEFT 2
  23. #define XRIGHT 2
  24. #define YTOP 10
  25. #define YBOTTOM 1
  26. /* Max/Min window size */
  27. #define MAXHEIGHT (200 - YTOP - YBOTTOM)
  28. #define MAXWIDTH   (640 - XLEFT - XRIGHT)
  29. #define MINWIDTH 200
  30. #define MINHEIGHT 80
  31.  
  32. /* Detach info */
  33. long _stack = 2000;
  34. char *_procname = "freeblks";
  35. long _priority = 0;
  36. long _BackGroundIO = TRUE;
  37. extern long _Backstdout;
  38.  
  39. typedef struct FileInfoBlock FIB;
  40. typedef struct InfoData INFO;
  41.  
  42. extern struct IntuitionBase *IntuitionBase;
  43. extern struct GfxBase *GfxBase;
  44.  
  45. /* Device access */
  46. struct MsgPort *port;
  47. struct IOStdReq *io;
  48. int DevOpen;
  49. /* Partition characteristics */
  50. long blk_size, blk_offset, root_blk, *secbuf, *secbuf2;
  51. struct Window *win;
  52. /* size of window, of each block, etc */
  53. int xdiv, rectw, recth, width, height;
  54. int cli;
  55.  
  56. struct NewWindow newwin = {
  57.     0, 0,
  58.     0, 0,
  59.     -1, -1,
  60.     CLOSEWINDOW,
  61.     WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE | SMART_REFRESH | NOCAREREFRESH | RM
  62. BTRAP,
  63.     NULL,
  64.     NULL,
  65.     NULL,
  66.     NULL,
  67.     NULL,
  68.     0, 0, 0, 0,
  69.     WBENCHSCREEN
  70. };
  71.  
  72. /* bcpl string -> C string */
  73. char *btoc_str(char *to, BSTR from)
  74. {
  75.     char *cstr = (char *)BADDR(from);
  76.  
  77.     strncpy(to, cstr + 1, *cstr);
  78.     to[*cstr] = '\0';
  79.  
  80.     return to;
  81. }
  82.  
  83. /* Calculate coords on window for block 'block' on disk */
  84. void cvt_point(long *x, long *y, long block)
  85. {
  86.     *x = rectw * (block / (xdiv * height)) + XLEFT;
  87.     *y = recth * (block % height) + YTOP;
  88. }
  89.  
  90. /* Calc size, & open window */
  91. int prepare_window(struct DeviceNode *dev)
  92. {
  93.     struct FileSysStartupMsg *msg = (struct FileSysStartupMsg *)BADDR(dev->dn_S
  94. tartup);
  95.     ULONG *env = (ULONG *)BADDR(msg->fssm_Environ);
  96.     long blkscyl = env[DE_NUMHEADS] * env[DE_BLKSPERTRACK];
  97.     long numcyls = env[DE_UPPERCYL] - env[DE_LOWCYL] + 1;
  98.     long blks;
  99.     static char title[80];
  100.  
  101.     if (blkscyl <= MAXHEIGHT) /* Do a "nice" presentation, 1 cylinder per vert
  102. line */
  103.     {
  104.         height = blkscyl;
  105.         xdiv = (numcyls / MAXWIDTH + 1); /* Nb of cylinders per vertical line *
  106. /
  107.         width = numcyls / xdiv;
  108.     }
  109.     else /* Just squash em in */
  110.     {
  111.         blks = numcyls * blkscyl;
  112.         height = MAXHEIGHT;
  113.         xdiv = (blks / MAXHEIGHT + 1) / MAXWIDTH + 1;
  114.         width = (blks / MAXHEIGHT + 1) / xdiv;
  115.     }
  116.     /* Size of rect for 1 block */
  117.     rectw = MINWIDTH / width + 1;
  118.     recth = MINHEIGHT / height + 1;
  119.  
  120.     /* Open window */
  121.     btoc_str(title, dev->dn_Name);
  122.     strcat(title, ":, free blocks");
  123.     newwin.Title = title;
  124.     newwin.Width = rectw * width + XLEFT + XRIGHT;
  125.     newwin.Height = recth * height + YTOP + YBOTTOM;
  126.  
  127.     if (win = OpenWindow(&newwin))
  128.     {
  129.         SetAPen(win->RPort, 2);
  130.         RectFill(win->RPort, XLEFT, YTOP, win->Width - XRIGHT - 1, win->Height
  131. - YBOTTOM - 1);
  132.         SetAPen(win->RPort, 3);
  133.         return TRUE;
  134.     }
  135.     return FALSE;
  136. }
  137.  
  138. /* Reads sector at offset 'sector' from disk ('sector' must be a multiple of 51
  139. 2) */
  140. BYTE *ReadSector(long sector, BYTE *buf, long len)
  141. {
  142.     io->io_Command = CMD_READ;
  143.     io->io_Length = len;
  144.     io->io_Data = (APTR)buf;
  145.     io->io_Offset = sector;
  146.     DoIO((struct IORequest *)io);
  147.     return (io->io_Error == 0) ? buf : NULL;
  148. }
  149.  
  150. /* Turn motor on/off */
  151. void Motor(int on)
  152. {
  153.     io->io_Command = TD_MOTOR;
  154.     io->io_Length = on;
  155.     DoIO((struct IORequest *)io);
  156. }
  157.  
  158. /* Find device by name */
  159. struct DeviceNode *FindDevice(char *name)
  160. {
  161.     struct DeviceNode *devlist;
  162.     int l = strlen(name), l2;
  163.     char *name2;
  164.  
  165.     Forbid();
  166.     devlist = (struct DeviceNode *)BADDR(((struct DosInfo *)BADDR(((struct Root
  167. Node *)(DOSBase->dl_Root))->rn_Info))->di_DevInfo);
  168.     for (;devlist; devlist = (struct DeviceNode *)BADDR(devlist->dn_Next))
  169.         if (devlist->dn_Type == DLT_DEVICE)
  170.         {
  171.             name2 = (char *)BADDR(devlist->dn_Name);
  172.             l2 = *name2;
  173.             if (l == l2 && strnicmp(name, name2 + 1, l) == 0) break;
  174.         }
  175.  
  176.     Permit();
  177.     return devlist;
  178. }
  179.  
  180. /* Find device by task */
  181. struct DeviceNode *TaskDevice(struct MsgPort *task)
  182. {
  183.     struct DeviceNode *devlist;
  184.  
  185.     Forbid();
  186.     devlist = (struct DeviceNode *)BADDR(((struct DosInfo *)BADDR(((struct Root
  187. Node *)(DOSBase->dl_Root))->rn_Info))->di_DevInfo);
  188.     for (;devlist; devlist = (struct DeviceNode *)BADDR(devlist->dn_Next))
  189.         if (devlist->dn_Type == DLT_DEVICE)
  190.         {
  191.             if (task == devlist->dn_Task) { Permit(); return devlist; }
  192.         }
  193.  
  194.     Permit();
  195.     return NULL;
  196. }
  197.  
  198. /* Reads block n of *partition* */
  199. BYTE *ReadBlock(long *buf, long n)
  200. {
  201.     return(ReadSector((blk_offset + n) * blk_size * 4, (BYTE *)buf, blk_size *
  202. 4));
  203. }
  204.  
  205. /* Get partition characteristics, open device */
  206. int setup(struct DeviceNode *dev)
  207. {
  208.     char devname[32];
  209.     struct FileSysStartupMsg *msg = (struct FileSysStartupMsg *)BADDR(dev->dn_S
  210. tartup);
  211.     ULONG *env = (ULONG *)BADDR(msg->fssm_Environ);
  212.     long err;
  213.  
  214.     port = CreatePort(0, 0);
  215.     if (!port)
  216.     {
  217.         error("No port!\n");
  218.         return FALSE;
  219.     }
  220.     io = CreateStdIO(port);
  221.     if (!io)
  222.     {
  223.         error("No IO request!\n");
  224.         return FALSE;
  225.     }
  226.     err = OpenDevice(btoc_str(devname, msg->fssm_Device), msg->fssm_Unit, (stru
  227. ct IORequest *)io, msg->fssm_Flags);
  228.     if (err)
  229.     {
  230.         error("Device not opened\n");
  231.         return FALSE;
  232.     }
  233.     DevOpen = TRUE;
  234.     blk_size = env[DE_SIZEBLOCK];
  235.     blk_offset = env[DE_LOWCYL] * env[DE_BLKSPERTRACK] * env[DE_NUMHEADS];
  236.     root_blk = (env[DE_BLKSPERTRACK] * env[DE_NUMHEADS] * (env[DE_UPPERCYL] - e
  237. nv[DE_LOWCYL] + 1) - 1 + env[DE_RESERVEDBLKS]) / 2;
  238.     secbuf = (long *)AllocMem(2 * 4 * blk_size, env[DE_MEMBUFTYPE]);
  239.     if (!secbuf)
  240.     {
  241.         error("No sector buffer!\n");
  242.         return FALSE;
  243.     }
  244.     secbuf2 = secbuf + blk_size;
  245.     return TRUE;
  246. }
  247.  
  248. /* Close device */
  249. void release(void)
  250. {
  251.     if (secbuf) FreeMem((char *)secbuf, 2 * 4 * blk_size);
  252.     if (DevOpen) CloseDevice((struct IORequest *)io);
  253.     if (io) DeleteStdIO(io);
  254.     if (port) DeletePort(port);
  255. }
  256.  
  257. /* Displays free blocks on device dev. For OFS/FFS !!! */
  258. void disp_free(struct DeviceNode *dev)
  259. {
  260.     struct FileSysStartupMsg *fmsg = (struct FileSysStartupMsg *)BADDR(dev->dn_
  261. Startup);
  262.     ULONG *env = (ULONG *)BADDR(fmsg->fssm_Environ);
  263.     int quit, bit;
  264.     struct IntuiMessage *msg;
  265.     long first, last, numblks, pos, i, blk, word, x, y;
  266.     int firstx, firsty, lastx, lasty;
  267.  
  268.     if (prepare_window(dev))
  269.     {
  270.         if (!ReadBlock(secbuf, root_blk)) goto diskerror;
  271.         first = blk_size - 49; last = blk_size - 24; /* extent of bitmap list *
  272. /
  273.         numblks = env[DE_NUMHEADS] * env[DE_BLKSPERTRACK] * (env[DE_UPPERCYL] -
  274.  env[DE_LOWCYL] + 1);
  275.         blk = env[DE_RESERVEDBLKS]; /* First block described in bitmap */
  276.         pos = first;
  277.         lasty = -recth - 1; firsty = -1;
  278.  
  279.         do {
  280.             if (pos == last) /* End of bitmap table list, read extension bitmap
  281.  table */
  282.             {
  283.                 if (!ReadBlock(secbuf, secbuf[last])) goto diskerror;
  284.                 pos = first = 0;
  285.                 last = blk_size - 1;
  286.             }
  287.             /* Read next bitmap sector */
  288.             if (!ReadBlock(secbuf2, secbuf[pos++])) goto diskerror;
  289.  
  290.             /* Display free blocks in it */
  291.             for (i = 1; blk != numblks && i < blk_size; i++)
  292.             {
  293.                 word = secbuf2[i];
  294.                 for (bit = 0; blk != numblks && bit < 32; bit++, blk++)
  295.                 {
  296.                     if (word & 1) /* Free sector */
  297.                     {
  298.                         cvt_point(&x, &y, blk);
  299.                         /* Speed up drawing (by a factor of 3 on HD), check
  300.                            for consecutive free blocks & draw them in one go */
  301.      
  302.                         if (y != lasty + recth || x != lastx)
  303.                         {
  304.                             /* Non consecutive blocks, draw */
  305.  
  306.                             if (firsty != -1)
  307.                                 RectFill(win->RPort, firstx, firsty, lastx + re
  308. ctw - 1, lasty + recth - 1);
  309.                             firstx = x; firsty = y;
  310.                         }
  311.                         lastx = x; lasty = y;
  312.                     }
  313.                     word >>= 1; /* next sector */
  314.                 }
  315.             }
  316.         } while (blk != numblks);
  317.         if (firsty != -1)
  318.             RectFill(win->RPort, firstx, firsty, lastx + rectw - 1, lasty + rec
  319. th - 1);
  320.         Motor(FALSE); /* Turn drive motor off */
  321.  
  322.         quit = FALSE;
  323.         while (!quit)
  324.         {
  325.             WaitPort(win->UserPort);
  326.             while (msg = (struct IntuiMessage *)GetMsg(win->UserPort))
  327.             {
  328.                 quit = msg->Class == CLOSEWINDOW;
  329.                 ReplyMsg((struct Message *)msg);
  330.             }
  331.         }
  332.         CloseWindow(win);
  333.     }
  334.     else error("Couldn't open window\n");
  335.     return;
  336.  
  337. diskerror:
  338.     CloseWindow(win);
  339.     error("Error reading disk\n");
  340. }
  341.  
  342. /* Display free blocks on partition passed as parm, from CLI only */
  343. void main(int argc, char **argv)
  344. {
  345.     struct DeviceNode *dev;
  346.  
  347.     cli = (argc != 0);
  348.  
  349.     if (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library"
  350. , 0L))
  351.         if (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0L))
  352.             if (argc != 2) error("Usage: free <device>\n")
  353.             else
  354.             {
  355.                 int l = strlen(argv[1]) - 1;
  356.  
  357.                 if (argv[1][l] != ':') error("Not a device spec!\n")
  358.                 else
  359.                 {
  360.                     argv[1][l] = '\0';
  361.                     dev = FindDevice(argv[1]);
  362.                     if (dev)
  363.                     {
  364.                         if (setup(dev)) disp_free(dev);
  365.                         release();
  366.                     }
  367.                     else error("No such device\n");
  368.                 }
  369.             }
  370.         else error("No graphics library !\n")
  371.     else error("No intuition library !\n");
  372.  
  373.     if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
  374.     if (GfxBase) CloseLibrary((struct Library *)GfxBase);
  375.     if (_Backstdout) Close(_Backstdout);
  376. }
  377.