[comp.sources.amiga] v90i267: du 1.4 - print out disc usage, Part01/01

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`&AMP(+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`&AMP(+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.