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 <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);
- }
-