home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff278.lzh / Frag / blocks.c < prev    next >
C/C++ Source or Header  |  1989-11-21  |  10KB  |  355 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.  
  9. #include <proto/exec.h>
  10. #include <proto/dos.h>
  11. #include <proto/graphics.h>
  12. #include <proto/intuition.h>
  13.  
  14. #include <stdio.h>
  15. #include <string.h>
  16.  
  17. #define error(s) { if (cli) Write(_Backstdout, (s), strlen(s)); }
  18.  
  19. #define USAGE "blocks <filename>\n"
  20. /* border sizes */
  21. #define XLEFT 2
  22. #define XRIGHT 2
  23. #define YTOP 10
  24. #define YBOTTOM 1
  25. /* Min & Max size for window */
  26. #define MAXHEIGHT (200 - YTOP - YBOTTOM)
  27. #define MAXWIDTH   (640 - XLEFT - XRIGHT)
  28. #define MINWIDTH 200
  29. #define MINHEIGHT 80
  30.  
  31. /* Spawn info */
  32. long _stack = 2000;
  33. char *_procname = "blocks";
  34. long _priority = 0;
  35. long _BackGroundIO = TRUE;
  36. extern long _Backstdout;
  37.  
  38. typedef struct FileInfoBlock FIB;
  39. typedef struct InfoData INFO;
  40.  
  41. extern struct IntuitionBase *IntuitionBase;
  42. extern struct GfxBase *GfxBase;
  43.  
  44. /* For io to device */
  45. struct MsgPort *port;
  46. struct IOStdReq *io;
  47. int DevOpen;
  48. /* Device info */
  49. long blk_size, blk_offset, root_blk, *secbuf;
  50. struct Window *win;
  51. /* size of window, of each block, etc */
  52. int xdiv, rectw, recth, width, height;
  53. int cli; /* Called from cli ? */
  54.  
  55. struct NewWindow newwin = {
  56.     0, 0,
  57.     0, 0,
  58.     -1, -1,
  59.     CLOSEWINDOW,
  60.     WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE | SMART_REFRESH | NOCAREREFRESH | RM
  61. BTRAP,
  62.     NULL,
  63.     NULL,
  64.     NULL,
  65.     NULL,
  66.     NULL,
  67.     0, 0, 0, 0,
  68.     WBENCHSCREEN
  69. };
  70.  
  71. /* Calculate coords on window for block 'block' on disk */
  72. void cvt_point(x, y, block)
  73. long *x, *y, block;
  74. {
  75.     *x = rectw * (block / (xdiv * height)) + XLEFT;
  76.     *y = recth * (block % height) + YTOP;
  77. }
  78.  
  79. /* Calc size, & open window */
  80. int prepare_window(fib, dev)
  81. struct FileInfoBlock *fib;
  82. struct DeviceNode *dev;
  83. {
  84.     /* Get disk characteristics */
  85.     struct FileSysStartupMsg *msg = (struct FileSysStartupMsg *)BADDR(dev->dn_S
  86. tartup);
  87.     ULONG *env = (ULONG *)BADDR(msg->fssm_Environ);
  88.     long blkscyl = env[DE_NUMHEADS] * env[DE_BLKSPERTRACK];
  89.     long numcyls = env[DE_UPPERCYL] - env[DE_LOWCYL] + 1;
  90.     long blks;
  91.     static char title[80];
  92.  
  93.     if (blkscyl <= MAXHEIGHT) /* Do a "nice" presentation, 1 cylinder per vert
  94. line */
  95.     {
  96.         height = blkscyl;
  97.         xdiv = (numcyls / MAXWIDTH + 1); /* Nb of cylinders per vertical line *
  98. /
  99.         width = numcyls / xdiv;
  100.     }
  101.     else /* Just squash em in */
  102.     {
  103.         blks = numcyls * blkscyl;
  104.         height = MAXHEIGHT;
  105.         xdiv = (blks / MAXHEIGHT + 1) / MAXWIDTH + 1;
  106.         width = (blks / MAXHEIGHT + 1) / xdiv;
  107.     }
  108.     /* Size of rect for 1 block */
  109.     rectw = MINWIDTH / width + 1;
  110.     recth = MINHEIGHT / height + 1;
  111.  
  112.     /* Open window */
  113.     sprintf(title, "File: %s, %ld blocks", fib->fib_FileName, fib->fib_NumBlock
  114. s);
  115.     newwin.Title = title;
  116.     newwin.Width = rectw * width + XLEFT + XRIGHT;
  117.     newwin.Height = recth * height + YTOP + YBOTTOM;
  118.  
  119.     if (win = OpenWindow(&newwin))
  120.     {
  121.         SetAPen(win->RPort, 2);
  122.         RectFill(win->RPort, XLEFT, YTOP, win->Width - XRIGHT - 1, win->Height
  123. - YBOTTOM - 1);
  124.         SetAPen(win->RPort, 3);
  125.         return TRUE;
  126.     }
  127.     return FALSE;
  128. }
  129.  
  130. /* bstr -> cstr */
  131. char *btoc_str(to, from)
  132. char *to;
  133. BSTR from;
  134. {
  135.     char *cstr = (char *)BADDR(from);
  136.  
  137.     strncpy(to, cstr + 1, *cstr);
  138.     to[*cstr] = '\0';
  139.  
  140.     return to;
  141. }
  142.  
  143. /* Reads sector at offset 'sector' from disk ('sector' must be a multiple of 51
  144. 2) */
  145. BYTE *ReadSector(sector, buf, len)
  146. long sector;
  147. BYTE *buf;
  148. long len;
  149. {
  150.     io->io_Command = CMD_READ;
  151.     io->io_Length = len;
  152.     io->io_Data = (APTR)buf;
  153.     io->io_Offset = sector;
  154.     DoIO((struct IORequest *)io);
  155.     return (io->io_Error == 0) ? buf : NULL;
  156. }
  157.  
  158. /* Find device by task */
  159. struct DeviceNode *TaskDevice(task)
  160. struct MsgPort *task;
  161. {
  162.     struct DeviceNode *devlist;
  163.  
  164.     Forbid();
  165.     devlist = (struct DeviceNode *)BADDR(((struct DosInfo *)BADDR(((struct Root
  166. Node *)(DOSBase->dl_Root))->rn_Info))->di_DevInfo);
  167.     for (;devlist; devlist = (struct DeviceNode *)BADDR(devlist->dn_Next))
  168.         if (devlist->dn_Type == DLT_DEVICE)
  169.         {
  170.             if (task == devlist->dn_Task) { Permit(); return devlist; }
  171.         }
  172.  
  173.     Permit();
  174.     return NULL;
  175. }
  176.  
  177. /* Reads block n of *partition* */
  178. void ReadBlock(n)
  179. long n;
  180. {
  181.     ReadSector((blk_offset + n) * blk_size * 4, secbuf, blk_size * 4);
  182. }
  183.  
  184. /* Get partition characteristics, open device */
  185. int setup(dev)
  186. struct DeviceNode *dev;
  187. {
  188.     char devname[32];
  189.     struct FileSysStartupMsg *msg = (struct FileSysStartupMsg *)BADDR(dev->dn_S
  190. tartup);
  191.     ULONG *env = (ULONG *)BADDR(msg->fssm_Environ);
  192.     long err;
  193.  
  194.     port = CreatePort(0, 0);
  195.     if (!port)
  196.     {
  197.         error("No port!\n");
  198.         return FALSE;
  199.     }
  200.     io = CreateStdIO(port);
  201.     if (!io)
  202.     {
  203.         error("No IO request!\n");
  204.         return FALSE;
  205.     }
  206.     err = OpenDevice(btoc_str(devname, msg->fssm_Device), msg->fssm_Unit, (stru
  207. ct IORequest *)io, msg->fssm_Flags);
  208.     if (err)
  209.     {
  210.         error("Device not opened\n");
  211.         return FALSE;
  212.     }
  213.     DevOpen = TRUE;
  214.     blk_size = env[DE_SIZEBLOCK];
  215.     blk_offset = env[DE_LOWCYL] * env[DE_BLKSPERTRACK] * env[DE_NUMHEADS];
  216.     root_blk = (env[DE_BLKSPERTRACK] * env[DE_NUMHEADS] * (env[DE_UPPERCYL] - e
  217. nv[DE_LOWCYL] + 1) - 1 + env[DE_RESERVEDBLKS]) / 2;
  218.     secbuf = (long *)AllocMem(4 * blk_size, env[DE_MEMBUFTYPE]);
  219.     if (!secbuf)
  220.     {
  221.         error("No sector buffer!\n");
  222.         return FALSE;
  223.     }
  224.     return TRUE;
  225. }
  226.  
  227. /* Close device */
  228. void release()
  229. {
  230.     if (secbuf) FreeMem((char *)secbuf, 4 * blk_size);
  231.     if (DevOpen) CloseDevice((struct IORequest *)io);
  232.     if (io) DeleteStdIO(io);
  233.     if (port) DeletePort(port);
  234. }
  235.  
  236. /* Displays blocks used by file described by fib */
  237. /* For OFS/FFS !!! */
  238. void get_blocks(fib, node, device)
  239. FIB *fib;
  240. struct DeviceList *node;
  241. struct DeviceNode *device;
  242. {
  243.     long key = fib->fib_DiskKey, data1 = blk_size - 51, used, i, x, y;
  244.     int quit;
  245.     struct IntuiMessage *msg;
  246.  
  247.     if (prepare_window(fib, device))
  248.     {
  249.         do {
  250.             Forbid();
  251.             if (device->dn_Task != node->dl_Task)
  252.             {
  253.                 error("Disk not in drive!\n");
  254.                 break;
  255.             }
  256.             ReadBlock(key); /* Read either File header or file list block */
  257.             Permit();
  258.             used = secbuf[2]; /* num blocks described here */
  259.             /* Draw blocks */
  260.             for (i = 0; i < used; i++)
  261.             {
  262.                 cvt_point(&x, &y, secbuf[data1 - i]);
  263.                 RectFill(win->RPort, x, y, x + rectw - 1, y + recth - 1);
  264.             }
  265.             /* Extension blocks ? */
  266.             key = secbuf[blk_size - 2];
  267.         } while (key != 0);
  268.  
  269.         /* Wait for window close */
  270.         quit = FALSE;
  271.         while (!quit)
  272.         {
  273.             WaitPort(win->UserPort);
  274.             while (msg = (struct IntuiMessage *)GetMsg(win->UserPort))
  275.             {
  276.                 quit = msg->Class == CLOSEWINDOW;
  277.                 ReplyMsg((struct Message *)msg);
  278.             }
  279.         }
  280.         CloseWindow(win);
  281.     }
  282. }
  283.  
  284. /* Display blocks used by file name */
  285. void disp_blocks(name)
  286. char *name;
  287. {
  288.     FIB *fib = (FIB *)AllocMem(sizeof(FIB), 0L);
  289.     INFO *info = (INFO *)AllocMem(sizeof(INFO), 0L);
  290.     BPTR lock = Lock(name, SHARED_LOCK);
  291.     struct DeviceList *node;
  292.     struct DeviceNode *device;
  293.  
  294.     if (fib && info)
  295.         if (lock)
  296.             if (Info(lock, info) && Examine(lock, fib))
  297.                 if (fib->fib_DirEntryType >= 0) error("Only for files!\n")
  298.                 else if (info->id_UnitNumber < 0) error("Only on OFS or FFS dis
  299. ks\n") /* Test detects RAM: ... */
  300.                 else
  301.                 {
  302.                     node = (struct DeviceList *)BADDR(info->id_VolumeNode);
  303.                     if (node == 0) error("Disk not in drive\n")
  304.                     else
  305.                         if (device = TaskDevice(node->dl_Task))
  306.                         {
  307.                             if (setup(device)) get_blocks(fib, node, device);
  308.                             release();
  309.                         }
  310.                         else error("Couldn't find disk's device!\n")
  311.                 }
  312.             else error("Couldn't get info on file\n")
  313.         else error("No such file\n")
  314.     else error("No memory !\n");
  315.  
  316.     if (lock) UnLock(lock);
  317.     if (fib) FreeMem((char *)fib, sizeof(FIB));
  318.     if (info) FreeMem((char *)info, sizeof(INFO));
  319. }
  320.  
  321. /* Display blocks used by files passed as parms
  322.    Works from WB or CLI */
  323. void main(argc, argv)
  324. int argc;
  325. char **argv;
  326. {
  327.     int i;
  328.  
  329.     cli = (argc != 0);
  330.  
  331.     if (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library"
  332. , 0L))
  333.         if (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0L))
  334.             if (argc == 0) /* WB */
  335.             {
  336.                 struct WBStartup *msg = (struct WBStartup *)argv;
  337.  
  338.                 for (i = 1; i < msg->sm_NumArgs; i++)
  339.                     if (msg->sm_ArgList[i].wa_Name[0] != '\0') /* A dir */
  340.                     {
  341.                         CurrentDir(msg->sm_ArgList[i].wa_Lock);
  342.                         disp_blocks(msg->sm_ArgList[i].wa_Name);
  343.                     }
  344.             }
  345.             else if (argc == 1) error(USAGE)
  346.             else
  347.                 for (i = 1; i < argc; i++) disp_blocks(argv[i]);
  348.         else error("No graphics library !\n")
  349.     else error("No intuition library !\n");
  350.  
  351.     if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
  352.     if (GfxBase) CloseLibrary((struct Library *)GfxBase);
  353.     if (_Backstdout) Close(_Backstdout);
  354. }
  355.