amiga-request@abcfd20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (10/09/90)
Submitted-by: peterc@softway.sw.oz.au (Peter Chubb) Posting-number: Volume 90, Issue 267 Archive-name: unix/du-1.4/part01 [ uuencoded executable enclosed ...tad ] Here's an update to du 1.2. This update fixes a bug that meant some files were reported with the wrong size, adds a -v option (for verbose -- the default is now only to list directories) and a -T option (how big would a tar file be?). Unfortunately, that increases the size of the executable to 1640 bytes. du prints out a summary of disc usage for a file or directory. It is pure, and thus can be made resident. It takes up only 1640 bytes. #!/bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 1 (of 1)." # Contents: du.c du.doc du.uu # Wrapped by tadguy@abcfd20 on Mon Oct 8 19:27:47 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'du.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'du.c'\" else echo shar: Extracting \"'du.c'\" \(8565 characters\) sed "s/^X//" >'du.c' <<'END_OF_FILE' X; /* To make, just execute me Xlc -v -j73 -j104 -O -cusf -M du Xblink du.o lib lib:lcr.lib nd sc sd batch quiet Xprotect du +p Xquit X;lcr.lib there for long division routine only X*/ X/************************************************************************ X * du.c -- calculate disk usage for files in a directory tree * X * * X * Copyright 1989,1990 Peter Chubb * X * All rights reserved * X * * X ************************************************************************/ X Xstatic const char RCSid[] = "$Id: du.c,v 1.4 90/08/08 20:51:48 peterc Exp $"; X X/* X * Written: X * 10 July 1989 Peter Chubb X * X * This is not guaranteed to work with any file systems other than the X * old (Slow) file system,. and the new (Fast) file system, as it X * contains code that `understands' the shape of these two filesystems. X * X * $Log: du.c,v $ X * Revision 1.4 90/08/08 20:51:48 peterc X * Moved knowledge about filesystems into table. X * Added const keyword where appropriate to try to give optimiser some hints. X * Moved constant repeated strings into named variables to try to X * save some space. X * X * Revision 1.3 90/06/11 11:10:11 peterc X * Added ability to cope with quoted filenames. X * Also fixed large file bug. X * X * Revision 1.2 90/06/06 20:07:37 peterc X * Added options to allow selection of blocksize; X * added allowance for file extension blocks. X * X * X */ X X#include <libraries/dos.h> X#include <proto/dos.h> X#include <proto/exec.h> X#include <exec/memory.h> X#include <string.h> X#include <stdlib.h> X#include <dos.h> X X#ifndef min X# define min(a, b) ((a) < (b) ? (a) : (b)) X#endif X X#define ABSEXECBASE ((struct ExecBase **)4L) Xtypedef unsigned short ushort; X Xvoid RawDoFmt(const char *fmt, const void *arglist, void (*prbuf)(), char *obuf); X#pragma syscall RawDoFmt 20a ba9804 X Xvoid __asm prbuf(const register __d0 char c); X#define R_A3 (8+3) X Xstruct DosLibrary *DOSBase; X Xvoid outval(const char *fmt,...); X Xlong __regargs du(const BPTR dir, const long verbosity, X const unsigned long level, const X struct fsdesc *fp); X Xlong __asm __saveds dumain(register __a0 char *cmd); Xunsigned long __regargs numBlocks(const LONG size, const struct fsdesc *fp); X X#define SFS 0 X#define FFS 1 X X#define SECSIZE 512 X Xconst char spaces[] = " "; Xconst char fmt[] = "%-32ls %6ld\n"; X Xconst struct fsdesc X{ X const char fs_tnam; /* flag to choose this fstype */ X const ushort fs_dbytes; /* bytes per data block */ X const ushort fs_fxdovhd; /* fixed per-file overhead */ X const ushort fs_varovhd; /* extra block for every fs_varovhd blocks */ X} fstab[] = /* real file systems should be before fake ones such as tar */ X{ X { /* Slow file system */ X 'S', X SECSIZE - (6 * sizeof(long)), /* data block has 6 long header */ X 1, /* at least one header block */ X SECSIZE/sizeof(long) - 56, /* and a block full of pointers, with a 56 long header */ X }, X { /* Fast file system */ X 'F', X SECSIZE, /* no header in data block */ X 1, /* at least one header block */ X SECSIZE/sizeof(long) - 56 /* block full of pointers, 56 long header */ X }, X { /* posix tar archive */ X 'T', X SECSIZE, X 1, X 0 X }, X}; X X#define NFILESYS (sizeof(fstab) / sizeof(fstab[0])) X X/* main routine -- parse arguments, then call du() to do the work */ Xlong __asm __saveds Xdumain(register __a0 char *cmd) X{ X const struct fsdesc *fp = (struct fsdesc *) 0; X register char *p; X long c; X long total; X long verbosity = 1; X BPTR dir; X struct Library *foo; X struct InfoData infodata; X X if (!(foo = OpenLibrary("dos.library", 0))) X return RETURN_ERROR; X DOSBase = (struct DosLibrary *) foo; X X while ((c = *cmd++) == ' ' || c == ' ') X ; X X while ((char)c == '-') X { X c = *cmd++; X switch((char)c) X { X case 's': X verbosity = 0; X break; X X case 'v': X verbosity++; X break; X X default: X if (fp) { X outval ("File system blocksize specified twice!\n"); X goto out; X } X for (fp = &fstab[0]; fp < &fstab[NFILESYS]; fp++) { X if (fp->fs_tnam == (char)c) X break; X } X if (!fp) { X outval("Usage: du [-s | -v] [-F | -S | -T] [dirname]\n"); X goto out; X } X break; X } X while ((c = *cmd++) == ' ') X ; X } X p = --cmd; X if (*p == '\"') X { X ++cmd; X while (*p && *p != '\n' && *++p != '\"') X ; X } X else X while (*p && *p != ' ' && *p != '\n') X p++; X *p = '\0'; X X if (p != cmd) { X c = 1; X dir = Lock(cmd, ACCESS_READ); X } else { X c = 0; X (void) CurrentDir(dir = CurrentDir(0L)); X } X if (!dir) { X outval("Can't open %ls\n", cmd); X return RETURN_WARN; X } X X if (!fp) { X Info(dir, &infodata); X for (fp = fstab; fp < &fstab[NFILESYS]; fp++) X if (fp->fs_dbytes == infodata.id_BytesPerBlock) X break; X if (fp == &fstab[NFILESYS]) { X outval("du: unknown filesystem type, blocksize %d\n", infodata.id_BytesPerBlock); X goto out; X } X } X X total = du(dir, verbosity, 0, fp); X X X if (total >= 0) X outval("Total: %ld\n", total); X else X outval("**BREAK**\n\n"); Xout: X if (c == 1) X UnLock(dir); X X CloseLibrary(foo); X return RETURN_OK; X} X X X/* outval -- our equivalent of printf */ Xvoid Xoutval(const char *fmt, ...) X{ X char obuf[200]; X X RawDoFmt(fmt, (&fmt) + 1, prbuf, obuf); X Write(Output(), obuf, strlen(obuf)); X} X X/* du -- calculate and print disc usage */ Xlong __regargs Xdu(dir, verbosity, level, fp) Xconst BPTR dir; /* lock on top of directory tree */ Xconst long verbosity; /* whether to print or not */ Xconst unsigned long level; /* how deep in the tree */ Xconst struct fsdesc *fp; X{ X /* note all these are longword aligned */ X X struct FileInfoBlock fib; X BPTR lck; X long total = 0; X long extra; X BPTR curdir = CurrentDir(dir); X long abort = 0; X X if (Examine(dir, &fib)) { X if (fib.fib_DirEntryType < 0) { /* X * must be the only file specified X * -- always print X */ X Write(Output(), spaces, (long)min(level, sizeof(spaces))); X outval(fmt, fib.fib_FileName, X total = numBlocks(fib.fib_Size, fp)); X } else { X total++; /* for directory block itself */ X while (ExNext(dir, &fib) && abort >= 0) { X if (SetSignal(0, 0) & SIGBREAKF_CTRL_C) X abort = -1; X else { X extra = numBlocks(fib.fib_Size, fp); X if (fib.fib_DirEntryType > 0) { X lck = Lock(fib.fib_FileName, ACCESS_READ); X /* should really check that lock succeeded... */ X extra += (abort = du(lck, verbosity, level+1, fp)); X UnLock(lck); X } X total += extra; X switch (verbosity) { X case 0: /* -s option */ X break; X X case 1: /* default -- print iff directory */ X if (fib.fib_DirEntryType < 0) X break; X /* FALL THROUGH */ X X default: /* verbose -- always print */ X Write(Output(), spaces, (long) min(level, (sizeof spaces))); X outval(fmt, fib.fib_FileName, extra); X } X } X } X } X } X (void) CurrentDir(curdir); X return abort < 0 ? -1 : total; X} X X X X/*----------------------------------------------------------------*/ X/* This stub routine is called from the RawDoFmt routine for each */ X/* character in the string. At invocation, we have: */ X/* D0 - next character to be formatted */ X/* A3 - pointer to data buffer */ X/* Stolen from Lattice-supplied Avail utility */ X/*----------------------------------------------------------------*/ Xvoid __asm prbuf(const register __d0 char c) X{ X char *p = (char *)__builtin_getreg(R_A3); X *p++ = c; X __builtin_putreg(R_A3, (long)p); X X /* It's a pity this doesn't generate X * move.b d0,(a3)+ X * rts X */ X} X X/* numBlocks -- work out how many blocks a file takes */ Xunsigned long __regargs XnumBlocks(const LONG size, const struct fsdesc *fp) X{ X register unsigned long blocks; X /* X * A data block holds fp->fs_dbytes bytes. X * Files also have extension blocks, X * and at least one header block. X * Each header block contains some amount of header info, X * and the remainder is filled with longs, each of which can X * address one block. The number of longs is held as fp->fs_varovhd. X * X * The algorithm used is less efficient than it could be, X * but who cares: the disc access time swamps it. X */ X X /* number of data blocks + fixed file overhead */ X blocks = ((size + fp->fs_dbytes - 1) / fp->fs_dbytes) + fp->fs_fxdovhd;; X /* add in header blocks */ X if (fp->fs_varovhd) X blocks += (blocks / fp->fs_varovhd); X X return blocks; X} END_OF_FILE if test 8565 -ne `wc -c <'du.c'`; then echo shar: \"'du.c'\" unpacked with wrong size! fi # end of 'du.c' fi if test -f 'du.doc' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'du.doc'\" else echo shar: Extracting \"'du.doc'\" \(3018 characters\) sed "s/^X//" >'du.doc' <<'END_OF_FILE' XDU 1.4 AMIGA DU 1.4 X XNAME X du -- print out disc usage X XSYNOPSIS X du [ -s | -v ] [ -S | -F | -T] [ filename ] X XDESCRIPTION X X du prints out a summary of disc usage for a X file or directory. It is pure, and thus can X be made resident. It takes up only 1640 X bytes. X X X The options to du are: X X -v verbose listing. du usually prints out X only total directory contents. With the X -v option, du prints out the block size X of every file. X X -s short listing. Print only the total X number of blocks used. X X -S Calculate the number of blocks used as X if by the old (Slow) 488 byte-block X file system. X X -F Calculate the number of blocks used as X if by the new (Fast) 512 byte-block file X system. X X -T Calculate the number of blocks that X would be used by a POSIX tar format X archive. Note that when this option is X used, the resulting file size will be X greater than the option given, except X when made on a raw device such as RDF:. X Moreover, most tar archivers round the X size of the output file up to the X nearest block boundary (often 10k). X X Using the -S and -F options, one can easily X work out whether a directory will fit when X moved between floppy and hard disc. Without X either option, du interrogates the file X system to work out the blocksize. X XCAVEATS X X du correctly accounts for directory blocks X and file list blocks on current versions of X AmigaDOS file systems. It will work X incorectly on MS-DOS volumes mounted via X msh: or crossdos. X XAUTHOR X Peter Chubb X peterc@softway.sw.oz.au X (... !uunet!munnari!softway.sw.oz!peterc) X XCHANGES X Version 1.2: First released version. X X Version 1.3: Fixed bug when calculating X blocksize for moderately large X files, and an off-by-one bug X for small files. X X Version 1.4: Moved info about files into X separate table, to allow easy X extension to new filesystems. X (It's still not flexible enough, X though). X X XDISTRIBUTION X X Copyright 1990 Peter Chubb X All rights reserved. X X This program and its associated X documentation may not be distributed for X profit. It may be distributed provided X X a) no charge is made other than for Xreasonable copying and media expenses, X X b) no change is made to the source, X documentation or binary, that is not clearly X marked as being a change, and X X c) all files are provided. These comprise: X du.doc -- this documentation file X du -- the program binary (or X du.uu, its uuencoded form) X du.c -- the program source. X X X This program is not warranted, or X guaranteed. You get exactly what you paid X for -- a copy of the program to do as you X wish with. If it crashes your machine, X writes rude letters to your spouse, or X explodes in your face ... caveat emptor! X However, to the best of my knowledge and X belief it works as advertised. END_OF_FILE if test 3018 -ne `wc -c <'du.doc'`; then echo shar: \"'du.doc'\" unpacked with wrong size! fi # end of 'du.doc' fi if test -f 'du.uu' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'du.uu'\" else echo shar: Extracting \"'du.uu'\" \(2329 characters\) sed "s/^X//" >'du.uu' <<'END_OF_FILE' Xbegin 664 du XM```#\P`````````"``````````$```%I````'P```^D```%I3E7_O$CG)SI)/ XM^0`````K2/_`)FW_P)'(?`$K2/_H0_H!VB`(+'@`!$ZN_=@O0``@2H!F!G`*E XM8``!N"EO`"``>'H`&(+J`9_9P";J`9_!@=GH`&AL@!7(`$@`$00!S9P973 XM06<&8`A\`&!24H9@3DJM_^AG#DAZ`8YA``(T6$]@``%00>P`7BM(_^A@$"`%7 XM(&W_Z!(0L@!G$%"M_^A![`!V(FW_Z+/(9>1*K?_H9@Y(>@%\80`!^EA/8``!U XM%GH`&(+J`9_8@!7(ML`%G@B1+4XHF2G`BL!)F&E**2A-G)A`3<@JP`6<>U XM4HMP(K`39NQ@%%*+2A-G#A`3<B"P`6<&<@JP`6;L0A.WRF<2>@$B"G3^+&P`Y XM>$ZN_ZPN`&`4>@!R`"QL`'A.KO^"+@`B!TZN_X)*AV80+PI(>@$@80`!<'`%X XM8```JDJM_^AF5B('0>W_Q"0(+&P`>$ZN_XY![`!>*TC_Z&`4<``@;?_H,"@`8 XM`K"M_]AG$%"M_^A![`!V(FW_Z+/(9>!![`!V(FW_Z+/(9A`O+?_82'H`TF$`< XM`1)03V`N0J<@!R(&(&W_Z&$``4183RP`2H9K#B\&2'H`VF$``.Y03V`*2'H`9 XMVF$``.)83W`!NH!F"B('+&P`>$ZN_Z8B;P`@+'@`!$ZN_F)P`$SM7.3_G$Y== XM3G5D;W,N;&EB<F%R>0!&:6QE('-Y<W1E;2!B;&]C:W-I>F4@<W!E8VEF:65DC XM('1W:6-E(0H`57-A9V4Z(&1U(%LM<R!\("UV72!;+48@?"`M4R!\("U472!;E XM9&ER;F%M95T*`$-A;B=T(&]P96X@)6QS"@!D=3H@=6YK;F]W;B!F:6QE<WES6 XM=&5M('1Y<&4L(&)L;V-K<VEZ92`E9`H``%1O=&%L.B`E;&0*`"HJ0E)%04LJM XM*@H*`$Y5_SA(YS`R(&T`"$/M``Q%^@&R1^W_."QX``1.KOWV+&P`>$ZN_\0@= XM2TH89OQ3B)'+(@`D"R8(3J[_T$S?3`Q.74YU3E7^W$CG/Q(F2$CM``/^Y'@`^ XM+BW^Y"('+&P`>$ZN_X)Z`"]``"`B!T'M_NPD"$ZN_YI*@&<``2P@+?[P2H!J+ XM3$ZN_\0L`"XM``AP(;Z`9`0B!V`"(@`O00`D(@9![``O)`@F+P`D3J[_T"`M3 XM_V@@2V$``1XH`"\$2&W^]$AL`%!A`/\Z3^\`#&```-AX`6```+AP`"(`+'@`[ XM!$ZN_LX(```,9P9Z_V```*`@+?]H($MA``#>+@`L+?[H("W^\$J`;S9![?[T; XM(@AT_BQL`'A.KO^L(BT`"%*!+P$O0``H(@8@2V$`_QQ83RH`WH4B+P`D+&P`4 XM>$ZN_Z;8AR`&2H!G1%.`9P)@""`M_O!*@&LV+&P`>$ZN_\0L`"`M``AR(;"!Q XM90(@`2(&0>P`+R0()@!.KO_0+P=(;?[T2&P`4&$`_GY/[P`,+BW^Y"('0>W^# XM["0(+&P`>$ZN_Y1*@&<&2H5J`/\R(B\`("QL`'A.KO^"2H5J!'#_8`(@!$S?S XM2/Q.74YU+P<N`!:'0>L``29(+A].=4Y5__Q(YS$0+@`F2'``,"L`!'(`,BL`F XM`G0`-`$F!]:"4X,O0``0(`-.N@`R(B\`$-"!+@!*:P`&9Q9P`#`K``8O0``0* XM(`<B+P`03KH`0MZ`(`=,WPB,3EU.=0``2H!J```>1(!*@6H```Q$@6$``"!$E XM@4YU80``&$2`1(%.=4J!:@``#$2!80``!D2`3G4O`DA!-`%F```B2$!(04A"/ XM-`!G```&A,$P`DA`-`"$P3`"2$(R`B0?3G4O`W80#$$`@&0```;AF5%##$$(A XM`&0```;IF5E##$$@`&0```;EF55#2D%K```&XYE30S0`YJA(0D)"YJI(0X#!O XM-@`P`C0#2$'$P9""9```"%-#T(%D_G(`,@-(0^>X2$#!028?)!].=0```^P`) XM```!`````0````H````````#\@```^H````?)$ED.B!D=2YC+'8@,2XT(#DP` XM+S`X+S`X(#(P.C4Q.C0X('!E=&5R8R!%>'`@)``@("`@("`@("`@("`@("`@J XM("`@("`@("`@("`@("`@(``E+3,R;',))39L9`H``%,``>@``0!(1@`"```!B X4`$A4``(```$``````````````_(R& X`` Xend Xsize 1640 END_OF_FILE if test 2329 -ne `wc -c <'du.uu'`; then echo shar: \"'du.uu'\" unpacked with wrong size! fi # end of 'du.uu' fi echo shar: End of archive 1 \(of 1\). cp /dev/null ark1isdone MISSING="" for I in 1 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have the archive. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Mail submissions (sources or binaries) to <amiga@uunet.uu.net>. Mail comments to the moderator at <amiga-request@uunet.uu.net>. Post requests for sources, and general discussion to comp.sys.amiga.