home *** CD-ROM | disk | FTP | other *** search
- #include <exec/types.h>
- #include <exec/io.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #include <libraries/filehandler.h>
- #include <intuition/intuition.h>
- #include <workbench/startup.h>
-
- #include <proto/exec.h>
- #include <proto/dos.h>
- #include <proto/graphics.h>
- #include <proto/intuition.h>
-
- #include <stdio.h>
- #include <string.h>
-
- #define error(s) { if (cli) Write(_Backstdout, (s), strlen(s)); }
-
- #define USAGE "blocks <filename>\n"
- /* border sizes */
- #define XLEFT 2
- #define XRIGHT 2
- #define YTOP 10
- #define YBOTTOM 1
- /* Min & Max size for window */
- #define MAXHEIGHT (200 - YTOP - YBOTTOM)
- #define MAXWIDTH (640 - XLEFT - XRIGHT)
- #define MINWIDTH 200
- #define MINHEIGHT 80
-
- /* Spawn info */
- long _stack = 2000;
- char *_procname = "blocks";
- long _priority = 0;
- long _BackGroundIO = TRUE;
- extern long _Backstdout;
-
- typedef struct FileInfoBlock FIB;
- typedef struct InfoData INFO;
-
- extern struct IntuitionBase *IntuitionBase;
- extern struct GfxBase *GfxBase;
-
- /* For io to device */
- struct MsgPort *port;
- struct IOStdReq *io;
- int DevOpen;
- /* Device info */
- long blk_size, blk_offset, root_blk, *secbuf;
- struct Window *win;
- /* size of window, of each block, etc */
- int xdiv, rectw, recth, width, height;
- int cli; /* Called from cli ? */
-
- struct NewWindow newwin = {
- 0, 0,
- 0, 0,
- -1, -1,
- CLOSEWINDOW,
- WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE | SMART_REFRESH | NOCAREREFRESH | RM
- BTRAP,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- 0, 0, 0, 0,
- WBENCHSCREEN
- };
-
- /* Calculate coords on window for block 'block' on disk */
- void cvt_point(x, y, block)
- long *x, *y, block;
- {
- *x = rectw * (block / (xdiv * height)) + XLEFT;
- *y = recth * (block % height) + YTOP;
- }
-
- /* Calc size, & open window */
- int prepare_window(fib, dev)
- struct FileInfoBlock *fib;
- struct DeviceNode *dev;
- {
- /* Get disk characteristics */
- struct FileSysStartupMsg *msg = (struct FileSysStartupMsg *)BADDR(dev->dn_S
- tartup);
- ULONG *env = (ULONG *)BADDR(msg->fssm_Environ);
- long blkscyl = env[DE_NUMHEADS] * env[DE_BLKSPERTRACK];
- long numcyls = env[DE_UPPERCYL] - env[DE_LOWCYL] + 1;
- long blks;
- static char title[80];
-
- if (blkscyl <= MAXHEIGHT) /* Do a "nice" presentation, 1 cylinder per vert
- line */
- {
- height = blkscyl;
- xdiv = (numcyls / MAXWIDTH + 1); /* Nb of cylinders per vertical line *
- /
- width = numcyls / xdiv;
- }
- else /* Just squash em in */
- {
- blks = numcyls * blkscyl;
- height = MAXHEIGHT;
- xdiv = (blks / MAXHEIGHT + 1) / MAXWIDTH + 1;
- width = (blks / MAXHEIGHT + 1) / xdiv;
- }
- /* Size of rect for 1 block */
- rectw = MINWIDTH / width + 1;
- recth = MINHEIGHT / height + 1;
-
- /* Open window */
- sprintf(title, "File: %s, %ld blocks", fib->fib_FileName, fib->fib_NumBlock
- s);
- newwin.Title = title;
- newwin.Width = rectw * width + XLEFT + XRIGHT;
- newwin.Height = recth * height + YTOP + YBOTTOM;
-
- if (win = OpenWindow(&newwin))
- {
- SetAPen(win->RPort, 2);
- RectFill(win->RPort, XLEFT, YTOP, win->Width - XRIGHT - 1, win->Height
- - YBOTTOM - 1);
- SetAPen(win->RPort, 3);
- return TRUE;
- }
- return FALSE;
- }
-
- /* bstr -> cstr */
- char *btoc_str(to, from)
- char *to;
- BSTR from;
- {
- char *cstr = (char *)BADDR(from);
-
- strncpy(to, cstr + 1, *cstr);
- to[*cstr] = '\0';
-
- return to;
- }
-
- /* Reads sector at offset 'sector' from disk ('sector' must be a multiple of 51
- 2) */
- BYTE *ReadSector(sector, buf, len)
- long sector;
- BYTE *buf;
- long len;
- {
- io->io_Command = CMD_READ;
- io->io_Length = len;
- io->io_Data = (APTR)buf;
- io->io_Offset = sector;
- DoIO((struct IORequest *)io);
- return (io->io_Error == 0) ? buf : NULL;
- }
-
- /* Find device by task */
- struct DeviceNode *TaskDevice(task)
- struct MsgPort *task;
- {
- struct DeviceNode *devlist;
-
- Forbid();
- devlist = (struct DeviceNode *)BADDR(((struct DosInfo *)BADDR(((struct Root
- Node *)(DOSBase->dl_Root))->rn_Info))->di_DevInfo);
- for (;devlist; devlist = (struct DeviceNode *)BADDR(devlist->dn_Next))
- if (devlist->dn_Type == DLT_DEVICE)
- {
- if (task == devlist->dn_Task) { Permit(); return devlist; }
- }
-
- Permit();
- return NULL;
- }
-
- /* Reads block n of *partition* */
- void ReadBlock(n)
- long n;
- {
- ReadSector((blk_offset + n) * blk_size * 4, secbuf, blk_size * 4);
- }
-
- /* Get partition characteristics, open device */
- int setup(dev)
- struct DeviceNode *dev;
- {
- char devname[32];
- struct FileSysStartupMsg *msg = (struct FileSysStartupMsg *)BADDR(dev->dn_S
- tartup);
- ULONG *env = (ULONG *)BADDR(msg->fssm_Environ);
- long err;
-
- port = CreatePort(0, 0);
- if (!port)
- {
- error("No port!\n");
- return FALSE;
- }
- io = CreateStdIO(port);
- if (!io)
- {
- error("No IO request!\n");
- return FALSE;
- }
- err = OpenDevice(btoc_str(devname, msg->fssm_Device), msg->fssm_Unit, (stru
- ct IORequest *)io, msg->fssm_Flags);
- if (err)
- {
- error("Device not opened\n");
- return FALSE;
- }
- DevOpen = TRUE;
- blk_size = env[DE_SIZEBLOCK];
- blk_offset = env[DE_LOWCYL] * env[DE_BLKSPERTRACK] * env[DE_NUMHEADS];
- root_blk = (env[DE_BLKSPERTRACK] * env[DE_NUMHEADS] * (env[DE_UPPERCYL] - e
- nv[DE_LOWCYL] + 1) - 1 + env[DE_RESERVEDBLKS]) / 2;
- secbuf = (long *)AllocMem(4 * blk_size, env[DE_MEMBUFTYPE]);
- if (!secbuf)
- {
- error("No sector buffer!\n");
- return FALSE;
- }
- return TRUE;
- }
-
- /* Close device */
- void release()
- {
- if (secbuf) FreeMem((char *)secbuf, 4 * blk_size);
- if (DevOpen) CloseDevice((struct IORequest *)io);
- if (io) DeleteStdIO(io);
- if (port) DeletePort(port);
- }
-
- /* Displays blocks used by file described by fib */
- /* For OFS/FFS !!! */
- void get_blocks(fib, node, device)
- FIB *fib;
- struct DeviceList *node;
- struct DeviceNode *device;
- {
- long key = fib->fib_DiskKey, data1 = blk_size - 51, used, i, x, y;
- int quit;
- struct IntuiMessage *msg;
-
- if (prepare_window(fib, device))
- {
- do {
- Forbid();
- if (device->dn_Task != node->dl_Task)
- {
- error("Disk not in drive!\n");
- break;
- }
- ReadBlock(key); /* Read either File header or file list block */
- Permit();
- used = secbuf[2]; /* num blocks described here */
- /* Draw blocks */
- for (i = 0; i < used; i++)
- {
- cvt_point(&x, &y, secbuf[data1 - i]);
- RectFill(win->RPort, x, y, x + rectw - 1, y + recth - 1);
- }
- /* Extension blocks ? */
- key = secbuf[blk_size - 2];
- } while (key != 0);
-
- /* Wait for window close */
- quit = FALSE;
- while (!quit)
- {
- WaitPort(win->UserPort);
- while (msg = (struct IntuiMessage *)GetMsg(win->UserPort))
- {
- quit = msg->Class == CLOSEWINDOW;
- ReplyMsg((struct Message *)msg);
- }
- }
- CloseWindow(win);
- }
- }
-
- /* Display blocks used by file name */
- void disp_blocks(name)
- char *name;
- {
- FIB *fib = (FIB *)AllocMem(sizeof(FIB), 0L);
- INFO *info = (INFO *)AllocMem(sizeof(INFO), 0L);
- BPTR lock = Lock(name, SHARED_LOCK);
- struct DeviceList *node;
- struct DeviceNode *device;
-
- if (fib && info)
- if (lock)
- if (Info(lock, info) && Examine(lock, fib))
- if (fib->fib_DirEntryType >= 0) error("Only for files!\n")
- else if (info->id_UnitNumber < 0) error("Only on OFS or FFS dis
- ks\n") /* Test detects RAM: ... */
- else
- {
- node = (struct DeviceList *)BADDR(info->id_VolumeNode);
- if (node == 0) error("Disk not in drive\n")
- else
- if (device = TaskDevice(node->dl_Task))
- {
- if (setup(device)) get_blocks(fib, node, device);
- release();
- }
- else error("Couldn't find disk's device!\n")
- }
- else error("Couldn't get info on file\n")
- else error("No such file\n")
- else error("No memory !\n");
-
- if (lock) UnLock(lock);
- if (fib) FreeMem((char *)fib, sizeof(FIB));
- if (info) FreeMem((char *)info, sizeof(INFO));
- }
-
- /* Display blocks used by files passed as parms
- Works from WB or CLI */
- void main(argc, argv)
- int argc;
- char **argv;
- {
- int i;
-
- cli = (argc != 0);
-
- if (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library"
- , 0L))
- if (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0L))
- if (argc == 0) /* WB */
- {
- struct WBStartup *msg = (struct WBStartup *)argv;
-
- for (i = 1; i < msg->sm_NumArgs; i++)
- if (msg->sm_ArgList[i].wa_Name[0] != '\0') /* A dir */
- {
- CurrentDir(msg->sm_ArgList[i].wa_Lock);
- disp_blocks(msg->sm_ArgList[i].wa_Name);
- }
- }
- else if (argc == 1) error(USAGE)
- else
- for (i = 1; i < argc; i++) disp_blocks(argv[i]);
- else error("No graphics library !\n")
- else error("No intuition library !\n");
-
- if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
- if (GfxBase) CloseLibrary((struct Library *)GfxBase);
- if (_Backstdout) Close(_Backstdout);
- }
-