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.