#include #include #include #include #include #include #include #include #include #include #include #include #include #define error(s) { if (cli) Write(_Backstdout, (s), strlen(s)); } #define USAGE "blocks \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); }