page%swap@Sun.COM (Bob Page) (11/13/89)
Submitted-by: dg3i+@andrew.cmu.edu (David Gay) Posting-number: Volume 89, Issue 201 Archive-name: dos/fs/frag.1 Here are two utilities, "blocks" and "free", to show disk and file fragmentation. [uuencoded executables included. ..bob] # This is a shell archive. # Remove anything above and including the cut line. # Then run the rest of the file through 'sh'. # Unpacked files will be owned by you and have default permissions. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: SHell ARchive # Run the following text through 'sh' to create: # lmkfile # free.c # free.doc # free.hdr # free.uu # blocks.c # blocks.doc # blocks.uu # This is archive 1 of a 1-part kit. # This archive created: Sun Nov 12 17:42:24 1989 echo "extracting lmkfile" sed 's/^X//' << \SHAR_EOF > lmkfile Xall: blocks free X Xblocks: blocks.c X lc -v -O blocks X @blink from lib:cback.o blocks.o to blocks lib lib:lc.lib batch nodebug def Xine __main=__tinymain verbose sc sd X Xfree: free.c X lc -cf -v -rr -O free X @blink from lib:cback.o free.o to free lib lib:lcr.lib batch nodebug define X @_main=@_tinymain verbose sc sd X SHAR_EOF echo "extracting free.c" sed 's/^X//' << \SHAR_EOF > free.c X#include <exec/types.h> X#include <exec/io.h> X#include <libraries/dos.h> X#include <libraries/dosextens.h> X#include <libraries/filehandler.h> X#include <intuition/intuition.h> X#include <workbench/startup.h> X#include <devices/trackdisk.h> X X#include <proto/exec.h> X#include <proto/dos.h> X#include <proto/graphics.h> X#include <proto/intuition.h> X X#include <stdio.h> X#include <stdlib.h> X#include <string.h> X X#define error(s) { if (cli) Write(_Backstdout, (s), strlen(s)); } X X/* border sizes, shouldn't be hard coded ... */ X#define XLEFT 2 X#define XRIGHT 2 X#define YTOP 10 X#define YBOTTOM 1 X/* Max/Min window size */ X#define MAXHEIGHT (200 - YTOP - YBOTTOM) X#define MAXWIDTH (640 - XLEFT - XRIGHT) X#define MINWIDTH 200 X#define MINHEIGHT 80 X X/* Detach info */ Xlong _stack = 2000; Xchar *_procname = "freeblks"; Xlong _priority = 0; Xlong _BackGroundIO = TRUE; Xextern long _Backstdout; X Xtypedef struct FileInfoBlock FIB; Xtypedef struct InfoData INFO; X Xextern struct IntuitionBase *IntuitionBase; Xextern struct GfxBase *GfxBase; X X/* Device access */ Xstruct MsgPort *port; Xstruct IOStdReq *io; Xint DevOpen; X/* Partition characteristics */ Xlong blk_size, blk_offset, root_blk, *secbuf, *secbuf2; Xstruct Window *win; X/* size of window, of each block, etc */ Xint xdiv, rectw, recth, width, height; Xint cli; X Xstruct NewWindow newwin = { X 0, 0, X 0, 0, X -1, -1, X CLOSEWINDOW, X WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE | SMART_REFRESH | NOCAREREFRESH | RM XBTRAP, X NULL, X NULL, X NULL, X NULL, X NULL, X 0, 0, 0, 0, X WBENCHSCREEN X}; X X/* bcpl string -> C string */ Xchar *btoc_str(char *to, BSTR from) X{ X char *cstr = (char *)BADDR(from); X X strncpy(to, cstr + 1, *cstr); X to[*cstr] = '\0'; X X return to; X} X X/* Calculate coords on window for block 'block' on disk */ Xvoid cvt_point(long *x, long *y, long block) X{ X *x = rectw * (block / (xdiv * height)) + XLEFT; X *y = recth * (block % height) + YTOP; X} X X/* Calc size, & open window */ Xint prepare_window(struct DeviceNode *dev) X{ X struct FileSysStartupMsg *msg = (struct FileSysStartupMsg *)BADDR(dev->dn_S Xtartup); X ULONG *env = (ULONG *)BADDR(msg->fssm_Environ); X long blkscyl = env[DE_NUMHEADS] * env[DE_BLKSPERTRACK]; X long numcyls = env[DE_UPPERCYL] - env[DE_LOWCYL] + 1; X long blks; X static char title[80]; X X if (blkscyl <= MAXHEIGHT) /* Do a "nice" presentation, 1 cylinder per vert Xline */ X { X height = blkscyl; X xdiv = (numcyls / MAXWIDTH + 1); /* Nb of cylinders per vertical line * X/ X width = numcyls / xdiv; X } X else /* Just squash em in */ X { X blks = numcyls * blkscyl; X height = MAXHEIGHT; X xdiv = (blks / MAXHEIGHT + 1) / MAXWIDTH + 1; X width = (blks / MAXHEIGHT + 1) / xdiv; X } X /* Size of rect for 1 block */ X rectw = MINWIDTH / width + 1; X recth = MINHEIGHT / height + 1; X X /* Open window */ X btoc_str(title, dev->dn_Name); X strcat(title, ":, free blocks"); X newwin.Title = title; X newwin.Width = rectw * width + XLEFT + XRIGHT; X newwin.Height = recth * height + YTOP + YBOTTOM; X X if (win = OpenWindow(&newwin)) X { X SetAPen(win->RPort, 2); X RectFill(win->RPort, XLEFT, YTOP, win->Width - XRIGHT - 1, win->Height X- YBOTTOM - 1); X SetAPen(win->RPort, 3); X return TRUE; X } X return FALSE; X} X X/* Reads sector at offset 'sector' from disk ('sector' must be a multiple of 51 X2) */ XBYTE *ReadSector(long sector, BYTE *buf, long len) X{ X io->io_Command = CMD_READ; X io->io_Length = len; X io->io_Data = (APTR)buf; X io->io_Offset = sector; X DoIO((struct IORequest *)io); X return (io->io_Error == 0) ? buf : NULL; X} X X/* Turn motor on/off */ Xvoid Motor(int on) X{ X io->io_Command = TD_MOTOR; X io->io_Length = on; X DoIO((struct IORequest *)io); X} X X/* Find device by name */ Xstruct DeviceNode *FindDevice(char *name) X{ X struct DeviceNode *devlist; X int l = strlen(name), l2; X char *name2; X X Forbid(); X devlist = (struct DeviceNode *)BADDR(((struct DosInfo *)BADDR(((struct Root XNode *)(DOSBase->dl_Root))->rn_Info))->di_DevInfo); X for (;devlist; devlist = (struct DeviceNode *)BADDR(devlist->dn_Next)) X if (devlist->dn_Type == DLT_DEVICE) X { X name2 = (char *)BADDR(devlist->dn_Name); X l2 = *name2; X if (l == l2 && strnicmp(name, name2 + 1, l) == 0) break; X } X X Permit(); X return devlist; X} X X/* Find device by task */ Xstruct DeviceNode *TaskDevice(struct MsgPort *task) X{ X struct DeviceNode *devlist; X X Forbid(); X devlist = (struct DeviceNode *)BADDR(((struct DosInfo *)BADDR(((struct Root XNode *)(DOSBase->dl_Root))->rn_Info))->di_DevInfo); X for (;devlist; devlist = (struct DeviceNode *)BADDR(devlist->dn_Next)) X if (devlist->dn_Type == DLT_DEVICE) X { X if (task == devlist->dn_Task) { Permit(); return devlist; } X } X X Permit(); X return NULL; X} X X/* Reads block n of *partition* */ XBYTE *ReadBlock(long *buf, long n) X{ X return(ReadSector((blk_offset + n) * blk_size * 4, (BYTE *)buf, blk_size * X4)); X} X X/* Get partition characteristics, open device */ Xint setup(struct DeviceNode *dev) X{ X char devname[32]; X struct FileSysStartupMsg *msg = (struct FileSysStartupMsg *)BADDR(dev->dn_S Xtartup); X ULONG *env = (ULONG *)BADDR(msg->fssm_Environ); X long err; X X port = CreatePort(0, 0); X if (!port) X { X error("No port!\n"); X return FALSE; X } X io = CreateStdIO(port); X if (!io) X { X error("No IO request!\n"); X return FALSE; X } X err = OpenDevice(btoc_str(devname, msg->fssm_Device), msg->fssm_Unit, (stru Xct IORequest *)io, msg->fssm_Flags); X if (err) X { X error("Device not opened\n"); X return FALSE; X } X DevOpen = TRUE; X blk_size = env[DE_SIZEBLOCK]; X blk_offset = env[DE_LOWCYL] * env[DE_BLKSPERTRACK] * env[DE_NUMHEADS]; X root_blk = (env[DE_BLKSPERTRACK] * env[DE_NUMHEADS] * (env[DE_UPPERCYL] - e Xnv[DE_LOWCYL] + 1) - 1 + env[DE_RESERVEDBLKS]) / 2; X secbuf = (long *)AllocMem(2 * 4 * blk_size, env[DE_MEMBUFTYPE]); X if (!secbuf) X { X error("No sector buffer!\n"); X return FALSE; X } X secbuf2 = secbuf + blk_size; X return TRUE; X} X X/* Close device */ Xvoid release(void) X{ X if (secbuf) FreeMem((char *)secbuf, 2 * 4 * blk_size); X if (DevOpen) CloseDevice((struct IORequest *)io); X if (io) DeleteStdIO(io); X if (port) DeletePort(port); X} X X/* Displays free blocks on device dev. For OFS/FFS !!! */ Xvoid disp_free(struct DeviceNode *dev) X{ X struct FileSysStartupMsg *fmsg = (struct FileSysStartupMsg *)BADDR(dev->dn_ XStartup); X ULONG *env = (ULONG *)BADDR(fmsg->fssm_Environ); X int quit, bit; X struct IntuiMessage *msg; X long first, last, numblks, pos, i, blk, word, x, y; X int firstx, firsty, lastx, lasty; X X if (prepare_window(dev)) X { X if (!ReadBlock(secbuf, root_blk)) goto diskerror; X first = blk_size - 49; last = blk_size - 24; /* extent of bitmap list * X/ X numblks = env[DE_NUMHEADS] * env[DE_BLKSPERTRACK] * (env[DE_UPPERCYL] - X env[DE_LOWCYL] + 1); X blk = env[DE_RESERVEDBLKS]; /* First block described in bitmap */ X pos = first; X lasty = -recth - 1; firsty = -1; X X do { X if (pos == last) /* End of bitmap table list, read extension bitmap X table */ X { X if (!ReadBlock(secbuf, secbuf[last])) goto diskerror; X pos = first = 0; X last = blk_size - 1; X } X /* Read next bitmap sector */ X if (!ReadBlock(secbuf2, secbuf[pos++])) goto diskerror; X X /* Display free blocks in it */ X for (i = 1; blk != numblks && i < blk_size; i++) X { X word = secbuf2[i]; X for (bit = 0; blk != numblks && bit < 32; bit++, blk++) X { X if (word & 1) /* Free sector */ X { X cvt_point(&x, &y, blk); X /* Speed up drawing (by a factor of 3 on HD), check X for consecutive free blocks & draw them in one go */ X X if (y != lasty + recth || x != lastx) X { X /* Non consecutive blocks, draw */ X X if (firsty != -1) X RectFill(win->RPort, firstx, firsty, lastx + re Xctw - 1, lasty + recth - 1); X firstx = x; firsty = y; X } X lastx = x; lasty = y; X } X word >>= 1; /* next sector */ X } X } X } while (blk != numblks); X if (firsty != -1) X RectFill(win->RPort, firstx, firsty, lastx + rectw - 1, lasty + rec Xth - 1); X Motor(FALSE); /* Turn drive motor off */ X X quit = FALSE; X while (!quit) X { X WaitPort(win->UserPort); X while (msg = (struct IntuiMessage *)GetMsg(win->UserPort)) X { X quit = msg->Class == CLOSEWINDOW; X ReplyMsg((struct Message *)msg); X } X } X CloseWindow(win); X } X else error("Couldn't open window\n"); X return; X Xdiskerror: X CloseWindow(win); X error("Error reading disk\n"); X} X X/* Display free blocks on partition passed as parm, from CLI only */ Xvoid main(int argc, char **argv) X{ X struct DeviceNode *dev; X X cli = (argc != 0); X X if (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library" X, 0L)) X if (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0L)) X if (argc != 2) error("Usage: free <device>\n") X else X { X int l = strlen(argv[1]) - 1; X X if (argv[1][l] != ':') error("Not a device spec!\n") X else X { X argv[1][l] = '\0'; X dev = FindDevice(argv[1]); X if (dev) X { X if (setup(dev)) disp_free(dev); X release(); X } X else error("No such device\n"); X } X } X else error("No graphics library !\n") X else error("No intuition library !\n"); X X if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase); X if (GfxBase) CloseLibrary((struct Library *)GfxBase); X if (_Backstdout) Close(_Backstdout); X} SHAR_EOF echo "extracting free.doc" sed 's/^X//' << \SHAR_EOF > free.doc X This is a small program to graphically dsplay the free blocks on a disk X(you can thus see how fragmented it is). X XUsage X----- X X This program runs from the CLI only: X X free <device name>: X X will display the free blocks on the disk in the device specified X (you must specify the device, not the name of the disk). X Note that this program detaches from the CLI, don't 'RUN' it ! X X Example: X X free df0: X X The window opened will be a representation of the disk, with cylinders X presented vertically (if possible). The lit pixels represent the free X blocks on the disk. X X XDistribution X------------ X X This software is placed in the public domain. X X X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ XDavid Gay X "(p.suiv :=: q.prec.suiv).prec :=: q.prec" X You don't want to know about this language ! X XGAY_D@ELMA.EPFL.CH, or GAY_D%ELMA.EPFL.CH@CLSEPF51.bitnet X(till mid-august 89) X X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ X X SHAR_EOF echo "extracting free.hdr" sed 's/^X//' << \SHAR_EOF > free.hdr XFrom dg3i+@andrew.cmu.edu Sat Nov 11 18:44:13 1989 XDate: Fri, 10 Nov 89 16:08:45 -0500 (EST) XFrom: David Gay <dg3i+@andrew.cmu.edu> XTo: page@Sun.COM XSubject: comp.sources.amiga submission, show disk space X X# This is a shell archive. X# Remove everything above and including the cut line. X# Then run the rest of the file through sh. SHAR_EOF echo "extracting free.uu" sed 's/^X//' << \SHAR_EOF > free.uu X Xbegin 644 free XM```#\P`````````#``````````(```#*```#0@```-8```/I````RDCG?OY+, XM[P`T)$@D`$GY`````"QX``0I3@!:*4\`8D*L`%Y'^0```K1R`"`\````*6`"C XM)L%1R/_\)FX!%'``(CP``#``3J[^SBEK`)@`5DJK`*QG``%080`"G"(L`%8L4 XM;`-(3J[_H"E``%8@:P"LT<C1R")H`!#3R=/)(`)R`!(9*`DF`=*!T(%:@.6(. XMT*P`%"E``!1![```+'@`!$ZN_R(B0"\`(FD`$$?I`.8@1"`#8`(6V%'(__P6" XM_``@($H@`F`"%MA1R/_\0ALI2P!V($0@`V`"%MA1R/_\0A-%Z0!L*4H`&D7ZY XM_Q8B_````#DF">2+(M)"DD7Z`38@/````-T2VE'(__Q*K`">9P``&D'L`(8BK XM""0\```#[2QL`TA.KO_B*4``<BQX``1.KO]\(BP`EB0L`)HH+`"(+&P#2$ZN; XM_W8F3DJ`9@``("1?(FH`$"(L`%9.KO^F($HL>``$3J[_''!H8```)B1`(E]%. XMZO^D0>H`2D'H``0@*``$(4D`!"*((T``!"!`((EP`"QX``1.KO]V(DLL>``$A XM3J[^8DS??WY.=2EK`#H`)@:L````@``F80`!0$7Z`/`I2@`:80`!3"E``%XO5 XM`"1`("H`)&<2+&P#2"!`(B@``"E!`%9.KO^"(BH`(&<:)#P```/M3J[_XBE`8 XM`&YG"N6(($`G:``(`*0@;`!>+PA(;``B(&@`)"EH``0`=DZZ`0A.N0``#,QPU XM`&```(0````Y`````"`/2.=^_BI`+'@`!$GY`````"E/`&)A``"ND\DL>``$X XM3J[^VB9`*6L`.@`F!JP```"``"8@:P"`T<C1R")H``S3R=/)*5$`'B%1``PB) XM+`!6+&P#2$ZN_X)(>@"$3KD```S,6$\B+``>+&P#2$ZN_V0B+`!63J[_IG``1 XM("P`3F<$($!.D$ZY```,Q"QX``0B;`-(3J[^8DZY```)3DJL`%YG&B(L`&YG- XM!$ZN_]PL>``$3J[_?")L`%Y.KOZ&+FP`8DS??WY.=4/L`'IP`$ZN_=@I0`-(K XM9P``!$YU<&1@G$'K`%Q.KOZ`0>L`7$ZN_HQ.=0``3OD```E,<&$```/L````M XM!0````$```+&```"M````HP```(<```#(@````,````"````)````CP````.* XM`````````_(```/I```#0DY5__0O"BM`__CE@")`1>D``1(12(%(P2]```0K@ XM2/_\(`$B2DZZ"EX@;P`$$!!(@"!M__Q",```(`@D7TY=3G5.5?_P*T#_]"`L* XM`R@B+`,X3KH*QB]````@+?_T(B\``$ZZ"M8B+`,L3KH*KE2`((`@+?_T(BP#V XM.$ZZ"KX@+`,P3KH*EG(*T($B@$Y=3G5.5?_X2.<S$B9(("L`'.6`($`B*``(& XMY8$@02`H``PB*``43KH*9BX`("@`*)"H`"0L`%*&<$)&`+Z`;B8I1P,X(`8BL XM/````GQ.N@I@4H`I0`,H(`8B+`,H3KH*4"E``S1@.BE``S@@!B('3KH*'G)"D XM1@%.N@HV4H`B/````GPO0``83KH*)E*`*4`#*"`O`!@B+`,H3KH*%"E``S1PX XM9-"`(BP#-$ZZ"@12@"E``RQP4"(L`SA.N@GT4H`I0`,P("L`*$'L`K1A`/ZJ4 XM0>P"M$/L`-).N@DZ0>P"M"E(`+P@+`,L(BP#-$ZZ":)8@#E``*8@+`,P(BP#Y XM.$ZZ"9!R"]"!.4``J$'L`*(L;`-`3J[_-"E``R1*@&=2($`B:``R<`(L;`-$A XM3J[^JB!L`R0P*``(2,!7@#(H``I(P56!+T``&"]!`!PB:``R<`)R"B0O`!@FG XM+P`<3J[^SB!L`R0B:``R<`-.KOZJ<`%@`G``3-](S$Y=3G5.5?_X2.<`$B9(2 XM(&P#"#%\``(`'"%!`"0A2P`H(&P#""%``"PK0/_X*T'__")(+'@`!$ZN_C@@- XM;`,($"@`'TH`9@0@2V`"D<@@"$S?2`!.74YU3E7__"\.(&P#"#%\``D`'"%`6 XM`"0K0/_\(D@L>``$3J[^."Q?3EU.=4CG`3(F2"!+2AAF_%.(D<LN""QX``1.I XMKO]\(&P#2"!H`"(@*``8Y8`@0"(H``3E@21!8"Y*J@`$9B(@*@`HY8`@0!(0/ XM2(%(P;*'9A!#Z``!(`<@2TZZ!TY*@&<*(!+E@"1`(`IFSBQX``1.KO]V(`I,_ XMWTR`3G5(YP`R)D@L>``$3J[_?"!L`T@@:``B("@`&.6`($`B*``$Y8$D06`>9 XM2JH`!&82M^H`"&8,+'@`!$ZN_W8@"F`4(!+E@"1`(`IFWBQX``1.KO]V<`!,` XMWTP`3G5.5?_X(BP#%-*`*T#_^"`L`Q!.N@>XY8`B+`,0Y8$K2/_\80#^DDY=] XM3G5.5?_82.<P,B9(("L`'.6`)D`@*P`(Y8`D0'``D<A.N@BB*4`#!&8B2JP#V XM/&<6<`DB+`!R0>P`XB0()@`L;`-(3J[_T'``8``!%B!L`P1.N@@V*4`#"$J`_ XM9BA*K`,\9QQR#R]!`!0B+`!R0>P`]B0()B\`%"QL`TA.KO_0<`!@``#>("L`J XM!$'M_]QA`/O^($`@$R)L`P@B*P`,+'@`!$ZN_D1*@&<B2JP#/&<6<!(B+`!R9 XM0>P!%B0()@`L;`-(3J[_T'``8```F'`!*4`##"(J``0I00,0("H`)"(J`!1.^ XMN@;"(BH`#$ZZ!KHI0`,4("H`%"(J``Q.N@:J(BH`*)*J`"12@4ZZ!IS0J@`8S XM4X#BB"E``Q@@+`,0YX`B*@`P+'@`!$ZN_SHI0`,<9B!*K`,\9Q9P$B(L`')!C XM[`$^)`@F`"QL`TA.KO_0<`!@$B`L`Q#E@"!L`QS1P"E(`R!P`4S?3`Q.74YU# XM+PY*K`,<9Q(@+`,0YX`B;`,<+'@`!$ZN_RY*K`,,9PPB;`,(+'@`!$ZN_CY** XMK`,(9P@@;`,(3KH%F$JL`P1G""!L`P1.N@6V+%].=4Y5_\!(YS\R)D@@2R`H5 XM`!SE@")`(BD`".6!)D%A`/M(2H!G``(N("P#&"!L`QQA`/WT2H!G``(Z>NC:5 XMK`,0*T7_["`K``PB*P`43KH%I"(K`"B2JP`D4H%.N@66*"L`&'S/W*P#$"M&1 XM_^@B+`,P1($N`5.'<O\K0?_4+T``)+R%9B0@!>6`(&P#'")(T\`@$6$`_9)*A XM@&<``=A\`"`L`Q!3@"M`_^P@!E*`(@;E@2!L`QS1P2M`_^@@$"!L`R!A`/UDZ XM2H!G``&J>@%\!&```+H@;`,@T>W_S"P0>@!@``"0"`8``&<``((@!$'M_^!#Z XM[?_<80#Z)-ZL`S`@+?_<L(=F#"`M_]`B+?_@LH!G4"`M_]1R_["!9S8B+?_0% XMTJP#+%.!)`=3@B]!`"@@;`,D(F@`,B`M_]@B+?_4+T(`+"0O`"@F+P`L+&P#" XM1$ZN_LX@+?_@(BW_W"M`_]@K0?_4*VW_X/_0+BW_W.*&4H52A+BO`"1G"'`@^ XMNH!M`/]F*BW_Y%*%+"W_S%B&*T7_Y"M&_\PL+P`DN(9G"+JL`Q!M`/\R(`8J! XM+?_L+"W_Z+B`9@#^T"PM_]1P_[R`9S@@+?_0T*P#+%.`(@?2K`,P4X$O0``D5 XM+T$`*"!L`R0B:``R("W_V"(&)"\`)"8O`"@L;`-$3J[^SG``80#[-GX`8$0@R XM;`,D(&@`5BQX``1.KOZ`8!P,JP```@``%%?`1`!(@$C`+@`B2RQX``1.KOZ&* XM(&P#)"!H`%8L>``$3J[^C"9`(`MFSDJ'9[@@;`,D+&P#0$ZN_[A@1DJL`SQGW XM0'`5(BP`<D'L`68D""8`+&P#2$ZN_]!@*"!L`R0L;`-`3J[_N$JL`SQG%G`37 XM(BP`<D'L`9(D""8`+&P#2$ZN_]!,WTS\3EU.=4Y5__Q(YS$R+@`F2$J'5L!$8 XM`$B`2,`I0`,\0^P!NG``+'@`!$ZN_=@I0`-`2H!G``#T0^P!S'``3J[]V"E`" XM`T1*@&<``+QR`KZ!9RA*K`,\9P``]'(5+T$`&"(L`')![`'>)`@F+P`8+&P#5 XM2$ZN_]!@``#4(&L`!$H89OQ3B)'K``0B"%.!(&L`!-'!)$AR.K(29RA*K`,\T XM9P``K'(3+T$`&"(L`')![`(*)`@F+P`8+&P#2$ZN_]!@``",0A(@:P`$80#Y) XM\"9`(`MG%B!+80#ZWDJ`9P8@2V$`_(9A`/PV8&1*K`,\9UYP#R(L`')![`(R8 XM)`@F`"QL`TA.KO_08$9*K`,\9T!R%B]!`!@B+`!R0>P"4B0()B\`&"QL`TA.= XMKO_08")*K`,\9QQR%R]!`!@B+`!R0>P"@B0()B\`&"QL`TA.KO_02JP#0&<,L XM(FP#0"QX``1.KOYB2JP#1&<,(FP#1"QX``1.KOYB2JP`<F<,(BP`<BQL`TA.J XMKO_<3-],C$Y=3G5.=4YU#```86T*#```>FX$!```($YU``!.5?]T2.<!,"9(G XM?@!P(+Z`;'H0$W(@L`%G#'()L`%G!G(*L`%F!%*+8.A*$V=>(`?E@%*'0>W_4 XM=-'`)$AP(K`39B)2BR2+2A-G"G`BL!-G!%*+8/)*$V8(<`%.N@!48*Q"&V"H@ XM)(M*$V<8$!-R(+`!9Q!R";`!9PIR"K`!9P12BV#D2A-F`F`$0AM@@$J'9P9!C XM[?]T8`0@;`!>(`=.NOW&<`!.N@`,3-\,@$Y=3G4``$[Y````&````````$Y5+ XM__Q(YP,P)D@D22X`2H=G,DH39RY*$F<J<``0&TZZ_Q!R`!(:+T``$"`!3KK_F XM`B(O`!"2@"P!2H9G!"`&8!I3AV#*2H=G$$H39P1P`6`*2A)G!'#_8`)P`$S?? XM#,!.74YU```B"&`$$-EG"%.`9/A@!D(84X!D^B`!3G4@"$H89OQ3B!#99OQ.$ XM=0``2.<`$B9(%WP`_P`(,'S__R=(`!0G2``8(DMP,"QX``1.KO\N3-](`$YU& XM``!(YP`2)DA*JP`*9PHB2RQX``1.KOZ8%WP`_P`(</\G0``4<``0*P`/+'@`H XM!$ZN_K`B2W`B3J[_+DS?2`!.=0``2.<P`"0`)@%(0DA#Q,'&P,#!U$-(0D)"\ XMT(),WP`,3G5*@&H``!Y$@$J!:@``#$2!80``($2!3G5A```81(!$@4YU2H%JK XM```,1(%A```&1(!.=2\"2$$T`68``")(0$A!2$(T`&<```:$P3`"2$`T`(3!J XM,`)(0C(")!].=2\#=A`,00"`9```!N&944,,00@`9```!NF964,,02``9```A XM!N6954-*06L```;CF5-#-`#FJ$A"0D+FJDA#@,$V`#`"-`-(0<3!D()D```(! XM4T/0@63^<@`R`TA#Y[A(0,%!)A\D'TYU2.<`,B9((`MF!'``8"9P,"(\``$`( XM`2QX``1.KO\Z)$`@"F<.%7P`!0`(0BH`"25+``X@"DS?3`!.=0``2.<#,B9(H XM+@!P_RQX``1.KOZV+``,!@#_9@1P`&!F<"(B/``!``%.KO\Z)$`@"F8*<``0W XM!DZN_K!@2"5+``H@!Q5```D5?``$``A"*@`.%48`#Y/)3J[^VB5``!`@"V<(7 XM(DI.KOZ>8!I!Z@`8)4@`%$'J`!0E2``<0JH`&!5\``(`("`*3-],P$YU``!@% XM```23G$``"!O``1@`/R23G$``$CG`#(F;`-,(`MG%"13(DL@*P`(+'@`!$ZN4 XM_RXF2F#HD<@I2`-0*4@#3$S?3`!.=0```^P````!`````@``"A8````````#1 XM\@```^H```"M`````````````````````0````$```#F3OD`````````````[ XM````````````````````````````````````````````````````````````` XM``````````````````````````````````````````````````````!D;W,NT XM;&EB<F%R>0`J````!]!F<F5E8FQK<P``````C``````````!``````````#_0 XM_P```@```P`.```````````````````````````````````````!.BP@9G)E6 XM92!B;&]C:W,``$YO('!O<G0A"@!.;R!P;W)T(0H`3F\@24\@<F5Q=65S="$*F XM`$YO($E/(')E<75E<W0A"@!$979I8V4@;F]T(&]P96YE9`H``$1E=FEC92!N- XM;W0@;W!E;F5D"@``3F\@<V5C=&]R(&)U9F9E<B$*``!.;R!S96-T;W(@8G5F$ XM9F5R(0H``$-O=6QD;B=T(&]P96X@=VEN9&]W"@!#;W5L9&XG="!O<&5N('=I. XM;F1O=PH`17)R;W(@<F5A9&EN9R!D:7-K"@!%<G)O<B!R96%D:6YG(&1I<VL*T XM`&EN='5I=&EO;BYL:6)R87)Y`&=R87!H:6-S+FQI8G)A<GD``%5S86=E.B!FO XM<F5E(#QD979I8V4^"@!5<V%G93H@9G)E92`\9&5V:6-E/@H`3F]T(&$@9&5VF XM:6-E('-P96,A"@!.;W0@82!D979I8V4@<W!E8R$*`$YO('-U8V@@9&5V:6-E_ XM"@!.;R!S=6-H(&1E=FEC90H`3F\@9W)A<&AI8W,@;&EB<F%R>2`A"@``3F\@? XM9W)A<&AI8W,@;&EB<F%R>2`A"@``3F\@:6YT=6ET:6]N(&QI8G)A<GD@(0H`1 XM3F\@:6YT=6ET:6]N(&QI8G)A<GD@(0H```````/L`````0````(```"6````H X%`````_)TI X`` Xend Xsize 5000 SHAR_EOF echo "extracting blocks.c" sed 's/^X//' << \SHAR_EOF > blocks.c X#include <exec/types.h> X#include <exec/io.h> X#include <libraries/dos.h> X#include <libraries/dosextens.h> X#include <libraries/filehandler.h> X#include <intuition/intuition.h> X#include <workbench/startup.h> X X#include <proto/exec.h> X#include <proto/dos.h> X#include <proto/graphics.h> X#include <proto/intuition.h> X X#include <stdio.h> X#include <string.h> X X#define error(s) { if (cli) Write(_Backstdout, (s), strlen(s)); } X X#define USAGE "blocks <filename>\n" X/* border sizes */ X#define XLEFT 2 X#define XRIGHT 2 X#define YTOP 10 X#define YBOTTOM 1 X/* Min & Max size for window */ X#define MAXHEIGHT (200 - YTOP - YBOTTOM) X#define MAXWIDTH (640 - XLEFT - XRIGHT) X#define MINWIDTH 200 X#define MINHEIGHT 80 X X/* Spawn info */ Xlong _stack = 2000; Xchar *_procname = "blocks"; Xlong _priority = 0; Xlong _BackGroundIO = TRUE; Xextern long _Backstdout; X Xtypedef struct FileInfoBlock FIB; Xtypedef struct InfoData INFO; X Xextern struct IntuitionBase *IntuitionBase; Xextern struct GfxBase *GfxBase; X X/* For io to device */ Xstruct MsgPort *port; Xstruct IOStdReq *io; Xint DevOpen; X/* Device info */ Xlong blk_size, blk_offset, root_blk, *secbuf; Xstruct Window *win; X/* size of window, of each block, etc */ Xint xdiv, rectw, recth, width, height; Xint cli; /* Called from cli ? */ X Xstruct NewWindow newwin = { X 0, 0, X 0, 0, X -1, -1, X CLOSEWINDOW, X WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE | SMART_REFRESH | NOCAREREFRESH | RM XBTRAP, X NULL, X NULL, X NULL, X NULL, X NULL, X 0, 0, 0, 0, X WBENCHSCREEN X}; X X/* Calculate coords on window for block 'block' on disk */ Xvoid cvt_point(x, y, block) Xlong *x, *y, block; X{ X *x = rectw * (block / (xdiv * height)) + XLEFT; X *y = recth * (block % height) + YTOP; X} X X/* Calc size, & open window */ Xint prepare_window(fib, dev) Xstruct FileInfoBlock *fib; Xstruct DeviceNode *dev; X{ X /* Get disk characteristics */ X struct FileSysStartupMsg *msg = (struct FileSysStartupMsg *)BADDR(dev->dn_S Xtartup); X ULONG *env = (ULONG *)BADDR(msg->fssm_Environ); X long blkscyl = env[DE_NUMHEADS] * env[DE_BLKSPERTRACK]; X long numcyls = env[DE_UPPERCYL] - env[DE_LOWCYL] + 1; X long blks; X static char title[80]; X X if (blkscyl <= MAXHEIGHT) /* Do a "nice" presentation, 1 cylinder per vert Xline */ X { X height = blkscyl; X xdiv = (numcyls / MAXWIDTH + 1); /* Nb of cylinders per vertical line * X/ X width = numcyls / xdiv; X } X else /* Just squash em in */ X { X blks = numcyls * blkscyl; X height = MAXHEIGHT; X xdiv = (blks / MAXHEIGHT + 1) / MAXWIDTH + 1; X width = (blks / MAXHEIGHT + 1) / xdiv; X } X /* Size of rect for 1 block */ X rectw = MINWIDTH / width + 1; X recth = MINHEIGHT / height + 1; X X /* Open window */ X sprintf(title, "File: %s, %ld blocks", fib->fib_FileName, fib->fib_NumBlock Xs); X newwin.Title = title; X newwin.Width = rectw * width + XLEFT + XRIGHT; X newwin.Height = recth * height + YTOP + YBOTTOM; X X if (win = OpenWindow(&newwin)) X { X SetAPen(win->RPort, 2); X RectFill(win->RPort, XLEFT, YTOP, win->Width - XRIGHT - 1, win->Height X- YBOTTOM - 1); X SetAPen(win->RPort, 3); X return TRUE; X } X return FALSE; X} X X/* bstr -> cstr */ Xchar *btoc_str(to, from) Xchar *to; XBSTR from; X{ X char *cstr = (char *)BADDR(from); X X strncpy(to, cstr + 1, *cstr); X to[*cstr] = '\0'; X X return to; X} X X/* Reads sector at offset 'sector' from disk ('sector' must be a multiple of 51 X2) */ XBYTE *ReadSector(sector, buf, len) Xlong sector; XBYTE *buf; Xlong len; X{ X io->io_Command = CMD_READ; X io->io_Length = len; X io->io_Data = (APTR)buf; X io->io_Offset = sector; X DoIO((struct IORequest *)io); X return (io->io_Error == 0) ? buf : NULL; X} X X/* Find device by task */ Xstruct DeviceNode *TaskDevice(task) Xstruct MsgPort *task; X{ X struct DeviceNode *devlist; X X Forbid(); X devlist = (struct DeviceNode *)BADDR(((struct DosInfo *)BADDR(((struct Root XNode *)(DOSBase->dl_Root))->rn_Info))->di_DevInfo); X for (;devlist; devlist = (struct DeviceNode *)BADDR(devlist->dn_Next)) X if (devlist->dn_Type == DLT_DEVICE) X { X if (task == devlist->dn_Task) { Permit(); return devlist; } X } X X Permit(); X return NULL; X} X X/* Reads block n of *partition* */ Xvoid ReadBlock(n) Xlong n; X{ X ReadSector((blk_offset + n) * blk_size * 4, secbuf, blk_size * 4); X} X X/* Get partition characteristics, open device */ Xint setup(dev) Xstruct DeviceNode *dev; X{ X char devname[32]; X struct FileSysStartupMsg *msg = (struct FileSysStartupMsg *)BADDR(dev->dn_S Xtartup); X ULONG *env = (ULONG *)BADDR(msg->fssm_Environ); X long err; X X port = CreatePort(0, 0); X if (!port) X { X error("No port!\n"); X return FALSE; X } X io = CreateStdIO(port); X if (!io) X { X error("No IO request!\n"); X return FALSE; X } X err = OpenDevice(btoc_str(devname, msg->fssm_Device), msg->fssm_Unit, (stru Xct IORequest *)io, msg->fssm_Flags); X if (err) X { X error("Device not opened\n"); X return FALSE; X } X DevOpen = TRUE; X blk_size = env[DE_SIZEBLOCK]; X blk_offset = env[DE_LOWCYL] * env[DE_BLKSPERTRACK] * env[DE_NUMHEADS]; X root_blk = (env[DE_BLKSPERTRACK] * env[DE_NUMHEADS] * (env[DE_UPPERCYL] - e Xnv[DE_LOWCYL] + 1) - 1 + env[DE_RESERVEDBLKS]) / 2; X secbuf = (long *)AllocMem(4 * blk_size, env[DE_MEMBUFTYPE]); X if (!secbuf) X { X error("No sector buffer!\n"); X return FALSE; X } X return TRUE; X} X X/* Close device */ Xvoid release() X{ X if (secbuf) FreeMem((char *)secbuf, 4 * blk_size); X if (DevOpen) CloseDevice((struct IORequest *)io); X if (io) DeleteStdIO(io); X if (port) DeletePort(port); X} X X/* Displays blocks used by file described by fib */ X/* For OFS/FFS !!! */ Xvoid get_blocks(fib, node, device) XFIB *fib; Xstruct DeviceList *node; Xstruct DeviceNode *device; X{ X long key = fib->fib_DiskKey, data1 = blk_size - 51, used, i, x, y; X int quit; X struct IntuiMessage *msg; X X if (prepare_window(fib, device)) X { X do { X Forbid(); X if (device->dn_Task != node->dl_Task) X { X error("Disk not in drive!\n"); X break; X } X ReadBlock(key); /* Read either File header or file list block */ X Permit(); X used = secbuf[2]; /* num blocks described here */ X /* Draw blocks */ X for (i = 0; i < used; i++) X { X cvt_point(&x, &y, secbuf[data1 - i]); X RectFill(win->RPort, x, y, x + rectw - 1, y + recth - 1); X } X /* Extension blocks ? */ X key = secbuf[blk_size - 2]; X } while (key != 0); X X /* Wait for window close */ X quit = FALSE; X while (!quit) X { X WaitPort(win->UserPort); X while (msg = (struct IntuiMessage *)GetMsg(win->UserPort)) X { X quit = msg->Class == CLOSEWINDOW; X ReplyMsg((struct Message *)msg); X } X } X CloseWindow(win); X } X} X X/* Display blocks used by file name */ Xvoid disp_blocks(name) Xchar *name; X{ X FIB *fib = (FIB *)AllocMem(sizeof(FIB), 0L); X INFO *info = (INFO *)AllocMem(sizeof(INFO), 0L); X BPTR lock = Lock(name, SHARED_LOCK); X struct DeviceList *node; X struct DeviceNode *device; X X if (fib && info) X if (lock) X if (Info(lock, info) && Examine(lock, fib)) X if (fib->fib_DirEntryType >= 0) error("Only for files!\n") X else if (info->id_UnitNumber < 0) error("Only on OFS or FFS dis Xks\n") /* Test detects RAM: ... */ X else X { X node = (struct DeviceList *)BADDR(info->id_VolumeNode); X if (node == 0) error("Disk not in drive\n") X else X if (device = TaskDevice(node->dl_Task)) X { X if (setup(device)) get_blocks(fib, node, device); X release(); X } X else error("Couldn't find disk's device!\n") X } X else error("Couldn't get info on file\n") X else error("No such file\n") X else error("No memory !\n"); X X if (lock) UnLock(lock); X if (fib) FreeMem((char *)fib, sizeof(FIB)); X if (info) FreeMem((char *)info, sizeof(INFO)); X} X X/* Display blocks used by files passed as parms X Works from WB or CLI */ Xvoid main(argc, argv) Xint argc; Xchar **argv; X{ X int i; X X cli = (argc != 0); X X if (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library" X, 0L)) X if (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0L)) X if (argc == 0) /* WB */ X { X struct WBStartup *msg = (struct WBStartup *)argv; X X for (i = 1; i < msg->sm_NumArgs; i++) X if (msg->sm_ArgList[i].wa_Name[0] != '\0') /* A dir */ X { X CurrentDir(msg->sm_ArgList[i].wa_Lock); X disp_blocks(msg->sm_ArgList[i].wa_Name); X } X } X else if (argc == 1) error(USAGE) X else X for (i = 1; i < argc; i++) disp_blocks(argv[i]); X else error("No graphics library !\n") X else error("No intuition library !\n"); X X if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase); X if (GfxBase) CloseLibrary((struct Library *)GfxBase); X if (_Backstdout) Close(_Backstdout); X} SHAR_EOF echo "extracting blocks.doc" sed 's/^X//' << \SHAR_EOF > blocks.doc X This is a small program to graphically dsplay the blocks used by a file X(you can thus see how fragmented it is). X XUsage X----- X X from the CLI: X X blocks <file1> <file2> ... X X will display the blocks used by file1, file2, ... X Note that this program detaches from the CLI, don't 'RUN' it ! X X from the WB: X X click on the icon for blocks (non provided, sorry!), then X select the other icons of the files you want, double-clicking X on the last one (you will have to hold the shift key down, of X course). X X X A window will be opened for the first file, when you close it, another X one for the second file will appear, and so on. X X The window opened will be a representation of the disk containing the X file, with cylinders presented vertically (if possible). The lit X pixels represent the blocks used by the file. X X XDistribution X------------ X X This software is placed in the public domain. X X X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ XDavid Gay X "(p.suiv :=: q.prec.suiv).prec :=: q.prec" X You don't want to know about this language ! X XGAY_D@ELMA.EPFL.CH, or GAY_D%ELMA.EPFL.CH@CLSEPF51.bitnet X(till mid-august 89) X X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ X X SHAR_EOF echo "extracting blocks.uu" sed 's/^X//' << \SHAR_EOF > blocks.uu X Xbegin 644 blocks XM```#\P`````````#``````````(```#*```$>@```48```/I````RDCG?OY+V XM[P`T)$@D`$GY`````"QX``0I3@!:*4\`8D*L`%Y'^0``!'!R`"`\````*F`"B XM)L%1R/_\)FX!%'``(CP``#``3J[^SBEK`)@`5DJK`*QG``%080`"G"(L`%8L4 XM;`4(3J[_H"E``%8@:P"LT<C1R")H`!#3R=/)(`)R`!(9*`DF`=*!T(%:@.6(0 XMT*P`%"E``!1![```+'@`!$ZN_R(B0"\`(FD`$$?I`.8@1"`#8`(6V%'(__P6" XM_``@($H@`F`"%MA1R/_\0ALI2P!V($0@`V`"%MA1R/_\0A-%Z0!L*4H`&D7ZY XM_Q8B_````#DF">2+(M)"DD7Z`38@/````-T2VE'(__Q*K`"<9P``&D'L`(8BI XM""0\```#[2QL!0A.KO_B*4``<BQX``1.KO]\(BP`E"0L`)@H+`"(+&P%"$ZN; XM_W8F3DJ`9@``("1?(FH`$"(L`%9.KO^F($HL>``$3J[_''!H8```)B1`(E]%. XMZO^D0>H`2D'H``0@*``$(4D`!"*((T``!"!`((EP`"QX``1.KO]V(DLL>``$A XM3J[^8DS??WY.=2EK`#H`)@:L````@``F80`!0$7Z`/`I2@`:80`!3"E``%XO5 XM`"1`("H`)&<2+&P%""!`(B@``"E!`%9.KO^"(BH`(&<:)#P```/M3J[_XBE`: XM`&YG"N6(($`G:``(`*0@;`!>+PA(;``B(&@`)"EH``0`=DZZ`0A.N0``#3!P: XM`&```(0````Y`````"`/2.=^_BI`+'@`!$GY`````"E/`&)A``"ND\DL>``$X XM3J[^VB9`*6L`.@`F!JP```"``"8@:P"`T<C1R")H``S3R=/)*5$`'B%1``PB) XM+`!6+&P%"$ZN_X)(>@"$3KD```TP6$\B+``>+&P%"$ZN_V0B+`!63J[_IG``Z XM("P`3F<$($!.D$ZY```1N"QX``0B;`4(3J[^8DZY```(UDJL`%YG&B(L`&YG/ XM!$ZN_]PL>``$3J[_?")L`%Y.KOZ&+FP`8DS??WY.=4/L`'IP`$ZN_=@I0`4(M XM9P``!$YU<&1@G$'K`%Q.KOZ`0>L`7$ZN_HQ.=0``3OD```C4<&$```/L````T XM!0````$```+&```"M````HP```(<```#(@````,````"````)````CP````.* XM`````````_(```/I```$>DY5__P@+`3@(BP$\$ZZ#_HO0```("T`$"(O``!.K XMNA`*(BP$Y$ZZ#^)4@"!M``@@@"`M`!`B+`3P3KH/[B`L!.A.N@_&<@K0@2!M? XM``P@@$Y=3G5.5?_P2.<S`B!M``P@*``<Y8`@0"(H``CE@2!!("@`#"(H`!1.K XMN@^0+@`@*``HD*@`)"P`4H9P0D8`OH!N)BE'!/`@!B(\```"?$ZZ#XI2@"E`C XM!.`@!B(L!.!.N@]Z*4`$[&`Z*4`$\"`&(@=.N@](<D)&`4ZZ#V!2@"(\```"O XM?"]``!1.N@]04H`I0`3@("\`%"(L!.!.N@\^*4`$['!DT(`B+`3L3KH/+E*`! XM*4`$Y'!0(BP$\$ZZ#QY2@"E`!.@@;0`(4(@B;0`(+RD`@"\(2&P`T$AL!'!.\ XMN@XV3^\`$$'L!'`I2`"Z("P$Y"(L!.Q.N@[$6(`Y0`"D("P$Z"(L!/!.N@ZR; XM<@O0@3E``*9![`"@+&P%`$ZN_S0I0`3<2H!G4B!`(F@`,G`"+&P%!$ZN_JH@% XM;`3<,"@`"$C`5X`R*``*2,%5@2]``!0O00`8(F@`,G`"<@HD+P`4)B\`&$ZN3 XM_LX@;`3<(F@`,G`#3J[^JG`!8`)P`$S?0,Q.74YU3E7__"`M``SE@"!`0^@`: XM`1(02(%(P2\!+PDO+0`(+T``#$ZZ#$@@;P`,$!!(@"!M``A",```(`A.74YUX XM3E4``$CG`!(F;P`4(&P$Q#%\``(`'"%M`!``)"%+`"@@;`3$(6T`"``L(D@LN XM>``$3J[^."!L!,00*``?2@!F!"!+8`*1R"`(3-](`$Y=3G5(YP`R)F\`$"QXF XM``1.KO]\(&P%""!H`"(@*``8Y8`@0"(H``3E@21!8!Y*J@`$9A*WZ@`(9@PLQ XM>``$3J[_=B`*8!0@$N6`)$`@"F;>+'@`!$ZN_W9P`$S?3`!.=4Y5```@+`30Z XMT*T`""(L!,Q.N@T^Y8`B+`3,Y8$O`2\L!-@O`&$`_RY.74YU3E7_V$CG,#(FB XM;P!$("L`'.6`)D`@*P`(Y8`D0$*G0J=.N@XB4$\I0`3`9B)*K`3T9Q9P"2(L1 XM`')![`#F)`@F`"QL!0A.KO_0<`!@``$*+RP$P$ZZ#;183RE`!,1*@&8H2JP$T XM]&<<<@\O00`4(BP`<D'L`/HD""8O`!0L;`4(3J[_T'``8```T"\K``1(;?_<V XM80#^6E!/($`@$R)L!,0B*P`,+'@`!$ZN_D1*@&<B2JP$]&<6<!(B+`!R0>P!N XM&B0()@`L;`4(3J[_T'``8```B'`!*4`$R"(J``0I003,("H`)"(J`!1.N@P\" XM(BH`#$ZZ##0I0`30("H`%"(J``Q.N@PD(BH`*)*J`"12@4ZZ#!;0J@`84X#BC XMB"E`!-0@+`3,Y8`B*@`P+'@`!$ZN_SHI0`389B!*K`3T9Q9P$B(L`')![`%"+ XM)`@F`"QL!0A.KO_0<`!@`G`!3-],#$Y=3G4O#DJL!-AG$B`L!,SE@")L!-@L5 XM>``$3J[_+DJL!,AG#")L!,0L>``$3J[^/DJL!,1G"B\L!,1.N@LB6$]*K`3`X XM9PHO+`3`3KH+/EA/+%].=4Y5_^A(YS<R)F\`1"1O`$@@;0`(+A!\S=RL!,PO/ XM"B\(80#[GE!/2H!G``$6+'@`!$ZN_WP@:@`(L>L`"&<B2JP$]&<``*1P$R(L* XM`')![`%J)`@F`"QL!0A.KO_08```BB\'80#]PEA/+'@`!$ZN_W8@;`38+B@`* XM"'H`8%(@!I"%Y8`@;`38T<`O$$AM_^Q(;?_P80#ZVD_O``P@+?_P(BP$Y-*`3 XM4X$D+?_L)BP$Z-:"4X,O00`@(&P$W")H`#(B`B0O`"`L;`4$3J[^SE*%NH=MY XMJB`L!,SE@"!L!-C1P"XH__A*AV8`_T9^`&!$(&P$W"!H`%8L>``$3J[^@&`<W XM#*H```(``!17P$0`2(!(P"X`(DHL>``$3J[^AB!L!-P@:`!6+'@`!$ZN_HPD5 XM0"`*9LY*AV>X(&P$W"QL!0!.KO^X3-],[$Y=3G5.5?_X2.<Q,B9O`"@@/```@ XM`01R`"QX``1.KO\Z+T``''`D<@!.KO\Z)$`@2B](`!@B"W3^+&P%"$ZN_ZPN0 XM`$JO`!QG``$R(`IG``$L2H=G``$,(@<D"DZN_XY*@&<``.0B!R0O`!Q.KO^:4 XM2H!G``#4(&\`'"`H``1*@&L>2JP$]&<``0QP$"(L`')#[`&2)`DF`$ZN_]!@Q XM``#V("H`!$J`:AY*K`3T9P``YG`9(BP`<D/L`;8D"28`3J[_T&```-`@*@`<T XMY8`F0"`+9AY*K`3T9P``O'`2(BP`<D/L`>HD"28`3J[_T&```*8O*P`(80#[) XMDEA/)$`@"F<F+PIA`/P,6$]*@&<0+PHO"R\O`"1A`/VH3^\`#&$`_5`D;P`8\ XM8&XD;P`82JP$]&=D<!TB+`!R0>P"$B0()@`L;`4(3J[_T&!,2JP$]&=&<!HBU XM+`!R0>P"3B0()@!.KO_08#)*K`3T9RQP#2(L`')![`*&)`@F`$ZN_]!@&$JL( XM!/1G$G`,(BP`<D'L`J(D""8`3J[_T$J'9PHB!RQL!0A.KO^F2J\`'&<2(F\`K XM'"`\```!!"QX``1.KO\N(`IG#")*<"0L>``$3J[_+DS?3(Q.74YU2.<S$BXO^ XM`!PF;P`@2H=6P$0`2(!(P"E`!/1#[`*^<``L>``$3J[]V"E`!0!G``"H0^P"S XMT'``3J[]V"E`!01G>$J'9CI^`7P(8"P@:P`DT<8B:``$2A%G&B(0+&P%"$ZNE XM_X(@:P`DT<8O*``$80#]QEA/4H=0AKZK`!QMSF!T<`&^@&8>2JP$]&=H<!(B$ XM+`!R0>P"XB0()@`L;`4(3J[_T&!0+`!8BV`*+QMA`/V(6$]2AKR';?)@.DJL[ XM!/1G-'`6(BP`<D'L`PHD""8`+&P%"$ZN_]!@'$JL!/1G%G`7(BP`<D'L`SHD1 XM""8`+&P%"$ZN_]!*K`4`9PPB;`4`+'@`!$ZN_F)*K`4$9PPB;`4$+'@`!$ZN0 XM_F)*K`!R9PPB+`!R+&P%"$ZN_]Q,WTC,3G5.=4YU3E7_Q$CG)S`F;P!<)&\`O XM8'X`?`!Z`'``&WP`(/_[<@`K0?_V=/\K0O_R0>W_T!M`__$;0/_\*T'_Y"M!R XM_^@K2/_,2A-G0G``$!-R&%U!:SBP>Q`(9O9.^Q`$`"-@```@`"!@```6`"M@) XM```,`"U@```"?@%@#GP!8`IZ`6`&&WP``?_\4HM@NA`3<C"P`68&4HL;0?_[O XM<"JP$V80(%)#Z``$)(DK4/_V4HM@#DAM__8O"TZZ!7!03]?`$!-R+K`!9B92% XMBW`JL!-F$"!20^@`!"2)*U#_\E*+8`Y(;?_R+PM.N@5"4$_7P!`3<FRP`68*J XM&WP``?_Q4HM@"')HL`%F`E*+$!MR`!(`&T#_\'`P74!K``)4LGL`"&;T3OL`L XM!`!C8``"*@!S8``!Z`!88``!?@!X8``!>`!P8``!7@!O8``!#`!U8```X@!D= XM8````DHM__%G#"!20^@`!"2)(!!@"B!20^@`!"2)(!`K0/_L;`IR`42M_^PKH XM0?_H2JW_Z&<$<"U@"DH&9P1P*V`"<"`;0/_0<``0!B(M_^B"@'``$`6"@&<(> XM4JW_S%*M_^0O+?_L+RW_S$ZZ`])03RM`_\@@+?_R2H!J!G(!*T'_\B`M_\@B& XM+?_RDH!([0`"_\1O+B!M_\PB2-/!8`(2V%.`9/IP`!`M__LB+?_$(&W_S&`"- XM$,!3@63Z("W_\BM`_\C1K?_D0>W_T"M(_\Q*!V<``5`;?``@__M@``%&2BW_E XM\6<,(%)#Z``$)(D@$&`*(%)#Z``$)(D@$"M`_^Q@`/]B2BW_\6<,(%)#Z``$< XM)(D@$&`*(%)#Z``$)(D@$"M`_^Q*+?_\9Q(@;?_,$/P`,'(!*T'_Y"M(_\PO) XM`"\M_\Q.N@,L4$\K0/_(8`#_*!M\`##_^R`M__)*@&H&<`@K0/_R2BW_\6<,= XM(%)#Z``$)(D@$&`*(%)#Z``$)(D@$"M`_^Q*+?_\9Q8@;?_,$/P`,!#\`'ARU XM`BM!_^0K2/_,+P`O+?_,3KH#"%!/*T#_R'!8L"W_\&8`_KY(;?_03KH"&%A/, XM8`#^L"!20^@`!"2)(E`K2?_,9@A!^@#<*TC_S"!M_\Q*&&;\4XB1[?_,*TC_" XMY"`M__)*@&LJL<!O)BM`_^1@('`!*T#_Y"!20^@`!"2)(!`;0/_00BW_T6`&A XM<`!@``",("W_Y"(M__:R@&P(=``K0O_V8`21K?_V2@=G-E.M_^1M&'``(&W_U XMS!`8+P`K2/_,(&T`$$Z06$]@XE.M__9M2'``$"W_^R\`(&T`$$Z06$]@Z%.MO XM__9M$G``$"W_^R\`(&T`$$Z06$]@Z%.M_^1M&'``(&W_S!`8+P`K2/_,(&T`& XM$$Z06$]@XB`+3-\,Y$Y=3G4``$Y5__9(YP$P)F\`'B1O`"(K;0`0__8>&DH'1 XM9S1P);X`9B*P$F8$4HI@&B\+2&W_]B\*80#[S$_O``PK0/_Z9P0D0<``0L XM!R\`3I-83V#&3-\,@$Y=3G5.5?]T2.<!,"9O`*!^`'`@OH!L``""$!-R(+`!4 XM9PQR";`!9P9R"K`!9@12BV#H2A-G9"`'Y8!2AT'M_W31P"1(<"*P$V8F4HLD5 XMBTH39PIP(K`39P12BV#R2A-F#$AX``%.N@!:6$]@ID(;8*(DBTH39Q@0$W(@& XML`%G$'()L`%G"G(*L`%G!%*+8.1*$V8"8`9"&V``_WI*AV<&0>W_=&`$(&P`N XM7B\(+P=.NOG,0I=.N@`,3.T,@/]H3EU.=4[Y````&````````$CG(#`F;P`0B XM)$M*$F<D<``0$D'L`VT(,``!"`!G"G(`$@!T()*"8`1R`!(`%(%2BF#8(`M,K XMWPP$3G4``````````'!A(F\`""!O``0@+P`,(@A@!!#99PA3@&3X8`9"&%.`R XM9/H@`4YU("\`""!O``1.5?_T(D]R"DZZ`>@&00`P$L%*@&;P(`D0X;_)9OI". XM$)"/3EU.=0``("\`""!O``1.5?_T(D\B``)!``<&00`P$L'FB&;P(`D0X;_)J XM9OI"$)"/3EU.=0``,#$R,S0U-C<X.6%B8V1E9B`O``@@;P`$0^\`!#(``D$`V XM#Q+[$-SHB&;R(`DB#UB!$.&RB6;Z0A"0@4YU(&\`!")(<@!P`"\"#!``*V<&Y XM#!``+68"4D@0&`0``#!M$@P```EN#"0!Y8'2@M*!TH!@Y@P1`"UF`D2!)!\@9 XM"%.`(&\`"""!D(E.=2\'+B\`"%*L!/P@!R!L!/@0P"E(!/@N'TYU3E4``$CG6 XM`#`F;P`0)&\`%$*L!/PI2P3X2&T`$"\*2'K_QDZZ_5(@;`3X0A`@+`3\3.T,A XM`/_X3EU.=4CG`!(F;P`,%WP`_P`(,'S__R=(`!0G2``8(DMP,"QX``1.KO\NS XM3-](`$YU2.<`$B9O``Q*JP`*9PHB2RQX``1.KOZ8%WP`_P`(</\G0``4<``0S XM*P`/+'@`!$ZN_K`B2W`B3J[_+DS?2`!.=4CG,``D`"8!2$)(0\3!QL#`P=1#, XM2$)"0M""3-\`#$YU2H!J```>1(!*@6H```Q$@6$``"!$@4YU80``&$2`1(%./ XM=4J!:@``#$2!80``!D2`3G4O`DA!-`%F```B2$!(04A"-`!G```&A,$P`DA`; XM-`"$P3`"2$(R`B0?3G4O`W80#$$`@&0```;AF5%##$$(`&0```;IF5E##$$@V XM`&0```;EF55#2D%K```&XYE30S0`YJA(0D)"YJI(0X#!-@`P`C0#2$'$P9""Y XM9```"%-#T(%D_G(`,@-(0^>X2$#!028?)!].=4CG`#(F;P`0(`MF!'``8"9P< XM,"(\``$``2QX``1.KO\Z)$`@"F<.%7P`!0`(0BH`"25+``X@"DS?3`!.=4CG4 XM`S(F;P`8+B\`''#_+'@`!$ZN_K8L``P&`/]F!'``8&9P(B(\``$``4ZN_SHD* XM0"`*9@IP`!`&3J[^L&!()4L`"B`'%4``"15\``0`"$(J``X51@`/D\E.KO[:B XM)4``$"`+9P@B2DZN_IY@&D'J`!@E2``40>H`%"5(`!Q"J@`8%7P``@`@(`I,& XMWTS`3G4``$CG`#(F;`4,(`MG%"13(DL@*P`(+'@`!$ZN_RXF2F#HD<@I2`40W XM*4@%#$S?3`!.=0```^P````!`````@``#>X````````#\@```^H```$<````H XM`````````````````0````$```#F3OD`````````````````````````````O XM````````````````````````````````````````````````````````````` XM``````````````````````````````````````!D;W,N;&EB<F%R>0`J````3 XM!]!B;&]C:W,``````(P``````````0``````````__\```(```,`#@``````S XM`````````````````````````````````49I;&4Z("5S+"`E;&0@8FQO8VMS2 XM``!.;R!P;W)T(0H`3F\@<&]R="$*`$YO($E/(')E<75E<W0A"@!.;R!)3R!RJ XM97%U97-T(0H`1&5V:6-E(&YO="!O<&5N960*``!$979I8V4@;F]T(&]P96YE@ XM9`H``$YO('-E8W1O<B!B=69F97(A"@``3F\@<V5C=&]R(&)U9F9E<B$*``!$6 XM:7-K(&YO="!I;B!D<FEV92$*`$1I<VL@;F]T(&EN(&1R:79E(0H`3VYL>2!F4 XM;W(@9FEL97,A"@``3VYL>2!F;W(@9FEL97,A"@``3VYL>2!O;B!/1E,@;W(@N XM1D93(&1I<VMS"@!/;FQY(&]N($]&4R!O<B!&1E,@9&ES:W,*`$1I<VL@;F]T2 XM(&EN(&1R:79E"@``1&ES:R!N;W0@:6X@9')I=F4*``!#;W5L9&XG="!F:6YDS XM(&1I<VLG<R!D979I8V4A"@!#;W5L9&XG="!F:6YD(&1I<VLG<R!D979I8V4AW XM"@!#;W5L9&XG="!G970@:6YF;R!O;B!F:6QE"@``0V]U;&1N)W0@9V5T(&EN4 XM9F\@;VX@9FEL90H``$YO('-U8V@@9FEL90H`3F\@<W5C:"!F:6QE"@!.;R!M: XM96UO<GD@(0H``$YO(&UE;6]R>2`A"@``:6YT=6ET:6]N+FQI8G)A<GD`9W)AX XM<&AI8W,N;&EB<F%R>0``8FQO8VMS(#QF:6QE;F%M93X*``!B;&]C:W,@/&9I& XM;&5N86UE/@H``$YO(&=R87!H:6-S(&QI8G)A<GD@(0H``$YO(&=R87!H:6-SV XM(&QI8G)A<GD@(0H``$YO(&EN='5I=&EO;B!L:6)R87)Y("$*`$YO(&EN='5I& XM=&EO;B!L:6)R87)Y("$*`````"`@("`@("`@("@H*"@H("`@("`@("`@("`@" XM("`@("`@2!`0$!`0$!`0$!`0$!`0$(2$A(2$A(2$A(00$!`0$!`0@8&!@8&!6 XM`0$!`0$!`0$!`0$!`0$!`0$!`0$0$!`0$!""@H*"@H("`@("`@("`@("`@(": XM`@("`@("`A`0$!`@("`@("`@("`@*"@H*"@@("`@("`@("`@("`@("`@("!(> XM$!`0$!`0$!`0$!`0$!`0A(2$A(2$A(2$A!`0$!`0$!"!@8&!@8$!`0$!`0$!5 XM`0$!`0$!`0$!`0$!`1`0$!`0$(*"@H*"@@("`@("`@("`@("`@("`@("`@("A X@$!`0$"````````/L`````0````(```"4`````````_("= X`` Xend Xsize 6692 SHAR_EOF echo "End of archive 1 (of 1)" # if you want to concatenate archives, remove anything after this line exit