home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
316.lha
/
frag
/
free.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-12-05
|
11KB
|
377 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 <devices/trackdisk.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define error(s) { if (cli) Write(_Backstdout, (s), strlen(s)); }
/* border sizes, shouldn't be hard coded ... */
#define XLEFT 2
#define XRIGHT 2
#define YTOP 10
#define YBOTTOM 1
/* Max/Min window size */
#define MAXHEIGHT (200 - YTOP - YBOTTOM)
#define MAXWIDTH (640 - XLEFT - XRIGHT)
#define MINWIDTH 200
#define MINHEIGHT 80
/* Detach info */
long _stack = 2000;
char *_procname = "freeblks";
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;
/* Device access */
struct MsgPort *port;
struct IOStdReq *io;
int DevOpen;
/* Partition characteristics */
long blk_size, blk_offset, root_blk, *secbuf, *secbuf2;
struct Window *win;
/* size of window, of each block, etc */
int xdiv, rectw, recth, width, height;
int 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
};
/* bcpl string -> C string */
char *btoc_str(char *to, BSTR from)
{
char *cstr = (char *)BADDR(from);
strncpy(to, cstr + 1, *cstr);
to[*cstr] = '\0';
return to;
}
/* Calculate coords on window for block 'block' on disk */
void cvt_point(long *x, long *y, long block)
{
*x = rectw * (block / (xdiv * height)) + XLEFT;
*y = recth * (block % height) + YTOP;
}
/* Calc size, & open window */
int prepare_window(struct DeviceNode *dev)
{
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 */
btoc_str(title, dev->dn_Name);
strcat(title, ":, free blocks");
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;
}
/* Reads sector at offset 'sector' from disk ('sector' must be a multiple of 51
2) */
BYTE *ReadSector(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;
}
/* Turn motor on/off */
void Motor(int on)
{
io->io_Command = TD_MOTOR;
io->io_Length = on;
DoIO((struct IORequest *)io);
}
/* Find device by name */
struct DeviceNode *FindDevice(char *name)
{
struct DeviceNode *devlist;
int l = strlen(name), l2;
char *name2;
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)
{
name2 = (char *)BADDR(devlist->dn_Name);
l2 = *name2;
if (l == l2 && strnicmp(name, name2 + 1, l) == 0) break;
}
Permit();
return devlist;
}
/* Find device by task */
struct DeviceNode *TaskDevice(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* */
BYTE *ReadBlock(long *buf, long n)
{
return(ReadSector((blk_offset + n) * blk_size * 4, (BYTE *)buf, blk_size *
4));
}
/* Get partition characteristics, open device */
int setup(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(2 * 4 * blk_size, env[DE_MEMBUFTYPE]);
if (!secbuf)
{
error("No sector buffer!\n");
return FALSE;
}
secbuf2 = secbuf + blk_size;
return TRUE;
}
/* Close device */
void release(void)
{
if (secbuf) FreeMem((char *)secbuf, 2 * 4 * blk_size);
if (DevOpen) CloseDevice((struct IORequest *)io);
if (io) DeleteStdIO(io);
if (port) DeletePort(port);
}
/* Displays free blocks on device dev. For OFS/FFS !!! */
void disp_free(struct DeviceNode *dev)
{
struct FileSysStartupMsg *fmsg = (struct FileSysStartupMsg *)BADDR(dev->dn_
Startup);
ULONG *env = (ULONG *)BADDR(fmsg->fssm_Environ);
int quit, bit;
struct IntuiMessage *msg;
long first, last, numblks, pos, i, blk, word, x, y;
int firstx, firsty, lastx, lasty;
if (prepare_window(dev))
{
if (!ReadBlock(secbuf, root_blk)) goto diskerror;
first = blk_size - 49; last = blk_size - 24; /* extent of bitmap list *
/
numblks = env[DE_NUMHEADS] * env[DE_BLKSPERTRACK] * (env[DE_UPPERCYL] -
env[DE_LOWCYL] + 1);
blk = env[DE_RESERVEDBLKS]; /* First block described in bitmap */
pos = first;
lasty = -recth - 1; firsty = -1;
do {
if (pos == last) /* End of bitmap table list, read extension bitmap
table */
{
if (!ReadBlock(secbuf, secbuf[last])) goto diskerror;
pos = first = 0;
last = blk_size - 1;
}
/* Read next bitmap sector */
if (!ReadBlock(secbuf2, secbuf[pos++])) goto diskerror;
/* Display free blocks in it */
for (i = 1; blk != numblks && i < blk_size; i++)
{
word = secbuf2[i];
for (bit = 0; blk != numblks && bit < 32; bit++, blk++)
{
if (word & 1) /* Free sector */
{
cvt_point(&x, &y, blk);
/* Speed up drawing (by a factor of 3 on HD), check
for consecutive free blocks & draw them in one go */
if (y != lasty + recth || x != lastx)
{
/* Non consecutive blocks, draw */
if (firsty != -1)
RectFill(win->RPort, firstx, firsty, lastx + re
ctw - 1, lasty + recth - 1);
firstx = x; firsty = y;
}
lastx = x; lasty = y;
}
word >>= 1; /* next sector */
}
}
} while (blk != numblks);
if (firsty != -1)
RectFill(win->RPort, firstx, firsty, lastx + rectw - 1, lasty + rec
th - 1);
Motor(FALSE); /* Turn drive motor off */
quit = FALSE;
while (!quit)
{
WaitPort(win->UserPort);
while (msg = (struct IntuiMessage *)GetMsg(win->UserPort))
{
quit = msg->Class == CLOSEWINDOW;
ReplyMsg((struct Message *)msg);
}
}
CloseWindow(win);
}
else error("Couldn't open window\n");
return;
diskerror:
CloseWindow(win);
error("Error reading disk\n");
}
/* Display free blocks on partition passed as parm, from CLI only */
void main(int argc, char **argv)
{
struct DeviceNode *dev;
cli = (argc != 0);
if (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library"
, 0L))
if (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0L))
if (argc != 2) error("Usage: free <device>\n")
else
{
int l = strlen(argv[1]) - 1;
if (argv[1][l] != ':') error("Not a device spec!\n")
else
{
argv[1][l] = '\0';
dev = FindDevice(argv[1]);
if (dev)
{
if (setup(dev)) disp_free(dev);
release();
}
else error("No such device\n");
}
}
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);
}