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 >
Wrap
C/C++ Source or Header
|
1989-11-21
|
10KB
|
355 lines
#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);
}