[comp.sources.amiga] v90i201: du 1.2 - calculate disc block usage, Part01/01

Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (07/08/90)

Submitted-by: peterc@softway.sw.oz.au (Peter Chubb)
Posting-number: Volume 90, Issue 201
Archive-name: unix/du-1.2/part01

This is du, a utility to tell you how much disc space a directory tree or
file is actually using.  Moreover, it can tell you how much space the
directory would take if transferred to a floppy using the slow file system,
or if transferred to a hard disc using the fast file system.
It is very small, and is an example of self-compiling code that does not
need a startup routine.

#!/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@xanth on Sun Jul  8 11:28:21 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'\" \(5487 characters\)
sed "s/^X//" >'du.c' <<'END_OF_FILE'
X; /* To make, just execute me
Xlc -v -j73 -O -cusf -M du
Xblink du.o lib lib:lc.lib nd sc sd batch quiet
Xprotect du +p
Xquit
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 char RCSid[] = "$Id: du.c,v 1.2 90/06/06 20:07:37 peterc Exp $";
X
X/*
X * Written:
X *	10 July 1989 Peter Chubb
X * $Log:	du.c,v $
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)
X
Xvoid RawDoFmt(char *fmt, void *arglist, void (*prbuf)(), char *obuf);
X#pragma syscall RawDoFmt 20a ba9804
X
Xvoid __asm prbuf(register __d0 char c);
X#define R_A3 (8+3)
X
Xstruct DosLibrary *DOSBase;
X
Xvoid outval(char *fmt,...);
X
Xlong __regargs du(BPTR dir, long slnt, unsigned long level, unsigned long bsize);
Xlong __asm __saveds dumain(register __a0 char *cmd);
Xunsigned long numBlocks(LONG size, unsigned long bsize);
X
X
X/* main routine -- parse arguments, then call du() to do the work */
Xlong __asm __saveds
Xdumain(register __a0 char *cmd)
X{
X    long total;
X    register char *p;
X    long 	  c;
X    long	  slnt = 0;
X    BPTR	  dir;
X    struct Library *foo;
X    unsigned long bsize = 0;
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++) == ' ')
X	;
X
X    while (c == '-')
X    {
X    	c = *cmd++;
X	switch(c)
X	{
X	case 's':    
X		slnt = 1;
X		break;
X
X	case 'F':
X		if (bsize)
X		{
X		    outval ("File system blocksize specified twice!\n");
X		    return RETURN_ERROR;
X		}
X		bsize = 512;
X		break;
X
X	case 'S':
X		if (bsize)
X		{
X		    outval ("File system blocksize specified twice!\n");
X		    return RETURN_ERROR;
X		}
X		bsize = 488;
X		break;
X
X	default:
X	    outval("Usage: du [-s] [-F | -S] [dirname]\n");
X	    return RETURN_ERROR;
X	}
X	while ((c = *cmd++) == ' ')
X	    ;
X    } 
X    p = --cmd;
X    while (*p != ' ' && *p != '\n' && *p)
X	p++;
X    *p = '\0';
X
X    if (p != cmd) 
X    {
X	c = 1;
X	dir = Lock(cmd, ACCESS_READ);
X    }
X    else 
X    {
X	c = 0;
X	dir = CurrentDir(0L);
X	(void) CurrentDir(dir);
X    }
X    if (!dir) 
X    {
X    	outval("Can't open %ls\n", cmd);
X	return RETURN_WARN;
X    }
X
X    if (!bsize)
X    {
X	Info(dir, &infodata);
X	bsize = infodata.id_BytesPerBlock;
X    }
X
X    total = du(dir, slnt, 0, bsize);
X
X    if (c)
X	UnLock(dir);
X
X    if (total >= 0)
X        outval("Total: %ld\n", total);
X    else
X	outval("**BREAK**\n\n");
X
X    CloseLibrary(foo);
X    return RETURN_OK;
X}
X
X
X/* outval -- our equivalent of printf */
Xvoid
Xoutval(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, slnt, level, bsize)
XBPTR dir; /* lock on top of directory tree */
Xlong slnt; /* whether to print or not */
Xunsigned long level; /* how deep in the tree */
Xunsigned long bsize;
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	    if (!slnt) {
X		Write(Output(), "                                  ", 
X				(long)min(level, 32));
X	    	outval("%ls	%ld\n", fib.fib_FileName, 
X				total = numBlocks(fib.fib_Size, bsize));
X	    }
X	} else 
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, bsize);
X	    	    if (fib.fib_DirEntryType > 0) {
X			lck = Lock(fib.fib_FileName, ACCESS_READ);
X			extra += (abort = du(lck, slnt, level+1, bsize));
X		    	UnLock(lck);
X		    } 
X		    total += extra;
X	    	    if (!slnt && abort >= 0) {
X			Write(Output(), "                                  ",
X					min(level, 32));
X	    	        outval("%-32ls %6ld\n", fib.fib_FileName, extra);
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(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
XnumBlocks(LONG size, unsigned long bsize)
X{
X	register unsigned long	blocks;
X	
X	blocks = (size + bsize - 1) / bsize;
X	blocks += (blocks / ((bsize/4) - 56)) + 1;
X	
X	return blocks;
X}
X
END_OF_FILE
if test 5487 -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'\" \(1862 characters\)
sed "s/^X//" >'du.doc' <<'END_OF_FILE'
XDU			AMIGA			DU
X
XNAME
X	du -- print out disc usage
X
XSYNOPSIS
X	du [ -s ] [ -S | -F ] [ filename ]
X
XDESCRIPTION
X
X	du prints out a summary of disc usage  for
X	a file or directory.  It is pure, and thus
X	can  be  made  resident.  It takes up only
X	1436 bytes.
X	
X	The options to du are:
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
X	    file system.
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.
X	Without either option, du interrogates  the
X	file system to work out the blocksize.
X
XCAVEATS
X	du correctly  accounts for directory blocks
X	and  file  list  blocks  on  AmigaDOS  file
X	systems.    It   will  work  incorectly  on
X	MS-DOS volumes mounted via msh: or crossdos. 
X
XAUTHOR
X	Peter Chubb
X	peterc@softway.sw.oz.au
X
XDISTRIBUTION
X
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
X	reasonable copying and media expenses, 
X
X	b) no change is made to the source,
X	documentation or binary, that is not
X	clearly 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
X		du.c   -- the program source.
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 1862 -ne `wc -c <'du.doc'`; then
    echo shar: \"'du.doc'\" unpacked with wrong size!
fi
chmod +x 'du.doc'
# 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'\" \(2042 characters\)
sed "s/^X//" >'du.uu' <<'END_OF_FILE'
Xbegin 700 du
XM```#\P`````````"``````````$```%(````#0```^D```%(3E7_O$CG+SA)!
XM^0`````K2/_`)FW_P'@`>@!#^@%<<``L>``$3J[]V"]``"!*@&8&<`I@``$Z,
XM*6\`(``P?@`>&W`@OH!G]F!F<``0&W)&D(%G$'(-D(%G)'(@D(%F.'@!8$)*L
XMA6<.2'H!'&$``<AP"F```/PJ/````@!@*$J%9PY(>@$"80`!KG`*8```XBH\$
XM```!Z&`.2'H!%&$``9AP"F```,Q^`!X;<""^@&?V<"V^@&>4)$M3BB9*8`)2V
XMBQ`3<B"P`6<*<@JP`6<$2@!F[$(3M\IG$GP!(@IT_BQL`#!.KO^L+@!@%'P`-
XM<@`L;``P3J[_@BX`(@=.KO^"2H=F#B\*2'H`S&$``2QP!6!@2H5F%"('0>W_Y
XMQ"0(+&P`,$ZN_XXJ+?_8+P5"IR`'(@1A``%(4$\J`$J&9PHB!RQL`#!.KO^F?
XM2H5K#B\%2'H`E&$``.103V`*2'H`E&$``-A83R)O`"`L>``$3J[^8G``3.T<0
XM]/^<3EU.=61O<RYL:6)R87)Y`$9I;&4@<WES=&5M(&)L;V-K<VEZ92!S<&5C<
XM:69I960@='=I8V4A"@!5<V%G93H@9'4@6RUS72!;+48@?"`M4UT@6V1I<FYA8
XM;65="@!#86XG="!O<&5N("5L<PH`5&]T86PZ("5L9`H`*BI"4D5!2RHJ"@H`D
XM("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@(```)6QS"25L9`H`,
XM`"4M,S)L<R`E-FQD"@``3E7_.$CG,#`@;0`(0^T`#$7Z`<!'[?\X+'@`!$ZNT
XM_?8L;``P3J[_Q"!+2AAF_%.(D<LB`"0+)@A.KO_03-\,#$Y=3G5.5?[<2.<_&
XM`"XM``A"K?[L*T#^Y"M!_N@B`"QL`#!.KO^">``O0``8(BW^Y$'M_O`D"$ZNV
XM_YI*@&<``30@+?[T2H!J``$(2JW^Z&8``2).KO_$+`!P(+Z`9`0B!V`"(@`O>
XM00`<(@9!^O\8)`@F+P`<3J[_T"\M``PO+?]L80`!("Z`2&W^^$AZ_QPK0/[L[
XM80#_+$_O`!!@``#6<``B`"QX``1.KO[."```#&<&>/]@``"<+RT`#"\M_VQA6
XM``#B4$\L`"HM_N@@+?[T2H!O-D'M_O@B"'3^+&P`,$ZN_ZPB!U*!+RT`#"\!;
XM+T``)"(%80#_$%!/*`#<A"(O`!PL;``P3J[_IMVM_NQ*A69`2H1K/"QL`#!.;
XMKO_$*@!P(+Z`9`0B!V`"(@`O00`<(@5!^OY2)`@F+P`<3J[_T"\&2&W^^$AZ&
XM_FQA`/YV3^\`#"(M_N1![?[P)`@L;``P3J[_E$J$6L%$`4B!2,'`@68`_RXB/
XM+P`8+&P`,$ZN_X)*A&H$</]@!"`M_NQ,WP#\3EU.=2\'+@`6AT'K``$F2"X?0
XM3G5.5?_X+P(@+0`,(@#DB70XDH(D+0`(U(!3@B`"+T$`!"(M``Q.N@!2(B\`4
XM!"]```A.N@!&4H`B+P`(TH`@`20?3EU.=0``2H!J```>1(!*@6H```Q$@6$`5
XM`"!$@4YU80``&$2`1(%.=4J!:@``#$2!80``!D2`3G4O`DA!-`%F```B2$!(H
XM04A"-`!G```&A,$P`DA`-`"$P3`"2$(R`B0?3G4O`W80#$$`@&0```;AF5%#7
XM#$$(`&0```;IF5E##$$@`&0```;EF55#2D%K```&XYE30S0`YJA(0D)"YJI(`
XM0X#!-@`P`C0#2$'$P9""9```"%-#T(%D_G(`,@-(0^>X2$#!028?)!].=0``>
XM`^P````!`````0````H````````#\@```^H````-)$ED.B!D=2YC+'8@,2XR2
XI(#DP+S`V+S`V(#(P.C`W.C,W('!E=&5R8R!%>'`@)````````````_(@#
X``
Xend
Xsize 1436
END_OF_FILE
if test 2042 -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@cs.odu.edu>.
Mail comments to the moderator at <amiga-request@cs.odu.edu>.
Post requests for sources, and general discussion to comp.sys.amiga.