[OpenAFS-devel] server side vos-dump

Neulinger, Nathan R. nneul@umr.edu
Mon, 19 Mar 2001 13:45:14 -0600


This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.

------_=_NextPart_000_01C0B0AD.1DDD7F60
Content-Type: text/plain;
	charset="ISO-8859-1"

I've got a server side vos-dump utility put together. It's bare bones, and
doesn't do any locking/etc., but it does work to create a vos dump file of a
volume without going through the volserver. I've attached the diff to the
vol/Makefile, and the two new files in vol that need to be added to create
'volutil', which at the moment, only supports the command 'dump'.

However, I haven't seen a tremendous speedup. Maybe 10-15% at most. From
looking at things, I'm really not sure where the slowdown is, but it appears
that most of the time is spent reading the source files. I'm not sure if
there is any way to speed that up or not. It's possible that by modifying
the DumpFile routine that I have copied for this vol dumper to use sendfile
could speed things up some, but I doubt all that much.

I have determined though that reiserfs is horrible for vice partitions for
vos dumps. (30 secs to dump 110MB/14k-files instead of 10 secs w/ ext2).
Maybe something with namei?

-- Nathan

------------------------------------------------------------
Nathan Neulinger                       EMail:  nneul@umr.edu
University of Missouri - Rolla         Phone: (573) 341-4841
Computing Services                       Fax: (573) 341-4216


------_=_NextPart_000_01C0B0AD.1DDD7F60
Content-Type: application/octet-stream;
	name="dumpstuff.c"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="dumpstuff.c"

/*=0A=
 * Copyright 2000, International Business Machines Corporation and =
others.=0A=
 * All Rights Reserved.=0A=
 * =0A=
 * This software has been released under the terms of the IBM Public=0A=
 * License.  For details, see the LICENSE file in the top-level =
source=0A=
 * directory or online at http://www.openafs.org/dl/license10.html=0A=
 */=0A=
=0A=
#include <afs/param.h>=0A=
#include <sys/types.h>=0A=
#include <ctype.h>=0A=
#include <stdio.h>=0A=
#include <errno.h>=0A=
#ifdef AFS_NT40_ENV=0A=
#include <fcntl.h>=0A=
#else=0A=
#include <sys/param.h>=0A=
#include <sys/file.h>=0A=
#include <sys/uio.h>=0A=
#include <netinet/in.h>=0A=
#include <unistd.h>=0A=
#endif=0A=
#include <sys/stat.h>=0A=
#include <afs/assert.h>=0A=
#include <rx/xdr.h>=0A=
#include <rx/rx.h>=0A=
#include <afs/afsint.h>=0A=
#include <afs/nfs.h>=0A=
#include <afs/errors.h>=0A=
#include <lock.h>=0A=
#include <lwp.h>=0A=
#include <afs/ihandle.h>=0A=
#include <afs/vnode.h>=0A=
#include <afs/volume.h>=0A=
#include <afs/partition.h>=0A=
#include "dump.h"=0A=
#include <afs/fssync.h>=0A=
#include <afs/acl.h>=0A=
#include "volser.h"=0A=
#include "volint.h"=0A=
=0A=
int writen(register int fd, register char *ptr, register int nbytes)=0A=
{=0A=
	int nleft, nwritten;=0A=
=0A=
	nleft =3D nbytes;=0A=
	while (nleft > 0)=0A=
	{=0A=
		nwritten =3D write(fd, ptr, nleft);=0A=
		if (nwritten <=3D 0)=0A=
			return (nwritten);=0A=
=0A=
		nleft -=3D nwritten;=0A=
		ptr +=3D nwritten;=0A=
	}=0A=
	return (nbytes - nleft);=0A=
}=0A=
=0A=
/* This iod stuff is a silly little package to emulate the old qi_in =
stuff, which=0A=
   emulated the stdio stuff.  There is a big assumption here, that =
the=0A=
   rx_Read will never be called directly, by a routine like readFile, =
when=0A=
   there is an old character that was pushed back with iod_ungetc.  =
This=0A=
   is really bletchy, and is here for compatibility only.  =
Eventually,=0A=
   we should define a volume format that doesn't require=0A=
   the pushing back of characters (i.e. characters should not double =
both=0A=
   as an end marker and a begin marker) */=0A=
struct iod=0A=
{=0A=
	int fd;						/* file to which to write, might be an array */=0A=
	int device;					/* dump device ID for volume */=0A=
	int parentId;				/* dump parent ID for volume */=0A=
	struct DiskPartition *dumpPartition;	/* Dump partition. */=0A=
	int code;					/* return code */=0A=
	char haveOldChar;			/* state for pushing back a character */=0A=
	char oldChar;=0A=
};=0A=
=0A=
/* Forward Declarations */=0A=
static int DumpDumpHeader(register struct iod *iodp, register Volume * =
vp,=0A=
	afs_int32 fromtime);=0A=
static int DumpPartial(register struct iod *iodp, register Volume * =
vp,=0A=
	afs_int32 fromtime, int dumpAllDirs);=0A=
static int DumpVnodeIndex(register struct iod *iodp, Volume * vp,=0A=
	VnodeClass class, afs_int32 fromtime, int forcedump);=0A=
static int DumpVnode(register struct iod *iodp, struct VnodeDiskObject =
*v,=0A=
	int vnodeNumber, int dumpEverything);=0A=
static int ReadDumpHeader(register struct iod *iodp, struct DumpHeader =
*hp);=0A=
static int ReadVnodes(register struct iod *iodp, Volume * vp,=0A=
	int incremental, afs_int32 * Lbuf, afs_int32 s1,=0A=
	afs_int32 * Sbuf, afs_int32 s2, afs_int32 delo);=0A=
static bit32 volser_WriteFile(int vn, struct iod *iodp, FdHandle_t * =
handleP,=0A=
	Error * status);=0A=
=0A=
static void iod_Init(register struct iod *iodp, register int fd)=0A=
{=0A=
	iodp->fd =3D fd;=0A=
	iodp->haveOldChar =3D 0;=0A=
}=0A=
=0A=
/* N.B. iod_Read doesn't check for oldchar (see previous comment) */=0A=
#if 0=0A=
#define iod_Read(iodp, buf, nbytes) rx_Read((iodp)->fd, buf, nbytes)=0A=
#else=0A=
#define iod_Read(iodp, buf, nbytes) sleep(0)=0A=
/*=0A=
	not doing yet, need to put in a readall/writeall routine to =0A=
	make sure to write everything=0A=
*/=0A=
#endif=0A=
=0A=
/* For the single dump case, it's ok to just return the "bytes =
written"=0A=
 * that rx_Write returns, since all the callers of iod_Write abort =
when=0A=
 * the returned value is less than they expect.  For the multi dump =
case,=0A=
 * I don't think we want half the replicas to go bad just because one =
=0A=
 * connection timed out, but if they all time out, then we should give =
up. =0A=
 */=0A=
static int iod_Write(struct iod *iodp, char *buf, int nbytes)=0A=
{=0A=
	int code, i;=0A=
	int one_success =3D 0;=0A=
=0A=
	if (iodp->fd)=0A=
	{=0A=
		code =3D writen(iodp->fd, buf, nbytes);=0A=
		return code;=0A=
	}=0A=
}=0A=
=0A=
static void iod_ungetc(struct iod *iodp, int achar)=0A=
{=0A=
	iodp->oldChar =3D achar;=0A=
	iodp->haveOldChar =3D 1;=0A=
}=0A=
=0A=
static int iod_getc(register struct iod *iodp)=0A=
{=0A=
	unsigned char t;=0A=
=0A=
	if (iodp->haveOldChar)=0A=
	{=0A=
		iodp->haveOldChar =3D 0;=0A=
		return iodp->oldChar;=0A=
	}=0A=
	if (iod_Read(iodp, &t, 1) =3D=3D 1)=0A=
		return t;=0A=
	return EOF;=0A=
}=0A=
=0A=
static int ReadShort(register struct iod *iodp, register unsigned short =
*sp)=0A=
{=0A=
	register b1, b0;=0A=
=0A=
	b1 =3D iod_getc(iodp);=0A=
	b0 =3D iod_getc(iodp);=0A=
	*sp =3D (b1 << 8) | b0;=0A=
	return b0 !=3D EOF;=0A=
}=0A=
=0A=
static int ReadInt32(register struct iod *iodp, afs_uint32 * lp)=0A=
{=0A=
	afs_uint32 register b3, b2, b1, b0;=0A=
=0A=
	b3 =3D iod_getc(iodp);=0A=
	b2 =3D iod_getc(iodp);=0A=
	b1 =3D iod_getc(iodp);=0A=
	b0 =3D iod_getc(iodp);=0A=
	*lp =3D (((((b3 << 8) | b2) << 8) | b1) << 8) | b0;=0A=
	return b0 !=3D EOF;=0A=
}=0A=
=0A=
static void ReadString(register struct iod *iodp, register char *to,=0A=
	register int maxa)=0A=
{=0A=
	register int c;=0A=
=0A=
	while (maxa--)=0A=
	{=0A=
		if ((*to++ =3D iod_getc(iodp)) =3D=3D 0)=0A=
			break;=0A=
	}=0A=
	if (to[-1])=0A=
	{=0A=
		while ((c =3D iod_getc(iodp)) && c !=3D EOF);=0A=
		to[-1] =3D 0;=0A=
	}=0A=
}=0A=
=0A=
static void ReadByteString(register struct iod *iodp, register byte * =
to,=0A=
	register int size)=0A=
{=0A=
	while (size--)=0A=
		*to++ =3D iod_getc(iodp);=0A=
}=0A=
=0A=
static int ReadVolumeHeader(register struct iod *iodp, VolumeDiskData * =
vol)=0A=
{=0A=
	register tag;=0A=
	afs_uint32 trash;=0A=
=0A=
	bzero(vol, sizeof(*vol));=0A=
	while ((tag =3D iod_getc(iodp)) > D_MAX && tag !=3D EOF)=0A=
	{=0A=
		switch (tag)=0A=
		{=0A=
			case 'i':=0A=
				if (!ReadInt32(iodp, &vol->id))=0A=
					return VOLSERREAD_DUMPERROR;=0A=
				break;=0A=
			case 'v':=0A=
				if (!ReadInt32(iodp, &trash))=0A=
					return VOLSERREAD_DUMPERROR;=0A=
				break;=0A=
			case 'n':=0A=
				ReadString(iodp, vol->name, sizeof(vol->name));=0A=
				/*this means the name of the retsored volume could be possibly =
different. In conjunction with SAFSVolSignalRestore */=0A=
				break;=0A=
			case 's':=0A=
				vol->inService =3D iod_getc(iodp);=0A=
				break;=0A=
			case 'b':=0A=
				vol->blessed =3D iod_getc(iodp);=0A=
				break;=0A=
			case 'u':=0A=
				if (!ReadInt32(iodp, &vol->uniquifier))=0A=
					return VOLSERREAD_DUMPERROR;=0A=
				break;=0A=
			case 't':=0A=
				vol->type =3D iod_getc(iodp);=0A=
				break;=0A=
			case 'p':=0A=
				if (!ReadInt32(iodp, &vol->parentId))=0A=
					return VOLSERREAD_DUMPERROR;=0A=
				break;=0A=
			case 'c':=0A=
				if (!ReadInt32(iodp, &vol->cloneId))=0A=
					return VOLSERREAD_DUMPERROR;=0A=
				break;=0A=
			case 'q':=0A=
				if (!ReadInt32(iodp, (afs_uint32 *) & vol->maxquota))=0A=
					return VOLSERREAD_DUMPERROR;=0A=
				break;=0A=
			case 'm':=0A=
				if (!ReadInt32(iodp, (afs_uint32 *) & vol->minquota))=0A=
					return VOLSERREAD_DUMPERROR;=0A=
				break;=0A=
			case 'd':=0A=
				if (!ReadInt32(iodp, (afs_uint32 *) & vol->diskused))=0A=
					return VOLSERREAD_DUMPERROR;	/* Bogus:  should calculate this =
*/=0A=
				break;=0A=
			case 'f':=0A=
				if (!ReadInt32(iodp, (afs_uint32 *) & vol->filecount))=0A=
					return VOLSERREAD_DUMPERROR;=0A=
				break;=0A=
			case 'a':=0A=
				if (!ReadInt32(iodp, &vol->accountNumber))=0A=
					return VOLSERREAD_DUMPERROR;=0A=
				break;=0A=
			case 'o':=0A=
				if (!ReadInt32(iodp, &vol->owner))=0A=
					return VOLSERREAD_DUMPERROR;=0A=
				break;=0A=
			case 'C':=0A=
				if (!ReadInt32(iodp, &vol->creationDate))=0A=
					return VOLSERREAD_DUMPERROR;=0A=
				break;=0A=
			case 'A':=0A=
				if (!ReadInt32(iodp, &vol->accessDate))=0A=
					return VOLSERREAD_DUMPERROR;=0A=
				break;=0A=
			case 'U':=0A=
				if (!ReadInt32(iodp, &vol->updateDate))=0A=
					return VOLSERREAD_DUMPERROR;=0A=
				break;=0A=
			case 'E':=0A=
				if (!ReadInt32(iodp, &vol->expirationDate))=0A=
					return VOLSERREAD_DUMPERROR;=0A=
				break;=0A=
			case 'B':=0A=
				if (!ReadInt32(iodp, &vol->backupDate))=0A=
					return VOLSERREAD_DUMPERROR;=0A=
				break;=0A=
			case 'O':=0A=
				ReadString(iodp, vol->offlineMessage,=0A=
					sizeof(vol->offlineMessage));=0A=
				break;=0A=
			case 'M':=0A=
				/*=0A=
				 * Detailed volume statistics are never stored in dumps,=0A=
				 * so we just restore either the null string if this volume=0A=
				 * had already been set to store statistics, or the old motd=0A=
				 * contents otherwise.  It doesn't matter, since this field=0A=
				 * will soon get initialized anyway.=0A=
				 */=0A=
				ReadString(iodp, (char *) (vol->stat_reads), VMSGSIZE);=0A=
				break;=0A=
			case 'W':=0A=
				{=0A=
					unsigned short length;=0A=
					int i;=0A=
					afs_uint32 data;=0A=
=0A=
					if (!ReadShort(iodp, &length))=0A=
						return VOLSERREAD_DUMPERROR;=0A=
					for (i =3D 0; i < length; i++)=0A=
					{=0A=
						if (!ReadInt32(iodp, &data))=0A=
							return VOLSERREAD_DUMPERROR;=0A=
						if (i <=0A=
							sizeof(vol->weekUse) / sizeof(vol->weekUse[0]))=0A=
							vol->weekUse[i] =3D data;=0A=
					}=0A=
					break;=0A=
				}=0A=
			case 'D':=0A=
				if (!ReadInt32(iodp, &vol->dayUseDate))=0A=
					return VOLSERREAD_DUMPERROR;=0A=
				break;=0A=
			case 'Z':=0A=
				if (!ReadInt32(iodp, (afs_uint32 *) & vol->dayUse))=0A=
					return VOLSERREAD_DUMPERROR;=0A=
				break;=0A=
		}=0A=
	}=0A=
	iod_ungetc(iodp, tag);=0A=
	return 0;=0A=
}=0A=
=0A=
static int DumpTag(register struct iod *iodp, register int tag)=0A=
{=0A=
	char p;=0A=
=0A=
	p =3D tag;=0A=
	return ((iod_Write(iodp, &p, 1) =3D=3D 1) ? 0 : VOLSERDUMPERROR);=0A=
=0A=
}=0A=
=0A=
static int DumpByte(register struct iod *iodp, char tag, byte value)=0A=
{=0A=
	char tbuffer[2];=0A=
	register byte *p =3D (unsigned char *) tbuffer;=0A=
=0A=
	*p++ =3D tag;=0A=
	*p =3D value;=0A=
	return ((iod_Write(iodp, tbuffer, 2) =3D=3D 2) ? 0 : =
VOLSERDUMPERROR);=0A=
}=0A=
=0A=
#define putint32(p, v)  *p++ =3D v>>24, *p++ =3D v>>16, *p++ =3D v>>8, =
*p++ =3D v=0A=
#define putshort(p, v) *p++ =3D v>>8, *p++ =3D v=0A=
=0A=
static int DumpDouble(register struct iod *iodp, char tag,=0A=
	register afs_uint32 value1, register afs_uint32 value2)=0A=
{=0A=
	char tbuffer[9];=0A=
	register byte *p =3D (unsigned char *) tbuffer;=0A=
=0A=
	*p++ =3D tag;=0A=
	putint32(p, value1);=0A=
	putint32(p, value2);=0A=
	return ((iod_Write(iodp, tbuffer, 9) =3D=3D 9) ? 0 : =
VOLSERDUMPERROR);=0A=
}=0A=
=0A=
static int DumpInt32(register struct iod *iodp, char tag,=0A=
	register afs_uint32 value)=0A=
{=0A=
	char tbuffer[5];=0A=
	register byte *p =3D (unsigned char *) tbuffer;=0A=
=0A=
	*p++ =3D tag;=0A=
	putint32(p, value);=0A=
	return ((iod_Write(iodp, tbuffer, 5) =3D=3D 5) ? 0 : =
VOLSERDUMPERROR);=0A=
}=0A=
=0A=
static int DumpArrayInt32(register struct iod *iodp, char tag,=0A=
	register afs_uint32 * array, register int nelem)=0A=
{=0A=
	char tbuffer[4];=0A=
	register afs_uint32 v;=0A=
	int code =3D 0;=0A=
	register byte *p =3D (unsigned char *) tbuffer;=0A=
=0A=
	*p++ =3D tag;=0A=
	putshort(p, nelem);=0A=
	code =3D iod_Write(iodp, tbuffer, 3);=0A=
	if (code !=3D 3)=0A=
		return VOLSERDUMPERROR;=0A=
	while (nelem--)=0A=
	{=0A=
		p =3D (unsigned char *) tbuffer;=0A=
		v =3D *array++;			/*this was register */=0A=
=0A=
		putint32(p, v);=0A=
		code =3D iod_Write(iodp, tbuffer, 4);=0A=
		if (code !=3D 4)=0A=
			return VOLSERDUMPERROR;=0A=
	}=0A=
	return 0;=0A=
}=0A=
=0A=
static int DumpShort(register struct iod *iodp, char tag, unsigned int =
value)=0A=
{=0A=
	char tbuffer[3];=0A=
	register byte *p =3D (unsigned char *) tbuffer;=0A=
=0A=
	*p++ =3D tag;=0A=
	*p++ =3D value >> 8;=0A=
	*p =3D value;=0A=
	return ((iod_Write(iodp, tbuffer, 3) =3D=3D 3) ? 0 : =
VOLSERDUMPERROR);=0A=
}=0A=
=0A=
static int DumpBool(register struct iod *iodp, char tag, unsigned int =
value)=0A=
{=0A=
	char tbuffer[2];=0A=
	register byte *p =3D (unsigned char *) tbuffer;=0A=
=0A=
	*p++ =3D tag;=0A=
	*p =3D value;=0A=
	return ((iod_Write(iodp, tbuffer, 2) =3D=3D 2) ? 0 : =
VOLSERDUMPERROR);=0A=
}=0A=
=0A=
static int DumpString(register struct iod *iodp, char tag, register =
char *s)=0A=
{=0A=
	register n;=0A=
	int code =3D 0;=0A=
=0A=
	code =3D iod_Write(iodp, &tag, 1);=0A=
	if (code !=3D 1)=0A=
		return VOLSERDUMPERROR;=0A=
	n =3D strlen(s) + 1;=0A=
	code =3D iod_Write(iodp, s, n);=0A=
	if (code !=3D n)=0A=
		return VOLSERDUMPERROR;=0A=
	return 0;=0A=
}=0A=
=0A=
static int DumpByteString(register struct iod *iodp, char tag,=0A=
	register byte * bs, register int nbytes)=0A=
{=0A=
	int code =3D 0;=0A=
=0A=
	code =3D iod_Write(iodp, &tag, 1);=0A=
	if (code !=3D 1)=0A=
		return VOLSERDUMPERROR;=0A=
	code =3D iod_Write(iodp, (char *) bs, nbytes);=0A=
	if (code !=3D nbytes)=0A=
		return VOLSERDUMPERROR;=0A=
	return 0;=0A=
}=0A=
=0A=
static int DumpFile(struct iod *iodp, char tag, int vnode,=0A=
	FdHandle_t * handleP)=0A=
{=0A=
	int code =3D 0, lcode =3D 0, error =3D 0;=0A=
	afs_int32 pad =3D 0, offset;=0A=
	int n, nbytes, howMany;=0A=
	byte *p;=0A=
	struct stat status;=0A=
	int size;=0A=
=0A=
#ifdef	AFS_AIX_ENV=0A=
#include <sys/statfs.h>=0A=
	struct statfs tstatfs;=0A=
#endif=0A=
=0A=
#ifdef AFS_NT40_ENV=0A=
	howMany =3D 4096;				/* Page size */=0A=
#else=0A=
	fstat(handleP->fd_fd, &status);=0A=
#ifdef	AFS_AIX_ENV=0A=
	/* Unfortunately in AIX valuable fields such as st_blksize are =0A=
	 * gone from the stat structure.=0A=
	 */=0A=
	fstatfs(handleP->fd_fd, &tstatfs);=0A=
	howMany =3D tstatfs.f_bsize;=0A=
#else=0A=
	howMany =3D status.st_blksize;=0A=
#endif=0A=
#endif /* AFS_NT40_ENV */=0A=
=0A=
	size =3D FDH_SIZE(handleP);=0A=
	code =3D DumpInt32(iodp, tag, size);=0A=
	if (code)=0A=
	{=0A=
		return VOLSERDUMPERROR;=0A=
	}=0A=
=0A=
howMany =3D 2560000;=0A=
=0A=
	p =3D (unsigned char *) malloc(howMany);=0A=
	if (!p)=0A=
	{=0A=
		Log("1 Volser: DumpFile: no memory");=0A=
		return VOLSERDUMPERROR;=0A=
	}=0A=
=0A=
	for (nbytes =3D size; (nbytes && !error); nbytes -=3D howMany)=0A=
	{=0A=
		if (nbytes < howMany)=0A=
			howMany =3D nbytes;=0A=
=0A=
		/* Read the data - unless we know we can't */=0A=
		n =3D (lcode ? 0 : FDH_READ(handleP, p, howMany));=0A=
=0A=
		/* If read any good data and we null padded previously, log the=0A=
		 * amount that we had null padded.=0A=
		 */=0A=
		if ((n > 0) && pad)=0A=
		{=0A=
			Log=0A=
				("1 Volser: DumpFile: Null padding file %d bytes at offset =
%u\n",=0A=
				pad, offset);=0A=
			pad =3D 0;=0A=
		}=0A=
=0A=
		/* If didn't read enough data, null padd the rest of the buffer. =
This=0A=
		 * can happen if, for instance, the media has some bad spots. We =
don't=0A=
		 * want to quit the dump, so we start null padding.=0A=
		 */=0A=
		if (n < howMany)=0A=
		{=0A=
			/* Record the read error */=0A=
			if (n < 0)=0A=
			{=0A=
				n =3D 0;=0A=
				Log=0A=
					("1 Volser: DumpFile: Error %d reading inode %s for vnode =
%d\n",=0A=
					errno, PrintInode(NULL, handleP->fd_ih->ih_ino), vnode);=0A=
			}=0A=
			else if (!pad)=0A=
			{=0A=
				Log=0A=
					("1 Volser: DumpFile: Error reading inode %s for vnode %d\n",=0A=
					PrintInode(NULL, handleP->fd_ih->ih_ino), vnode);=0A=
			}=0A=
=0A=
			/* Pad the rest of the buffer with zeros. Remember offset we started =
=0A=
			 * padding. Keep total tally of padding.=0A=
			 */=0A=
			bzero(p + n, howMany - n);=0A=
			if (!pad)=0A=
				offset =3D (status.st_size - nbytes) + n;=0A=
			pad +=3D (howMany - n);=0A=
=0A=
			/* Now seek over the data we could not get. An error here means =
we=0A=
			 * can't do the next read.=0A=
			 */=0A=
			lcode =3D FDH_SEEK(handleP, ((size - nbytes) + howMany), =
SEEK_SET);=0A=
			if (lcode !=3D ((size - nbytes) + howMany))=0A=
			{=0A=
				if (lcode < 0)=0A=
				{=0A=
					Log=0A=
						("1 Volser: DumpFile: Error %d seeking in inode %s for vnode =
%d\n",=0A=
						errno, PrintInode(NULL, handleP->fd_ih->ih_ino),=0A=
						vnode);=0A=
				}=0A=
				else=0A=
				{=0A=
					Log=0A=
						("1 Volser: DumpFile: Error seeking in inode %s for vnode =
%d\n",=0A=
						PrintInode(NULL, handleP->fd_ih->ih_ino), vnode);=0A=
					lcode =3D -1;=0A=
				}=0A=
			}=0A=
			else=0A=
			{=0A=
				lcode =3D 0;=0A=
			}=0A=
		}=0A=
=0A=
		/* Now write the data out */=0A=
		if (iod_Write(iodp, (char *) p, howMany) !=3D howMany)=0A=
			error =3D VOLSERDUMPERROR;=0A=
	}=0A=
=0A=
	if (pad)=0A=
	{							/* Any padding we hadn't reported yet */=0A=
		Log("1 Volser: DumpFile: Null padding file: %d bytes at offset =
%u\n",=0A=
			pad, offset);=0A=
	}=0A=
=0A=
	free(p);=0A=
	return error;=0A=
}=0A=
=0A=
static int DumpVolumeHeader(register struct iod *iodp, register Volume =
* vp)=0A=
{=0A=
	int code =3D 0;=0A=
	static char nullString[1] =3D "";	/*The ``contents'' of motd */=0A=
=0A=
	if (!code)=0A=
		code =3D DumpTag(iodp, D_VOLUMEHEADER);=0A=
	if (!code)=0A=
	{=0A=
		code =3D DumpInt32(iodp, 'i', V_id(vp));=0A=
	}=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'v', V_stamp(vp).version);=0A=
	if (!code)=0A=
		code =3D DumpString(iodp, 'n', V_name(vp));=0A=
	if (!code)=0A=
		code =3D DumpBool(iodp, 's', V_inService(vp));=0A=
	if (!code)=0A=
		code =3D DumpBool(iodp, 'b', V_blessed(vp));=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'u', V_uniquifier(vp));=0A=
	if (!code)=0A=
		code =3D DumpByte(iodp, 't', (byte) V_type(vp));=0A=
	if (!code)=0A=
	{=0A=
		code =3D DumpInt32(iodp, 'p', V_parentId(vp));=0A=
	}=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'c', V_cloneId(vp));=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'q', V_maxquota(vp));=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'm', V_minquota(vp));=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'd', V_diskused(vp));=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'f', V_filecount(vp));=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'a', V_accountNumber(vp));=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'o', V_owner(vp));=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'C', V_creationDate(vp));	/* Rw volume =
creation date */=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'A', V_accessDate(vp));=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'U', V_updateDate(vp));=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'E', V_expirationDate(vp));=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'B', V_backupDate(vp));	/* Rw volume backup =
clone date */=0A=
	if (!code)=0A=
		code =3D DumpString(iodp, 'O', V_offlineMessage(vp));=0A=
	/*=0A=
	 * We do NOT dump the detailed volume statistics residing in the =
old=0A=
	 * motd field, since we cannot tell from the info in a dump whether=0A=
	 * statistics data has been put there.  Instead, we dump a null =
string,=0A=
	 * just as if that was what the motd contained.=0A=
	 */=0A=
	if (!code)=0A=
		code =3D DumpString(iodp, 'M', nullString);=0A=
	if (!code)=0A=
		code =3D=0A=
			DumpArrayInt32(iodp, 'W', (afs_uint32 *) V_weekUse(vp),=0A=
			sizeof(V_weekUse(vp)) / sizeof(V_weekUse(vp)[0]));=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'D', V_dayUseDate(vp));=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'Z', V_dayUse(vp));=0A=
	return code;=0A=
}=0A=
=0A=
static int DumpEnd(register struct iod *iodp)=0A=
{=0A=
	return (DumpInt32(iodp, D_DUMPEND, DUMPENDMAGIC));=0A=
}=0A=
=0A=
/* Guts of the dump code */=0A=
=0A=
/* Dump a whole volume */=0A=
int DumpVolume(register int fd, register Volume * vp,=0A=
	afs_int32 fromtime, int dumpAllDirs)=0A=
{=0A=
	struct iod iod;=0A=
	int code =3D 0;=0A=
	register struct iod *iodp =3D &iod;=0A=
=0A=
	iod_Init(iodp, fd);=0A=
=0A=
	if (!code)=0A=
		code =3D DumpDumpHeader(iodp, vp, fromtime);=0A=
	if (!code)=0A=
		code =3D DumpPartial(iodp, vp, fromtime, dumpAllDirs);=0A=
	if (!code)=0A=
		code =3D DumpEnd(iodp);=0A=
=0A=
	return code;=0A=
}=0A=
=0A=
/* A partial dump (no dump header) */=0A=
static int DumpPartial(register struct iod *iodp, register Volume * =
vp,=0A=
	afs_int32 fromtime, int dumpAllDirs)=0A=
{=0A=
	int code =3D 0;=0A=
=0A=
	if (!code)=0A=
		code =3D DumpVolumeHeader(iodp, vp);=0A=
	if (!code)=0A=
		code =3D DumpVnodeIndex(iodp, vp, vLarge, fromtime, dumpAllDirs);=0A=
	if (!code)=0A=
		code =3D DumpVnodeIndex(iodp, vp, vSmall, fromtime, 0);=0A=
	return code;=0A=
}=0A=
=0A=
static int DumpVnodeIndex(register struct iod *iodp, Volume * vp,=0A=
	VnodeClass class, afs_int32 fromtime, int forcedump)=0A=
{=0A=
	register int code =3D 0;=0A=
	register struct VnodeClassInfo *vcp =3D &VnodeClassInfo[class];=0A=
	char buf[SIZEOF_LARGEDISKVNODE];=0A=
	struct VnodeDiskObject *vnode =3D (struct VnodeDiskObject *) buf;=0A=
	StreamHandle_t *file;=0A=
	IHandle_t *handle;=0A=
	FdHandle_t *fdP;=0A=
	int size;=0A=
	int flag;=0A=
	register int vnodeIndex, nVnodes;=0A=
=0A=
	fdP =3D IH_OPEN(vp->vnodeIndex[class].handle);=0A=
	assert(fdP !=3D NULL);=0A=
	file =3D FDH_FDOPEN(fdP, "r+");=0A=
	assert(file !=3D NULL);=0A=
	size =3D OS_SIZE(fdP->fd_fd);=0A=
	assert(size !=3D -1);=0A=
	nVnodes =3D (size / vcp->diskSize) - 1;=0A=
	if (nVnodes > 0)=0A=
	{=0A=
		assert((nVnodes + 1) * vcp->diskSize =3D=3D size)=0A=
			assert(STREAM_SEEK(file, vcp->diskSize, 0) =3D=3D 0)}=0A=
	else=0A=
		nVnodes =3D 0;=0A=
	for (vnodeIndex =3D 0;=0A=
		nVnodes && STREAM_READ(vnode, vcp->diskSize, 1, file) =3D=3D 1 && =
!code;=0A=
		nVnodes--, vnodeIndex++)=0A=
	{=0A=
		flag =3D forcedump || (vnode->serverModifyTime >=3D fromtime);=0A=
		/* Note:  the >=3D test is very important since some old volumes may =
not have=0A=
		   a serverModifyTime.  For an epoch dump, this results in 0>=3D0 =
test, which=0A=
		   does dump the file! */=0A=
		if (!code)=0A=
			code =3D=0A=
				DumpVnode(iodp, vnode, bitNumberToVnodeNumber(vnodeIndex,=0A=
				 class), flag);=0A=
	}=0A=
	STREAM_CLOSE(file);=0A=
	FDH_CLOSE(fdP);=0A=
	return code;=0A=
}=0A=
=0A=
static int DumpDumpHeader(register struct iod *iodp, register Volume * =
vp,=0A=
	afs_int32 fromtime)=0A=
{=0A=
	int code =3D 0;=0A=
	int UseLatestReadOnlyClone =3D 1;=0A=
	afs_int32 dumpTimes[2];=0A=
=0A=
	iodp->device =3D vp->device;=0A=
	iodp->parentId =3D V_parentId(vp);=0A=
	iodp->dumpPartition =3D vp->partition;=0A=
	if (!code)=0A=
		code =3D DumpDouble(iodp, D_DUMPHEADER, DUMPBEGINMAGIC, =
DUMPVERSION);=0A=
	if (!code)=0A=
		code =3D=0A=
			DumpInt32(iodp, 'v',=0A=
			UseLatestReadOnlyClone ? V_id(vp) : V_parentId(vp));=0A=
	if (!code)=0A=
		code =3D DumpString(iodp, 'n', V_name(vp));=0A=
	dumpTimes[0] =3D fromtime;=0A=
	dumpTimes[1] =3D V_backupDate(vp);	/* Until the time the clone was =
made */=0A=
	if (!code)=0A=
		code =3D DumpArrayInt32(iodp, 't', (afs_uint32 *) dumpTimes, 2);=0A=
	return code;=0A=
}=0A=
=0A=
static int DumpVnode(register struct iod *iodp, struct VnodeDiskObject =
*v,=0A=
	int vnodeNumber, int dumpEverything)=0A=
{=0A=
	int code =3D 0;=0A=
	IHandle_t *ihP;=0A=
	FdHandle_t *fdP;=0A=
=0A=
	if (!v || v->type =3D=3D vNull)=0A=
		return code;=0A=
	if (!code)=0A=
		code =3D DumpDouble(iodp, D_VNODE, vnodeNumber, v->uniquifier);=0A=
	if (!dumpEverything)=0A=
		return code;=0A=
	if (!code)=0A=
		code =3D DumpByte(iodp, 't', (byte) v->type);=0A=
	if (!code)=0A=
		code =3D DumpShort(iodp, 'l', v->linkCount);	/* May not need this =
*/=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'v', v->dataVersion);=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'm', v->unixModifyTime);=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'a', v->author);=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'o', v->owner);=0A=
	if (!code && v->group)=0A=
		code =3D DumpInt32(iodp, 'g', v->group);	/* default group is 0 */=0A=
	if (!code)=0A=
		code =3D DumpShort(iodp, 'b', v->modeBits);=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 'p', v->parent);=0A=
	if (!code)=0A=
		code =3D DumpInt32(iodp, 's', v->serverModifyTime);=0A=
	if (v->type =3D=3D vDirectory)=0A=
	{=0A=
		acl_HtonACL(VVnodeDiskACL(v));=0A=
		if (!code)=0A=
			code =3D=0A=
				DumpByteString(iodp, 'A', (byte *) VVnodeDiskACL(v),=0A=
				VAclDiskSize(v));=0A=
	}=0A=
	if (VNDISK_GET_INO(v))=0A=
	{=0A=
		IH_INIT(ihP, iodp->device, iodp->parentId, VNDISK_GET_INO(v));=0A=
		fdP =3D IH_OPEN(ihP);=0A=
		if (fdP =3D=3D NULL)=0A=
		{=0A=
			Log=0A=
				("1 Volser: DumpVnode: dump: Unable to open inode %d for vnode %d; =
not dumped, error %d\n",=0A=
				VNDISK_GET_INO(v), vnodeNumber, errno);=0A=
			IH_RELEASE(ihP);=0A=
			return VOLSERREAD_DUMPERROR;=0A=
		}=0A=
		code =3D DumpFile(iodp, 'f', vnodeNumber, fdP);=0A=
		FDH_CLOSE(fdP);=0A=
		IH_RELEASE(ihP);=0A=
	}=0A=
	return code;=0A=
}=0A=
=0A=
int ProcessIndex(Volume * vp, VnodeClass class, afs_int32 ** Bufp, int =
*sizep,=0A=
	int del)=0A=
{=0A=
	int i, nVnodes, offset, code, index =3D 0;=0A=
	afs_int32 *Buf;=0A=
	int cnt =3D 0;=0A=
	int size;=0A=
	StreamHandle_t *afile;=0A=
	FdHandle_t *fdP;=0A=
	struct VnodeClassInfo *vcp =3D &VnodeClassInfo[class];=0A=
	char buf[SIZEOF_LARGEDISKVNODE], zero[SIZEOF_LARGEDISKVNODE];=0A=
	register struct VnodeDiskObject *vnode =3D (struct VnodeDiskObject *) =
buf;=0A=
=0A=
	bzero(zero, sizeof(zero));	/* zero out our proto-vnode */=0A=
	fdP =3D IH_OPEN(vp->vnodeIndex[class].handle);=0A=
	if (fdP =3D=3D NULL)=0A=
		return -1;=0A=
	afile =3D FDH_FDOPEN(fdP, "r+");=0A=
	if (del)=0A=
	{=0A=
		int cnt1 =3D 0;=0A=
=0A=
		Buf =3D *Bufp;=0A=
		for (i =3D 0; i < *sizep; i++)=0A=
		{=0A=
			if (Buf[i])=0A=
			{=0A=
				cnt++;=0A=
				STREAM_SEEK(afile, Buf[i], 0);=0A=
				code =3D STREAM_READ(vnode, vcp->diskSize, 1, afile);=0A=
				if (code =3D=3D 1)=0A=
				{=0A=
					if (vnode->type !=3D vNull && VNDISK_GET_INO(vnode))=0A=
					{=0A=
						cnt1++;=0A=
						if (1)=0A=
						{=0A=
							Log=0A=
								("RestoreVolume %d Cleanup: Removing old vnode=3D%d inode=3D%d =
size=3D%d\n",=0A=
								V_id(vp), bitNumberToVnodeNumber(i, class),=0A=
								VNDISK_GET_INO(vnode), vnode->length);=0A=
						}=0A=
						IH_DEC(V_linkHandle(vp), VNDISK_GET_INO(vnode),=0A=
							V_parentId(vp));=0A=
						DOPOLL;=0A=
					}=0A=
					STREAM_SEEK(afile, Buf[i], 0);=0A=
					(void) STREAM_WRITE(zero, vcp->diskSize, 1, afile);	/* Zero it out =
*/=0A=
				}=0A=
				Buf[i] =3D 0;=0A=
			}=0A=
		}=0A=
		if (1)=0A=
		{=0A=
			Log("RestoreVolume Cleanup: Removed %d inodes for volume %d\n",=0A=
				cnt1, V_id(vp));=0A=
		}=0A=
		STREAM_FLUSH(afile);	/* ensure 0s are on the disk */=0A=
		OS_SYNC(afile->str_fd);=0A=
	}=0A=
	else=0A=
	{=0A=
		size =3D OS_SIZE(fdP->fd_fd);=0A=
		assert(size !=3D -1)=0A=
			nVnodes =3D (size <=3D vcp->diskSize ? 0 :=0A=
			size - vcp->diskSize) >> vcp->logSize;=0A=
		if (nVnodes > 0)=0A=
		{=0A=
			Buf =3D (afs_int32 *) malloc(nVnodes * sizeof(afs_int32));=0A=
			if (Buf =3D=3D NULL)=0A=
				return 1;=0A=
			bzero((char *) Buf, nVnodes * sizeof(afs_int32));=0A=
			STREAM_SEEK(afile, offset =3D vcp->diskSize, 0);=0A=
			while (1)=0A=
			{=0A=
				code =3D STREAM_READ(vnode, vcp->diskSize, 1, afile);=0A=
				if (code !=3D 1)=0A=
				{=0A=
					break;=0A=
				}=0A=
				if (vnode->type !=3D vNull && VNDISK_GET_INO(vnode))=0A=
				{=0A=
					Buf[(offset >> vcp->logSize) - 1] =3D offset;=0A=
					cnt++;=0A=
				}=0A=
				offset +=3D vcp->diskSize;=0A=
			}=0A=
			*Bufp =3D Buf;=0A=
			*sizep =3D nVnodes;=0A=
		}=0A=
	}=0A=
	STREAM_CLOSE(afile);=0A=
	FDH_CLOSE(fdP);=0A=
	return 0;=0A=
}=0A=
=0A=
int RestoreVolume(register int fd, Volume * avp,=0A=
	int incremental, struct restoreCookie *cookie)=0A=
{=0A=
	VolumeDiskData vol;=0A=
	struct DumpHeader header;=0A=
	afs_uint32 endMagic;=0A=
	Error error =3D 0, vupdate;=0A=
	register Volume *vp;=0A=
	struct iod iod;=0A=
	register struct iod *iodp =3D &iod;=0A=
	afs_int32 *b1 =3D 0, *b2 =3D 0;=0A=
	int s1 =3D 0, s2 =3D 0, delo =3D 0, tdelo;=0A=
	int tag;=0A=
=0A=
	iod_Init(iodp, fd);=0A=
=0A=
	vp =3D avp;=0A=
	if (!ReadDumpHeader(iodp, &header))=0A=
	{=0A=
		Log=0A=
			("1 Volser: RestoreVolume: Error reading header file for dump; =
aborted\n");=0A=
		return VOLSERREAD_DUMPERROR;=0A=
	}=0A=
	if (iod_getc(iodp) !=3D D_VOLUMEHEADER)=0A=
	{=0A=
		Log=0A=
			("1 Volser: RestoreVolume: Volume header missing from dump; not =
restored\n");=0A=
		return VOLSERREAD_DUMPERROR;=0A=
	}=0A=
	if (ReadVolumeHeader(iodp, &vol) =3D=3D VOLSERREAD_DUMPERROR)=0A=
		return VOLSERREAD_DUMPERROR;=0A=
=0A=
	delo =3D ProcessIndex(vp, vLarge, &b1, &s1, 0);=0A=
	if (!delo)=0A=
		delo =3D ProcessIndex(vp, vSmall, &b2, &s2, 0);=0A=
	if (delo)=0A=
	{=0A=
		if (b1)=0A=
			free((char *) b1);=0A=
		if (b2)=0A=
			free((char *) b2);=0A=
		b1 =3D b2 =3D 0;=0A=
	}=0A=
=0A=
	strncpy(vol.name, cookie->name, VOLSER_OLDMAXVOLNAME);=0A=
	vol.type =3D cookie->type;=0A=
	vol.cloneId =3D cookie->clone;=0A=
	vol.parentId =3D cookie->parent;=0A=
=0A=
	tdelo =3D delo;=0A=
	while (1)=0A=
	{=0A=
		if (ReadVnodes(iodp, vp, 0, b1, s1, b2, s2, tdelo))=0A=
		{=0A=
			error =3D VOLSERREAD_DUMPERROR;=0A=
			goto clean;=0A=
		}=0A=
		tag =3D iod_getc(iodp);=0A=
		if (tag !=3D D_VOLUMEHEADER)=0A=
			break;=0A=
		if (ReadVolumeHeader(iodp, &vol) =3D=3D VOLSERREAD_DUMPERROR)=0A=
		{=0A=
			error =3D VOLSERREAD_DUMPERROR;=0A=
			goto out;=0A=
		}=0A=
		tdelo =3D -1;=0A=
	}=0A=
	if (tag !=3D D_DUMPEND || !ReadInt32(iodp, &endMagic)=0A=
		|| endMagic !=3D DUMPENDMAGIC)=0A=
	{=0A=
		Log=0A=
			("1 Volser: RestoreVolume: End of dump not found; restore =
aborted\n");=0A=
		error =3D VOLSERREAD_DUMPERROR;=0A=
		goto clean;=0A=
	}=0A=
=0A=
	if (iod_getc(iodp) !=3D EOF)=0A=
	{=0A=
		Log=0A=
			("1 Volser: RestoreVolume: Unrecognized postamble in dump; restore =
aborted\n");=0A=
		error =3D VOLSERREAD_DUMPERROR;=0A=
		goto clean;=0A=
	}=0A=
=0A=
	if (!delo)=0A=
	{=0A=
		ProcessIndex(vp, vLarge, &b1, &s1, 1);=0A=
		ProcessIndex(vp, vSmall, &b2, &s2, 1);=0A=
	}=0A=
=0A=
  clean:=0A=
	ClearVolumeStats(&vol);=0A=
	CopyVolumeHeader(&vol, &V_disk(vp));=0A=
	V_destroyMe(vp) =3D 0;=0A=
	VUpdateVolume(&vupdate, vp);=0A=
	if (vupdate)=0A=
	{=0A=
		Log=0A=
			("1 Volser: RestoreVolume: Unable to rewrite volume header; restore =
aborted\n");=0A=
		error =3D VOLSERREAD_DUMPERROR;=0A=
		goto out;=0A=
	}=0A=
  out:=0A=
	/* Free the malloced space above */=0A=
	if (b1)=0A=
		free((char *) b1);=0A=
	if (b2)=0A=
		free((char *) b2);=0A=
	return error;=0A=
}=0A=
=0A=
static int ReadVnodes(register struct iod *iodp, Volume * vp,=0A=
	int incremental, afs_int32 * Lbuf, afs_int32 s1,=0A=
	afs_int32 * Sbuf, afs_int32 s2, afs_int32 delo)=0A=
{=0A=
	afs_int32 vnodeNumber;=0A=
	char buf[SIZEOF_LARGEDISKVNODE];=0A=
	register tag;=0A=
	struct VnodeDiskObject *vnode =3D (struct VnodeDiskObject *) buf;=0A=
	struct VnodeDiskObject oldvnode;=0A=
	int idx;=0A=
	VnodeClass class;=0A=
	struct VnodeClassInfo *vcp;=0A=
	IHandle_t *tmpH;=0A=
	FdHandle_t *fdP;=0A=
	Inode nearInode;=0A=
=0A=
	tag =3D iod_getc(iodp);=0A=
	V_pref(vp, nearInode);=0A=
	while (tag =3D=3D D_VNODE)=0A=
	{=0A=
		int haveStuff =3D 0;=0A=
=0A=
		bzero(buf, sizeof(buf));=0A=
		if (!ReadInt32(iodp, (afs_uint32 *) & vnodeNumber))=0A=
			break;=0A=
=0A=
		ReadInt32(iodp, &vnode->uniquifier);=0A=
		while ((tag =3D iod_getc(iodp)) > D_MAX && tag !=3D EOF)=0A=
		{=0A=
			haveStuff =3D 1;=0A=
			switch (tag)=0A=
			{=0A=
				case 't':=0A=
					vnode->type =3D (VnodeType) iod_getc(iodp);=0A=
					break;=0A=
				case 'l':=0A=
					{=0A=
						unsigned short tlc;=0A=
=0A=
						ReadShort(iodp, &tlc);=0A=
						vnode->linkCount =3D (signed int) tlc;=0A=
					}=0A=
					break;=0A=
				case 'v':=0A=
					ReadInt32(iodp, &vnode->dataVersion);=0A=
					break;=0A=
				case 'm':=0A=
					ReadInt32(iodp, &vnode->unixModifyTime);=0A=
					break;=0A=
				case 's':=0A=
					ReadInt32(iodp, &vnode->serverModifyTime);=0A=
					break;=0A=
				case 'a':=0A=
					ReadInt32(iodp, &vnode->author);=0A=
					break;=0A=
				case 'o':=0A=
					ReadInt32(iodp, &vnode->owner);=0A=
					break;=0A=
				case 'g':=0A=
					ReadInt32(iodp, (afs_uint32 *) & vnode->group);=0A=
					break;=0A=
				case 'b':=0A=
					{=0A=
						unsigned short modeBits;=0A=
=0A=
						ReadShort(iodp, &modeBits);=0A=
						vnode->modeBits =3D (unsigned int) modeBits;=0A=
						break;=0A=
					}=0A=
				case 'p':=0A=
					ReadInt32(iodp, &vnode->parent);=0A=
					break;=0A=
				case 'A':=0A=
					ReadByteString(iodp, (byte *) VVnodeDiskACL(vnode),=0A=
						VAclDiskSize(vnode));=0A=
					acl_NtohACL(VVnodeDiskACL(vnode));=0A=
					break;=0A=
				case 'f':=0A=
					{=0A=
						Inode ino;=0A=
						Error error;=0A=
=0A=
						ino =3D IH_CREATE(V_linkHandle(vp),=0A=
							V_device(vp),=0A=
							VPartitionPath(V_partition(vp)),=0A=
							nearInode, V_parentId(vp), vnodeNumber,=0A=
							vnode->uniquifier, vnode->dataVersion);=0A=
						if (!VALID_INO(ino))=0A=
						{=0A=
							perror("unable to allocate inode");=0A=
							Log("1 Volser: ReadVnodes: Restore aborted\n");=0A=
							return VOLSERREAD_DUMPERROR;=0A=
						}=0A=
						nearInode =3D ino;=0A=
						VNDISK_SET_INO(vnode, ino);=0A=
						IH_INIT(tmpH, vp->device, V_parentId(vp), ino);=0A=
						fdP =3D IH_OPEN(tmpH);=0A=
						if (fdP =3D=3D NULL)=0A=
						{=0A=
							IH_RELEASE(tmpH);=0A=
							return VOLSERREAD_DUMPERROR;=0A=
						}=0A=
						vnode->length =3D=0A=
							volser_WriteFile(vnodeNumber, iodp, fdP, &error);=0A=
						FDH_REALLYCLOSE(fdP);=0A=
						IH_RELEASE(tmpH);=0A=
						if (error)=0A=
						{=0A=
							Log("1 Volser: ReadVnodes: IDEC inode %d\n", ino);=0A=
							IH_DEC(V_linkHandle(vp), ino, V_parentId(vp));=0A=
							return VOLSERREAD_DUMPERROR;=0A=
						}=0A=
						break;=0A=
					}=0A=
			}=0A=
		}=0A=
=0A=
		class =3D vnodeIdToClass(vnodeNumber);=0A=
		vcp =3D &VnodeClassInfo[class];=0A=
=0A=
		/* Mark this vnode as in this dump - so we don't delete it later =
*/=0A=
		if (!delo)=0A=
		{=0A=
			idx =3D (vnodeIndexOffset(vcp, vnodeNumber) >> vcp->logSize) - 1;=0A=
			if (class =3D=3D vLarge)=0A=
			{=0A=
				if (Lbuf && (idx < s1))=0A=
					Lbuf[idx] =3D 0;=0A=
			}=0A=
			else=0A=
			{=0A=
				if (Sbuf && (idx < s2))=0A=
					Sbuf[idx] =3D 0;=0A=
			}=0A=
		}=0A=
=0A=
		if (haveStuff)=0A=
		{=0A=
			FdHandle_t *fdP =3D IH_OPEN(vp->vnodeIndex[class].handle);=0A=
=0A=
			if (fdP =3D=3D NULL)=0A=
			{=0A=
				Log=0A=
					("1 Volser: ReadVnodes: Error opening vnode index; restore =
aborted\n");=0A=
				return VOLSERREAD_DUMPERROR;=0A=
			}=0A=
			if (FDH_SEEK(fdP, vnodeIndexOffset(vcp, vnodeNumber),=0A=
					SEEK_SET) < 0)=0A=
			{=0A=
				Log=0A=
					("1 Volser: ReadVnodes: Error seeking into vnode index; restore =
aborted\n");=0A=
				FDH_REALLYCLOSE(fdP);=0A=
				return VOLSERREAD_DUMPERROR;=0A=
			}=0A=
			if (FDH_READ(fdP, &oldvnode,=0A=
					sizeof(oldvnode)) =3D=3D sizeof(oldvnode))=0A=
			{=0A=
				if (oldvnode.type !=3D vNull && VNDISK_GET_INO(&oldvnode))=0A=
				{=0A=
					IH_DEC(V_linkHandle(vp), VNDISK_GET_INO(&oldvnode),=0A=
						V_parentId(vp));=0A=
				}=0A=
			}=0A=
			vnode->vnodeMagic =3D vcp->magic;=0A=
			if (FDH_SEEK(fdP, vnodeIndexOffset(vcp, vnodeNumber),=0A=
					SEEK_SET) < 0)=0A=
			{=0A=
				Log=0A=
					("1 Volser: ReadVnodes: Error seeking into vnode index; restore =
aborted\n");=0A=
				FDH_REALLYCLOSE(fdP);=0A=
				return VOLSERREAD_DUMPERROR;=0A=
			}=0A=
			if (FDH_WRITE(fdP, vnode, vcp->diskSize) !=3D vcp->diskSize)=0A=
			{=0A=
				Log=0A=
					("1 Volser: ReadVnodes: Error writing vnode index; restore =
aborted\n");=0A=
				FDH_REALLYCLOSE(fdP);=0A=
				return VOLSERREAD_DUMPERROR;=0A=
			}=0A=
			FDH_CLOSE(fdP);=0A=
		}=0A=
	}=0A=
	iod_ungetc(iodp, tag);=0A=
=0A=
	return 0;=0A=
}=0A=
=0A=
/* called with disk file only.  Note that we don't have to worry about =
rx_Read=0A=
 * needing to read an ungetc'd character, since the ReadInt32 will have =
read=0A=
 * it instead.=0A=
 */=0A=
static bit32 volser_WriteFile(int vn, struct iod *iodp, FdHandle_t * =
handleP,=0A=
	Error * status)=0A=
{=0A=
	afs_int32 code;=0A=
	afs_uint32 filesize;=0A=
	bit32 written =3D 0;=0A=
	register afs_uint32 size =3D 8192;=0A=
	register afs_uint32 nbytes;=0A=
	unsigned char *p;=0A=
=0A=
	*status =3D 0;=0A=
	if (!ReadInt32(iodp, &filesize))=0A=
	{=0A=
		*status =3D 1;=0A=
		return (0);=0A=
	}=0A=
	p =3D (unsigned char *) malloc(size);=0A=
	if (p =3D=3D NULL)=0A=
	{=0A=
		*status =3D 2;=0A=
		return (0);=0A=
	}=0A=
	for (nbytes =3D filesize; nbytes; nbytes -=3D size)=0A=
	{=0A=
		if (nbytes < size)=0A=
			size =3D nbytes;=0A=
=0A=
		if ((code =3D iod_Read(iodp, p, size)) !=3D size)=0A=
		{=0A=
			Log=0A=
				("1 Volser: WriteFile: Error reading dump file %d size=3D%d =
nbytes=3D%d (%d of %d); restore aborted\n",=0A=
				vn, filesize, nbytes, code, size);=0A=
			*status =3D 3;=0A=
			break;=0A=
		}=0A=
		code =3D FDH_WRITE(handleP, p, size);=0A=
		if (code > 0)=0A=
			written +=3D code;=0A=
		if (code !=3D size)=0A=
		{=0A=
			Log=0A=
				("1 Volser: WriteFile: Error creating file in volume; restore =
aborted\n");=0A=
			*status =3D 4;=0A=
			break;=0A=
		}=0A=
	}=0A=
	free(p);=0A=
	return (written);=0A=
}=0A=
=0A=
static int ReadDumpHeader(register struct iod *iodp, struct DumpHeader =
*hp)=0A=
{=0A=
	register tag;=0A=
	afs_uint32 beginMagic;=0A=
=0A=
	if (iod_getc(iodp) !=3D D_DUMPHEADER || !ReadInt32(iodp, =
&beginMagic)=0A=
		|| !ReadInt32(iodp, (afs_uint32 *) & hp->version)=0A=
		|| beginMagic !=3D DUMPBEGINMAGIC) return 0;=0A=
	hp->volumeId =3D 0;=0A=
	hp->nDumpTimes =3D 0;=0A=
	while ((tag =3D iod_getc(iodp)) > D_MAX)=0A=
	{=0A=
		unsigned short arrayLength;=0A=
		register int i;=0A=
=0A=
		switch (tag)=0A=
		{=0A=
			case 'v':=0A=
				if (!ReadInt32(iodp, &hp->volumeId))=0A=
					return 0;=0A=
				break;=0A=
			case 'n':=0A=
				ReadString(iodp, hp->volumeName, sizeof(hp->volumeName));=0A=
				break;=0A=
			case 't':=0A=
				if (!ReadShort(iodp, &arrayLength))=0A=
					return 0;=0A=
				hp->nDumpTimes =3D (arrayLength >> 1);=0A=
				for (i =3D 0; i < hp->nDumpTimes; i++)=0A=
					if (!ReadInt32(iodp,=0A=
							(afs_uint32 *) & hp->dumpTimes[i].from)=0A=
						|| !ReadInt32(iodp,=0A=
							(afs_uint32 *) & hp->dumpTimes[i].to))=0A=
						return 0;=0A=
				break;=0A=
		}=0A=
	}=0A=
	if (!hp->volumeId || !hp->nDumpTimes)=0A=
	{=0A=
		return 0;=0A=
	}=0A=
	iod_ungetc(iodp, tag);=0A=
	return 1;=0A=
}=0A=

------_=_NextPart_000_01C0B0AD.1DDD7F60
Content-Type: application/octet-stream;
	name="vol-info.c"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="vol-info.c"

/*=0A=
 * Copyright 2000, International Business Machines Corporation and =
others.=0A=
 * All Rights Reserved.=0A=
 * =0A=
 * This software has been released under the terms of the IBM Public=0A=
 * License.  For details, see the LICENSE file in the top-level =
source=0A=
 * directory or online at http://www.openafs.org/dl/license10.html=0A=
 */=0A=
=0A=
#ifndef lint=0A=
#endif=0A=
/*=0A=
   System:		VICE-TWO=0A=
   Module:		vol-info.c=0A=
   Institution:	The Information Technology Center, Carnegie-Mellon =
University=0A=
   =0A=
   */=0A=
=0A=
#include <afs/param.h>=0A=
#include <ctype.h>=0A=
#include <errno.h>=0A=
#include <sys/stat.h>=0A=
#include <stdio.h>=0A=
#include <string.h>=0A=
#ifdef AFS_NT40_ENV=0A=
#include <fcntl.h>=0A=
#include <time.h>=0A=
#include <io.h>=0A=
#else=0A=
#include <sys/param.h>=0A=
#include <sys/file.h>=0A=
#include <sys/time.h>=0A=
#endif=0A=
#include <afs/cmd.h>=0A=
=0A=
#include <rx/xdr.h>=0A=
#include <afs/afsint.h>=0A=
#include "nfs.h"=0A=
#include <afs/errors.h>=0A=
#include "lock.h"=0A=
#include "lwp.h"=0A=
#include <afs/afssyscalls.h>=0A=
#include "ihandle.h"=0A=
#include "vnode.h"=0A=
#include "volume.h"=0A=
#include "partition.h"=0A=
#include "viceinode.h"=0A=
#include "volinodes.h"=0A=
#include <afs/afssyscalls.h>=0A=
=0A=
#ifdef _AIX=0A=
#include <time.h>=0A=
#endif=0A=
=0A=
#include <dirent.h>=0A=
=0A=
int DumpVnodes =3D 0;	/* Dump everything, i.e. summary of all vnodes =
*/=0A=
int DumpInodeNumber =3D 0;	/* Dump inode numbers with vnodes */=0A=
int DumpDate =3D 0;		/* Dump vnode date (server modify date) with vnode =
*/=0A=
int InodeTimes =3D 0;		/* Dump some of the dates associated with inodes =
*/=0A=
int online =3D 0;=0A=
int dheader=3D0;=0A=
int dsizeOnly =3D 0, totvolsize=3D0, Vauxsize =3D 0, Vdiskused =3D 0, =
Vvnodesize =3D 0;=0A=
int Totvolsize=3D0, TVauxsize =3D 0, TVdiskused =3D 0, TVvnodesize =3D =
0;=0A=
int Stotvolsize=3D0, SVauxsize =3D 0, SVdiskused =3D 0, SVvnodesize =3D =
0;=0A=
int fixheader =3D 0, saveinodes =3D 0, orphaned=3D0;=0A=
int VolumeChanged;=0A=
=0A=
/* Forward Declarations */=0A=
void PrintHeader(register Volume *vp);=0A=
void HandleAllPart(void);=0A=
void HandlePart(struct DiskPartition *partP);=0A=
void HandleVolume(struct DiskPartition *partP, char *name);=0A=
struct DiskPartition *FindCurrentPartition(void);=0A=
Volume *AttachVolume(struct DiskPartition *dp, char *volname,=0A=
		     register struct VolumeHeader *header);=0A=
void PrintVnode(int offset, VnodeDiskObject *vnode, int vnodeNumber,=0A=
		Inode ino);=0A=
void PrintVnodes(Volume *vp, VnodeClass class);=0A=
=0A=
char *date(time_t date)=0A=
{=0A=
    static char results[8][100];=0A=
    static next;=0A=
    struct tm *tm =3D localtime(&date);=0A=
    char buf[32];=0A=
=0A=
    strftime (buf, 32, "%Y/%m/%d.%H:%M:%S", tm); /* NT does not have %T =
*/=0A=
    sprintf(results[next =3D (next+1)&7], "%lu (%s)", (unsigned long) =
date, buf);=0A=
    return results[next];=0A=
}=0A=
=0A=
#ifndef AFS_NT40_ENV=0A=
#include "AFS_component_version_number.c"=0A=
#endif=0A=
=0A=
char name[VMAXPATHLEN];=0A=
=0A=
char BU[1000];=0A=
=0A=
int ReadHdr1(IHandle_t *ih, char *to, int size, u_int magic, u_int =
version)=0A=
{=0A=
    struct versionStamp *vsn;=0A=
    int bad=3D0; =0A=
    int code;=0A=
=0A=
    vsn =3D (struct versionStamp *) to;=0A=
    =0A=
    code =3D IH_IREAD(ih, 0, to, size);=0A=
    if (code !=3D size)=0A=
	return -1;=0A=
=0A=
    if (vsn->magic !=3D magic) {=0A=
	bad++;=0A=
	printf("Inode %s: Bad magic %x (%x): IGNORED\n",=0A=
	       PrintInode(NULL, ih->ih_ino), vsn->magic, magic);=0A=
    }=0A=
=0A=
    /* Check is conditional, in case caller wants to inspect version =
himself */=0A=
    if (version && vsn->version !=3D version) {=0A=
	bad++;=0A=
	printf("Inode %s: Bad version %x (%x): IGNORED\n",=0A=
	       PrintInode(NULL, ih->ih_ino), vsn->version, version);=0A=
    }=0A=
    if (bad && fixheader) {=0A=
	vsn->magic =3D magic;=0A=
	vsn->version =3D version;=0A=
	printf("Special index inode %s has a bad header. =
Reconstructing...\n",=0A=
	       PrintInode(NULL, ih->ih_ino));=0A=
	code =3D IH_IWRITE(ih, 0, to, size);=0A=
	if (code !=3D size) {=0A=
	    printf("Write failed; header left in damaged state\n");=0A=
	}=0A=
    } else {=0A=
	if (!dsizeOnly && !saveinodes) {=0A=
	    printf("Inode %s: Good magic %x and version %x\n",=0A=
		   PrintInode(NULL, ih->ih_ino), magic, version);=0A=
	}=0A=
    }=0A=
    return 0;=0A=
}=0A=
=0A=
=0A=
Volume *AttachVolume(struct DiskPartition *dp, char *volname,=0A=
		     register struct VolumeHeader *header)=0A=
{=0A=
    register Volume *vp;=0A=
    afs_int32 ec =3D 0;=0A=
=0A=
    vp =3D (Volume *) calloc(1, sizeof(Volume));=0A=
    vp->specialStatus =3D 0;=0A=
    vp->device =3D dp->device;=0A=
    vp->partition =3D dp;=0A=
    IH_INIT(vp->vnodeIndex[vLarge].handle, dp->device, =
header->parent,=0A=
	    header->largeVnodeIndex);=0A=
    IH_INIT(vp->vnodeIndex[vSmall].handle, dp->device, =
header->parent,=0A=
	    header->smallVnodeIndex);=0A=
    IH_INIT(vp->diskDataHandle, dp->device, header->parent,=0A=
	    header->volumeInfo);=0A=
    IH_INIT(V_linkHandle(vp), dp->device, header->parent,=0A=
	    header->linkTable);=0A=
    vp->cacheCheck =3D 0;		/* XXXX */=0A=
    vp->shuttingDown =3D 0;=0A=
    vp->goingOffline =3D 0;=0A=
    vp->nUsers =3D 1;=0A=
    vp->header =3D (struct volHeader *) calloc(1, sizeof(*vp->header)); =
   =0A=
    ec =3D ReadHdr1(V_diskDataHandle(vp),=0A=
		 (char *)&V_disk(vp), sizeof(V_disk(vp)),=0A=
		 VOLUMEINFOMAGIC, VOLUMEINFOVERSION);=0A=
    if (!ec) {=0A=
	struct IndexFileHeader iHead;=0A=
    	ec =3D ReadHdr1(vp->vnodeIndex[vSmall].handle,=0A=
		     (char *)&iHead, sizeof(iHead),=0A=
		     SMALLINDEXMAGIC, SMALLINDEXVERSION);=0A=
    }=0A=
    if (!ec) {=0A=
	struct IndexFileHeader iHead;=0A=
	ec =3D ReadHdr1(vp->vnodeIndex[vLarge].handle,=0A=
		     (char *)&iHead, sizeof(iHead),=0A=
		     LARGEINDEXMAGIC, LARGEINDEXVERSION);=0A=
    }=0A=
#ifdef AFS_NAMEI_ENV=0A=
    if (!ec) {=0A=
	struct versionStamp stamp;=0A=
	ec =3D ReadHdr1(V_linkHandle(vp),=0A=
		     (char *)&stamp, sizeof(stamp),=0A=
		     LINKTABLEMAGIC, LINKTABLEVERSION);=0A=
    }=0A=
#endif=0A=
    if (ec) return (Volume *)0;=0A=
    return vp;=0A=
}=0A=
=0A=
=0A=
static int handleit(struct cmd_syndesc *as)=0A=
{=0A=
    register struct cmd_item *ti;=0A=
    int err =3D 0;=0A=
    int volumeId=3D0;=0A=
    char *partName =3D 0;=0A=
    struct DiskPartition *partP=3D NULL;=0A=
=0A=
    =0A=
#ifndef AFS_NT40_ENV=0A=
    if (geteuid() !=3D 0) { =0A=
	printf("vol-info must be run as root; sorry\n");=0A=
	exit(1);=0A=
    }=0A=
#endif=0A=
=0A=
    if (as->parms[0].items)=0A=
	online =3D 1;=0A=
    else    =0A=
	online =3D 0;=0A=
    if (as->parms[1].items)=0A=
	DumpVnodes =3D 1;=0A=
    else    =0A=
	DumpVnodes =3D 0;=0A=
    if (as->parms[2].items)=0A=
	DumpDate =3D 1;=0A=
    else    =0A=
	DumpDate =3D 0;=0A=
    if (as->parms[3].items)=0A=
	DumpInodeNumber =3D 1;=0A=
    else    =0A=
	DumpInodeNumber =3D 0;=0A=
    if (as->parms[4].items)=0A=
	InodeTimes =3D 1;=0A=
    else    =0A=
	InodeTimes =3D 0;=0A=
    if (ti =3D as->parms[5].items)=0A=
	partName =3D ti->data;=0A=
    if (ti =3D as->parms[6].items)=0A=
	volumeId =3D atoi(ti->data);=0A=
    if (as->parms[7].items)=0A=
	dheader =3D 1;=0A=
    else    =0A=
	dheader =3D 0;=0A=
    if (as->parms[8].items) {=0A=
	dsizeOnly =3D 1;=0A=
	dheader =3D 1;=0A=
	DumpVnodes =3D 1;=0A=
    } else    =0A=
	dsizeOnly =3D 0;=0A=
    if (as->parms[9].items) {=0A=
	fixheader =3D 1;=0A=
    } else    =0A=
	fixheader =3D 0;=0A=
    if (as->parms[10].items) {=0A=
	saveinodes =3D 1;=0A=
	dheader =3D 1;=0A=
	DumpVnodes =3D 1;=0A=
    } else    =0A=
	saveinodes =3D 0;=0A=
    if (as->parms[11].items) {=0A=
	orphaned =3D 1;=0A=
	DumpVnodes =3D 1;=0A=
    } else    =0A=
	orphaned =3D 0;    =0A=
=0A=
    DInit(10);=0A=
=0A=
    err =3D VAttachPartitions();=0A=
    if (err) {=0A=
	printf("%d partitions had errors during attach.\n", err);=0A=
    }=0A=
=0A=
    if (partName) {=0A=
	partP =3D VGetPartition(partName, 0);=0A=
	if (!partP) {=0A=
	    printf("%s is not an AFS partition name on this server.\n",=0A=
		   partName);=0A=
	    exit(1);=0A=
	}=0A=
    }=0A=
=0A=
    if (!volumeId) {=0A=
	if (!partP) {=0A=
	    HandleAllPart();=0A=
	} else {=0A=
	    HandlePart(partP);=0A=
	}=0A=
    } else {=0A=
	char name1[128];=0A=
	=0A=
	if (!partP) {=0A=
	    partP =3D FindCurrentPartition();=0A=
	    if (!partP) {=0A=
		printf("Current partition is not a vice partition.\n");=0A=
		exit(1);=0A=
	    }=0A=
	}=0A=
	sprintf(name1,VFORMAT,volumeId);=0A=
	if (dsizeOnly && !saveinodes)=0A=
	    printf("Volume-Id\t  Volsize  Auxsize Inodesize  AVolsize SizeDiff =
               (VolName)\n");=0A=
	HandleVolume(partP, name1);=0A=
    }=0A=
    return 0;=0A=
}=0A=
=0A=
#ifdef AFS_NT40_ENV=0A=
#include <direct.h>=0A=
struct DiskPartition *FindCurrentPartition()=0A=
{=0A=
    int dr =3D _getdrive();=0A=
    struct DiskPartition *dp;=0A=
    =0A=
    dr --;=0A=
    for(dp =3D DiskPartitionList; dp; dp =3D dp->next) {=0A=
	if (*dp->devName - 'A' =3D=3D dr)=0A=
	    break;=0A=
    }=0A=
    if (!dp) {=0A=
	printf("Current drive is not a valid vice partition.\n");=0A=
    }=0A=
    return dp;=0A=
}=0A=
#else=0A=
struct DiskPartition *FindCurrentPartition()=0A=
{=0A=
    char partName[1024];=0A=
    char tmp =3D '\0';=0A=
    char *p;=0A=
    struct DiskPartition *dp;=0A=
=0A=
    if (!getcwd(partName, 1023)) {=0A=
	perror("pwd");=0A=
	exit(1);=0A=
    }=0A=
    p =3D strchr(&partName[1], '/');=0A=
    if (p) {=0A=
	tmp =3D *p;=0A=
	*p =3D '\0';=0A=
    }=0A=
    if (!(dp =3D VGetPartition(partName, 0))) {=0A=
	if (tmp) *p =3D tmp;=0A=
	printf("%s is not a valid vice partition.\n", partName);=0A=
	exit(1);=0A=
    }=0A=
    return dp;=0A=
}=0A=
#endif=0A=
=0A=
void HandleAllPart(void)=0A=
{=0A=
    struct DiskPartition *partP;=0A=
=0A=
=0A=
    for (partP =3D DiskPartitionList; partP; partP =3D partP->next) =
{=0A=
	printf("Processing Partition %s:\n", partP->name);=0A=
	HandlePart(partP);=0A=
	Stotvolsize +=3D Totvolsize;=0A=
	SVauxsize +=3D TVauxsize;=0A=
	SVvnodesize +=3D TVvnodesize;=0A=
	SVdiskused +=3D TVdiskused;=0A=
    }=0A=
=0A=
    if (dsizeOnly) {=0A=
	printf("\nServer Totals%12d%9d%10d%10d%9d\n",=0A=
	       SVdiskused, SVauxsize, SVvnodesize, Stotvolsize,=0A=
	       Stotvolsize-SVdiskused);=0A=
    }=0A=
}=0A=
=0A=
=0A=
void HandlePart(struct DiskPartition *partP)=0A=
{=0A=
    int nvols=3D0;=0A=
    DIR *dirp;=0A=
    struct dirent  *dp;=0A=
#ifdef AFS_NT40_ENV=0A=
    char pname[64];=0A=
    char *p =3D pname;=0A=
    (void) sprintf(pname, "%s\\", VPartitionPath(partP));=0A=
#else=0A=
    char *p =3D VPartitionPath(partP);=0A=
#endif=0A=
    =0A=
    if (chdir(p) =3D=3D -1) {=0A=
	printf("Can't chdir to partition %s; giving up\n", p);=0A=
	exit(1);=0A=
    }=0A=
    if ((dirp =3D opendir(".")) =3D=3D NULL) {=0A=
	printf("Can't read directory %s; giving up\n", p);=0A=
	exit(1);=0A=
    }=0A=
    if (dsizeOnly && !saveinodes)=0A=
	printf("Volume-Id\t  Volsize  Auxsize Inodesize  AVolsize SizeDiff     =
           (VolName)\n");=0A=
    while (dp =3D readdir(dirp)) {=0A=
	p =3D (char *)rindex(dp->d_name, '.');=0A=
	if (p !=3D NULL && strcmp(p, VHDREXT) =3D=3D 0) {=0A=
	    HandleVolume(partP, dp->d_name);		=0A=
	    Totvolsize +=3D totvolsize;=0A=
	    TVauxsize +=3D Vauxsize;=0A=
	    TVvnodesize +=3D Vvnodesize;=0A=
	    TVdiskused +=3D Vdiskused;=0A=
	    nvols++;=0A=
	} =0A=
    }=0A=
    closedir(dirp);=0A=
    if (dsizeOnly) {=0A=
	printf("\nPart Totals  %12d%9d%10d%10d%9d (%d volumes)\n\n",=0A=
	       TVdiskused, TVauxsize, TVvnodesize, Totvolsize,=0A=
	       Totvolsize-TVdiskused, nvols);=0A=
    }=0A=
}=0A=
=0A=
=0A=
void HandleVolume(struct DiskPartition *dp, char *name) =0A=
{=0A=
    struct VolumeHeader header;=0A=
    struct VolumeDiskHeader diskHeader;=0A=
    struct stat status, stat;=0A=
    register int fd;=0A=
    Volume *vp;=0A=
    IHandle_t *ih;=0A=
    char headerName[1024];=0A=
=0A=
    if (online) {=0A=
	printf("volinfo: -online not supported\n");=0A=
	exit(1);=0A=
    } else {=0A=
	afs_int32 n;=0A=
=0A=
	(void) sprintf(headerName, "%s/%s", VPartitionPath(dp), name);=0A=
	if ((fd =3D open(headerName, O_RDONLY)) =3D=3D -1=0A=
	    || fstat(fd,&status) =3D=3D -1) {=0A=
	    printf("Volinfo: Cannot read volume header %s\n", name);=0A=
	    close(fd);=0A=
	    exit(1);=0A=
	}=0A=
	n =3D read(fd, &diskHeader, sizeof (diskHeader));=0A=
=0A=
	if (n !=3D sizeof (diskHeader)=0A=
	    || diskHeader.stamp.magic !=3D VOLUMEHEADERMAGIC) {=0A=
	    printf("Volinfo: Error reading volume header %s\n", name);=0A=
	    exit(1);=0A=
	}=0A=
	if (diskHeader.stamp.version !=3D VOLUMEHEADERVERSION) {=0A=
	    printf("Volinfo: Volume %s, version number is incorrect; volume =
needs salvage\n",name);=0A=
	    exit(1);=0A=
	}=0A=
	DiskToVolumeHeader(&header, &diskHeader);=0A=
=0A=
	if (dheader) {=0A=
	    FdHandle_t *fdP;=0A=
	    int size =3D 0;=0A=
	    int code;=0A=
=0A=
	    if (fstat(fd, &stat) =3D=3D -1) {=0A=
		perror("stat");=0A=
		exit(1);=0A=
	    }		=0A=
	    if (!dsizeOnly && !saveinodes) {=0A=
		printf("Volume header (size =3D %d):\n", size =3D stat.st_size);=0A=
		printf("\tstamp\t=3D 0x%x\n", header.stamp.version);=0A=
		printf("\tVolId\t=3D %d\n", header.id);=0A=
	    }=0A=
=0A=
	    IH_INIT(ih, dp->device , header.id, header.volumeInfo);=0A=
	    fdP =3D IH_OPEN(ih);=0A=
	    if (fdP =3D=3D NULL) {=0A=
		perror("opening volume info");=0A=
		exit(1);=0A=
	    }=0A=
	    code =3D FDH_SIZE(fdP);=0A=
	    if (code =3D=3D -1) {=0A=
		perror("fstat");=0A=
		exit(1);=0A=
	    }	    =0A=
	    FDH_REALLYCLOSE(fdP);=0A=
	    IH_RELEASE(ih);=0A=
	    size +=3D code;=0A=
	    if (!dsizeOnly && !saveinodes) {=0A=
		printf("\tparent\t=3D %d\n", header.parent);=0A=
		printf("\tInfo inode\t=3D %s (size =3D %d)\n",=0A=
		       PrintInode(NULL, header.volumeInfo), code);=0A=
	    }=0A=
=0A=
	    IH_INIT(ih, dp->device , header.id,  header.smallVnodeIndex);=0A=
	    fdP =3D IH_OPEN(ih);=0A=
	    if (fdP =3D=3D NULL) {=0A=
		perror("opening small vnode index");=0A=
		exit(1);=0A=
	    }=0A=
	    code =3D FDH_SIZE(fdP);=0A=
	    if (code =3D=3D -1) {=0A=
		perror("fstat");=0A=
		exit(1);=0A=
	    }	    =0A=
	    FDH_REALLYCLOSE(fdP);=0A=
	    IH_RELEASE(ih);=0A=
	    size +=3D code;=0A=
	    if (!dsizeOnly && !saveinodes) {=0A=
		printf("\tSmall inode\t=3D %s (size =3D %d)\n",=0A=
		       PrintInode(NULL, header.smallVnodeIndex), code);=0A=
	    }=0A=
=0A=
	    IH_INIT(ih, dp->device, header.id, header.largeVnodeIndex);=0A=
	    fdP =3D IH_OPEN(ih);=0A=
	    if (fdP =3D=3D NULL) {=0A=
		perror("opening large vnode index");=0A=
		exit(1);=0A=
	    }=0A=
	    code =3D FDH_SIZE(fdP);=0A=
	    if (code =3D=3D -1) {=0A=
		perror("fstat");=0A=
		exit(1);=0A=
	    }	    =0A=
	    FDH_REALLYCLOSE(fdP);=0A=
	    IH_RELEASE(ih);=0A=
	    size +=3D code;=0A=
	    if (!dsizeOnly && !saveinodes) {=0A=
		printf("\tLarge inode\t=3D %s (size =3D %d)\n",=0A=
		       PrintInode(NULL, header.largeVnodeIndex), code);=0A=
#ifndef AFS_NT40_ENV=0A=
		printf("Total aux volume size =3D %d\n\n", size);=0A=
#endif=0A=
	    }=0A=
#ifdef AFS_NAMEI_ENV=0A=
	    IH_INIT(ih, dp->device, header.id, header.linkTable);=0A=
	    fdP =3D IH_OPEN(ih);=0A=
	    if (fdP =3D=3D NULL) {=0A=
		perror("opening link table index");=0A=
		exit(1);=0A=
	    }=0A=
	    code =3D FDH_SIZE(fdP);=0A=
	    if (code =3D=3D -1) {=0A=
		perror("fstat");=0A=
		exit(1);=0A=
	    }	    =0A=
	    FDH_REALLYCLOSE(fdP);=0A=
	    IH_RELEASE(ih);=0A=
	    size +=3D code;=0A=
	    if (!dsizeOnly && !saveinodes) {=0A=
		printf("\tLink inode\t=3D %s (size =3D %d)\n",=0A=
		       PrintInode(NULL, header.linkTable), code);=0A=
		printf("Total aux volume size =3D %d\n\n", size);=0A=
	    }=0A=
#endif=0A=
	    Vauxsize =3D size;=0A=
	}=0A=
	close(fd);=0A=
	vp =3D AttachVolume(dp, name, &header);=0A=
	if (!vp) {=0A=
	    printf("Volinfo: Error attaching volume header %s\n", name);=0A=
	    exit(1);=0A=
	}=0A=
    }=0A=
    PrintHeader(vp);=0A=
    if (DumpVnodes) {=0A=
	if (!dsizeOnly && !saveinodes)=0A=
	    printf("\nLarge vnodes (directories)\n");=0A=
	PrintVnodes(vp, vLarge);=0A=
	if (!dsizeOnly && !saveinodes) {=0A=
	    printf("\nSmall vnodes(files, symbolic links)\n");=0A=
	    fflush(stdout);=0A=
	}=0A=
	if (saveinodes) =0A=
	    printf("Saving all volume files to current directory ...\n");=0A=
	PrintVnodes(vp, vSmall);=0A=
    }=0A=
    if (dsizeOnly) {=0A=
	Vauxsize =3D Vauxsize/1024;=0A=
	Vvnodesize =3D Vvnodesize/1024;=0A=
	totvolsize =3D Vauxsize + Vvnodesize;=0A=
	if (saveinodes)=0A=
	    printf("Volume-Id\t  Volsize  Auxsize Inodesize  AVolsize SizeDiff =
               (VolName)\n");=0A=
=0A=
	printf("%d\t%9d%9d%10d%10d%9d\t%24s\n",=0A=
	       V_id(vp), Vdiskused, Vauxsize, Vvnodesize, totvolsize,=0A=
	       totvolsize-Vdiskused, V_name(vp));=0A=
    }=0A=
}=0A=
=0A=
=0A=
main(argc,argv)=0A=
char **argv;=0A=
{=0A=
    register struct cmd_syndesc *ts;=0A=
    afs_int32 code;=0A=
=0A=
    ts =3D cmd_CreateSyntax((char *)0, handleit, 0, "Dump volume's =
internal state");=0A=
    cmd_AddParm(ts, "-online", CMD_FLAG, CMD_OPTIONAL, "Get info from =
running fileserver");=0A=
    cmd_AddParm(ts, "-vnode", CMD_FLAG, CMD_OPTIONAL, "Dump vnode =
info");=0A=
    cmd_AddParm(ts, "-date", CMD_FLAG, CMD_OPTIONAL, "Also dump vnode's =
mod date");=0A=
    cmd_AddParm(ts, "-inode", CMD_FLAG, CMD_OPTIONAL, "Dump vnode's =
inode number");=0A=
    cmd_AddParm(ts, "-itime", CMD_FLAG, CMD_OPTIONAL, "Dump special =
inode's mod times");=0A=
    cmd_AddParm(ts, "-part", CMD_LIST, CMD_OPTIONAL, "AFS partition =
name (default current partition)");=0A=
    cmd_AddParm(ts, "-volumeid", CMD_LIST, CMD_OPTIONAL, "Volume =
id");=0A=
    cmd_AddParm(ts, "-header", CMD_FLAG, CMD_OPTIONAL, "Dump volume's =
header info");=0A=
    cmd_AddParm(ts, "-sizeOnly", CMD_FLAG, CMD_OPTIONAL, "Dump volume's =
size");=0A=
    cmd_AddParm(ts, "-fixheader", CMD_FLAG, CMD_OPTIONAL, "Try to fix =
header");    =0A=
    cmd_AddParm(ts, "-saveinodes", CMD_FLAG, CMD_OPTIONAL, "Try to save =
all inodes");    =0A=
    cmd_AddParm(ts, "-orphaned", CMD_FLAG, CMD_OPTIONAL, "List all =
dir/files without a parent");    =0A=
    code =3D cmd_Dispatch(argc, argv);=0A=
    return code;=0A=
}=0A=
=0A=
#define typestring(type) (type =3D=3D RWVOL? "read/write": type =3D=3D =
ROVOL? "readonly": type =3D=3D BACKVOL? "backup": "unknown")=0A=
=0A=
void PrintHeader(register Volume *vp)=0A=
{=0A=
    Vdiskused =3D V_diskused(vp);=0A=
    if (dsizeOnly || saveinodes) return;=0A=
    printf("Volume header for volume %u (%s)\n", V_id(vp), =
V_name(vp));=0A=
    printf("stamp.magic =3D %x, stamp.version =3D %u\n", =
V_stamp(vp).magic,=0A=
	V_stamp(vp).version);=0A=
    printf("inUse =3D %d, inService =3D %d, blessed =3D %d, =
needsSalvaged =3D %d, dontSalvage =3D %d\n",=0A=
	V_inUse(vp), V_inService(vp), V_blessed(vp), V_needsSalvaged(vp), =
V_dontSalvage(vp));=0A=
    printf("type =3D %d (%s), uniquifier =3D %u, needsCallback =3D %d, =
destroyMe =3D %x\n",=0A=
	V_type(vp), typestring(V_type(vp)), V_uniquifier(vp), =
V_needsCallback(vp), =0A=
	V_destroyMe(vp));=0A=
    printf("id =3D %u, parentId =3D %u, cloneId =3D %u, backupId =3D =
%u, restoredFromId =3D %u\n",=0A=
	V_id(vp), V_parentId(vp), V_cloneId(vp), V_backupId(vp), =
V_restoredFromId(vp));=0A=
    printf("maxquota =3D %d, minquota =3D %d, maxfiles =3D %d, =
filecount =3D %d, diskused =3D %d\n",=0A=
	V_maxquota(vp), V_minquota(vp), V_maxfiles(vp), V_filecount(vp), =
V_diskused(vp));=0A=
    printf("creationDate =3D %s, copyDate =3D %s\n", =
date(V_creationDate(vp)), date(V_copyDate(vp)));=0A=
    printf("backupDate =3D %s, expirationDate =3D %s\n", =
date(V_backupDate(vp)), date(V_expirationDate(vp)));=0A=
    printf("accessDate =3D %s, updateDate =3D %s\n", =
date(V_accessDate(vp)), date(V_updateDate(vp)));=0A=
    printf("owner =3D %u, accountNumber =3D %u\n", V_owner(vp), =
V_accountNumber(vp));=0A=
    printf("dayUse =3D %u; week =3D (%u, %u, %u, %u, %u, %u, %u), =
dayUseDate =3D %s\n",=0A=
	V_dayUse(vp), V_weekUse(vp)[0], V_weekUse(vp)[1], V_weekUse(vp)[2],=0A=
	=
V_weekUse(vp)[3],V_weekUse(vp)[4],V_weekUse(vp)[5],V_weekUse(vp)[6],=0A=
	date(V_dayUseDate(vp)));=0A=
}=0A=
=0A=
/* GetFileInfo=0A=
 * OS independent file info. Die on failure.=0A=
 */=0A=
#ifdef AFS_NT40_ENV=0A=
char *NT_date(FILETIME *ft)=0A=
{=0A=
    static char result[8][64];=0A=
    static int next =3D 0;=0A=
    SYSTEMTIME st;=0A=
    FILETIME lft;=0A=
    =0A=
    if (!FileTimeToLocalFileTime(ft, &lft) ||=0A=
	!FileTimeToSystemTime(&lft, &st)) {=0A=
	printf("Time conversion failed.\n");=0A=
	exit(1);=0A=
    }=0A=
    sprintf(result[next =3D ((next+1)&7)], =
"%4d/%02d/%02d.%2d:%2d:%2d",=0A=
	    st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute,=0A=
	    st.wSecond);=0A=
    return result[next];=0A=
}=0A=
#endif=0A=
=0A=
static void GetFileInfo(FD_t fd, int *size, char **ctime, char =
**mtime,=0A=
		       char **atime)=0A=
{=0A=
#ifdef AFS_NT40_ENV=0A=
    BY_HANDLE_FILE_INFORMATION fi;=0A=
    if (!GetFileInformationByHandle(fd, &fi)) {=0A=
	printf("GetFileInformationByHandle failed, exiting\n");=0A=
	exit(1);=0A=
    }=0A=
    *size =3D (int)fi.nFileSizeLow;=0A=
    *ctime =3D "N/A";=0A=
    *mtime =3D NT_date(&fi.ftLastWriteTime);=0A=
    *atime =3D NT_date(&fi.ftLastAccessTime);=0A=
#else=0A=
    struct stat status;=0A=
    if (fstat(fd, &status) =3D=3D -1) {=0A=
	printf("fstat failed %d\n", errno);=0A=
	exit(1);=0A=
    }=0A=
    *size =3D (int)status.st_size;=0A=
    *ctime =3D date(status.st_ctime);=0A=
    *mtime =3D date(status.st_mtime);=0A=
    *atime =3D date(status.st_atime);=0A=
#endif=0A=
}=0A=
=0A=
void PrintVnodes(Volume *vp, VnodeClass class)=0A=
{=0A=
    afs_int32 diskSize =3D (class =3D=3D vSmall ?=0A=
		      SIZEOF_SMALLDISKVNODE : SIZEOF_LARGEDISKVNODE);=0A=
    char buf[SIZEOF_LARGEDISKVNODE];=0A=
    struct VnodeDiskObject *vnode =3D (struct VnodeDiskObject *) =
buf;=0A=
    StreamHandle_t *file;=0A=
    register int vnodeIndex, nVnodes, offset=3D0;=0A=
    Inode ino;=0A=
    IHandle_t *ih =3D vp->vnodeIndex[class].handle;=0A=
    FdHandle_t *fdP;=0A=
    int size;=0A=
    char *ctime, *atime, *mtime;=0A=
    char nfile[50], buffer[256];=0A=
    int total, ofd, len, code, bad=3D0;=0A=
=0A=
    fdP =3D IH_OPEN(ih);=0A=
    if (fdP =3D=3D NULL) {=0A=
	printf("open failed\n");=0A=
	exit(1);=0A=
    }=0A=
=0A=
    file =3D FDH_FDOPEN(fdP, "r");=0A=
    if (!file) {=0A=
	printf("fdopen failed\n");=0A=
	exit(1);=0A=
    }=0A=
=0A=
    GetFileInfo(fdP->fd_fd, &size, &ctime, &atime, &mtime);=0A=
    if (InodeTimes && !dsizeOnly) {=0A=
	printf("ichanged : %s\nimodified: %s\niaccessed: %s\n\n",=0A=
	       ctime, mtime, atime);=0A=
    }=0A=
=0A=
    nVnodes =3D (size / diskSize) - 1;=0A=
    if (nVnodes > 0) {=0A=
	STREAM_SEEK(file, diskSize, 0);=0A=
    }=0A=
    else nVnodes =3D 0;=0A=
=0A=
    for (vnodeIndex =3D 0; nVnodes && STREAM_READ(vnode, diskSize, 1, =
file) =3D=3D 1;=0A=
	 nVnodes--, vnodeIndex++, offset +=3D diskSize) {=0A=
=0A=
	ino =3D VNDISK_GET_INO(vnode);=0A=
	if (saveinodes) {=0A=
	    if (VALID_INO(ino) && (class =3D=3D vSmall)) {=0A=
		IHandle_t *ih1;=0A=
		FdHandle_t *fdP1;=0A=
		IH_INIT(ih1, V_device(vp), V_parentId(vp), ino);=0A=
		fdP1  =3D IH_OPEN(ih1);=0A=
		if (fdP1 =3D=3D NULL) {=0A=
		    printf("Can't open inode %s error %d (ignored)\n",=0A=
			   PrintInode(NULL, ino), errno);=0A=
		    continue;=0A=
		}=0A=
		sprintf(nfile, "TmpInode.%s", PrintInode(NULL, ino));=0A=
		printf("About to copy inode %d to file %s...\n",=0A=
		       (int) ino, nfile);=0A=
		ofd =3D open(nfile, O_CREAT | O_RDWR | O_TRUNC, 0600);=0A=
		if (ofd < 0) {=0A=
		    printf("Can't create file %s; error %d (ignored)\n", nfile, =
errno);=0A=
		    continue;=0A=
		}	    =0A=
		total =3D bad =3D 0;=0A=
		while (1) {=0A=
		    len =3D FDH_READ(fdP1, buffer, sizeof(buffer));=0A=
		    if (len < 0) {=0A=
			FDH_REALLYCLOSE(fdP1);=0A=
			IH_RELEASE(ih1);=0A=
			close(ofd);=0A=
			unlink(nfile);=0A=
			printf("Error while reading from inode %s (%d - ignored)\n",=0A=
			       PrintInode(NULL, ino), errno);=0A=
			bad =3D 1;=0A=
			break;=0A=
		    }=0A=
		    if (len =3D=3D 0) break;	   /* No more input */=0A=
		    code =3D write(ofd, buffer, len);=0A=
		    if (code !=3D len) {=0A=
			FDH_REALLYCLOSE(fdP1);=0A=
			IH_RELEASE(ih1);=0A=
			close(ofd);=0A=
			unlink(nfile);=0A=
			printf("Error while writing to \"%s\" (%d - ignored)\n", nfile, =
errno);=0A=
			bad =3D 1;=0A=
			break;=0A=
		    }=0A=
		    total +=3D len;=0A=
		}=0A=
		if (bad) continue;=0A=
		FDH_REALLYCLOSE(fdP1);=0A=
		IH_RELEASE(ih1);=0A=
		close(ofd);=0A=
		printf("... Copied inode %d to file %s (%d bytes)\n",=0A=
		       (int) ino, nfile, total);=0A=
	    }=0A=
	} else {=0A=
	    PrintVnode(offset, vnode,=0A=
		       bitNumberToVnodeNumber(vnodeIndex, class), ino);=0A=
	}=0A=
    }=0A=
    STREAM_CLOSE(file);=0A=
    FDH_CLOSE(fdP);=0A=
}=0A=
=0A=
void PrintVnode(int offset, VnodeDiskObject *vnode, int vnodeNumber, =
Inode ino)=0A=
{=0A=
    Vvnodesize +=3D vnode->length;=0A=
    if (dsizeOnly) return;=0A=
    if (orphaned && (vnode->length =3D=3D0 || vnode->parent || =
!offset)) return;=0A=
    printf("%10d Vnode %u.%u.%u cloned: %d, length: %d linkCount: %d =
parent: %d",=0A=
        offset, vnodeNumber, vnode->uniquifier, vnode->dataVersion, =
vnode->cloned, vnode->length, vnode->linkCount, vnode->parent);=0A=
    if (DumpInodeNumber)=0A=
	printf(" inode: %s", PrintInode(NULL, ino));=0A=
    if (DumpDate)=0A=
	printf(" ServerModTime: %s", date(vnode->serverModifyTime));=0A=
    printf("\n");=0A=
}=0A=

------_=_NextPart_000_01C0B0AD.1DDD7F60
Content-Type: application/octet-stream;
	name="vol-util.diff"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="vol-util.diff"

Index: vol/Makefile=0A=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
RCS file: /cvs/openafs/src/vol/Makefile,v=0A=
retrieving revision 1.3=0A=
diff -u -u -r1.3 Makefile=0A=
--- vol/Makefile	2001/01/31 21:28:01	1.3=0A=
+++ vol/Makefile	2001/03/19 19:40:15=0A=
@@ -10,7 +10,7 @@=0A=
 include ../config/Makefile.${SYS_NAME}=0A=
 include ../config/Makefile.version=0A=
 =0A=
-INCDIRS=3D -I. -I${DESTDIR}include ${FSINCLUDES}=0A=
+INCDIRS=3D -I. -I${DESTDIR}include -I../volser ${FSINCLUDES}=0A=
 INSTALL =3D ${SRCDIR}bin/install=0A=
 LDFLAGS =3D ${OPTMZ} ${PROF} ${LDIRS} ${XLDFLAGS}=0A=
 =0A=
@@ -30,11 +30,12 @@=0A=
 	 namei_ops.o=0A=
 =0A=
 =0A=
-OBJECTS=3D${VLIBOBJS} physio.o vol-salvage.o vol-info.o =0A=
+OBJECTS=3D${VLIBOBJS} physio.o vol-salvage.o vol-info.o vol-util.o =
dumpstuff.o=0A=
 =0A=
 all:	${DESTDIR}lib/afs/vlib.a \=0A=
 	${DESTDIR}root.server/usr/afs/bin/salvager \=0A=
 	${DESTDIR}root.server/usr/afs/bin/volinfo \=0A=
+	${DESTDIR}root.server/usr/afs/bin/volutil \=0A=
 	gi=0A=
 =0A=
 system: install=0A=
@@ -48,6 +49,9 @@=0A=
 ${DESTDIR}root.server/usr/afs/bin/volinfo: volinfo=0A=
 	${INSTALL} -s $? $@=0A=
 =0A=
+${DESTDIR}root.server/usr/afs/bin/volutil: volutil=0A=
+	${INSTALL} -s $? $@=0A=
+=0A=
 ${DESTDIR}lib/afs/vlib.a: vlib.a=0A=
 	${INSTALL} $? $@=0A=
 =0A=
@@ -88,6 +92,7 @@=0A=
 =0A=
 vol-salvage: vol-salvage.o=0A=
 vol-info: vol-info.o physio.o ihandle.o=0A=
+vol-util: vol-util.o physio.o ihandle.o dumpstuff.o =0A=
 =0A=
 listinodes.o: listinodes.c AFS_component_version_number.c=0A=
 	case ${SYS_NAME} in				\=0A=
@@ -108,15 +113,12 @@=0A=
         esac=0A=
 =0A=
 volinfo: vol-info.o physio.o ihandle.o=0A=
-	case ${SYS_NAME} in \=0A=
-		*linux*) \=0A=
-			${CC} ${CFLAGS} ${DBG} -o volinfo vol-info.o physio.o \=0A=
-				ihandle.o ${LIBS}  ;; \=0A=
-		*) \=0A=
-			${CC} ${CFLAGS} ${DBG} -o volinfo vol-info.o physio.o \=0A=
-				 ihandle.o ${LIBS} ;; \=0A=
-	esac=0A=
+	${CC} ${CFLAGS} ${DBG} -o volinfo vol-info.o physio.o \=0A=
+		ihandle.o ${LIBS}=0A=
 =0A=
+volutil: vol-util.o physio.o ihandle.o dumpstuff.o=0A=
+	${CC} ${CFLAGS} ${DBG} -o volutil vol-util.o physio.o \=0A=
+		ihandle.o dumpstuff.o ${LIBS}=0A=
 =0A=
 fs_conv_dux40D: fs_conv_411.o=0A=
 	${CC} ${CFLAGS} ${DESTDIR}lib/afs/libcmd.a -o fs_conv_dux40D =
fs_conv_411.o  ${LIBS} =0A=

------_=_NextPart_000_01C0B0AD.1DDD7F60--