From 3467c697025a8d857a023cba549f0218e6dbb04e Mon Sep 17 00:00:00 2001 From: Nathan Neulinger Date: Thu, 28 Aug 2003 04:16:33 +0000 Subject: [PATCH] voldump-builds-with-volser-20030827 avoid circular dependancy issue. --- src/vol/Makefile.in | 12 +- src/vol/vol-dump.c | 872 ------------------------------------------------- src/volser/Makefile.in | 26 +- src/volser/vol-dump.c | 871 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 896 insertions(+), 885 deletions(-) delete mode 100644 src/vol/vol-dump.c create mode 100644 src/volser/vol-dump.c diff --git a/src/vol/Makefile.in b/src/vol/Makefile.in index 81368a6..18ba917 100644 --- a/src/vol/Makefile.in +++ b/src/vol/Makefile.in @@ -30,7 +30,6 @@ all: gi \ ${TOP_LIBDIR}/libvlib.a \ salvager \ volinfo \ - voldump \ $(FS_CONV_OSF40D) \ $(XFS_SIZE_CHECK) \ $(FS_CONV_SOL26) \ @@ -52,7 +51,6 @@ install: \ ${DESTDIR}${libdir}/afs/libvlib.a \ ${DESTDIR}${afssrvlibexecdir}/salvager \ ${DESTDIR}${afssrvsbindir}/volinfo \ - ${DESTDIR}${afssrvsbindir}/voldump \ $(install_FS_CONV_OSF40D) \ $(install_XFS_SIZE_CHECK) \ $(install_FS_CONV_SOL26) \ @@ -164,10 +162,6 @@ volinfo: vol-info.o physio.o ihandle.o ${LIBS} ${CC} ${CFLAGS} -o volinfo vol-info.o physio.o \ ihandle.o ${LIBS} ${XLIBS} -voldump: vol-dump.o physio.o ihandle.o ${LIBS} - ${CC} ${CFLAGS} -o voldump vol-dump.o physio.o \ - ihandle.o ${LIBS} ${XLIBS} - fs_conv_dux40D: fs_conv_411.o ${CC} ${CFLAGS} ${TOP_LIBDIR}/libcmd.a -o fs_conv_dux40D fs_conv_411.o ${LIBS} ${XLIBS} @@ -185,7 +179,7 @@ xfs_size_check: xfs_size_check.c # clean: $(RM) -f *.o *.a AFS_component_version_number.c - $(RM) -f ${SCMPROGS} ${STAGEPROGS} core salvager volinfo voldump gi fs_conv_sol26 fs_conv_dux40D + $(RM) -f ${SCMPROGS} ${STAGEPROGS} core salvager volinfo gi fs_conv_sol26 fs_conv_dux40D test: cd test; $(MAKE) @@ -209,9 +203,6 @@ ${DESTDIR}${afssrvlibexecdir}/salvager: salvager ${DESTDIR}${afssrvsbindir}/volinfo: volinfo ${INSTALL} -s $? $@ -${DESTDIR}${afssrvsbindir}/voldump: voldump - ${INSTALL} -s $? $@ - ${DESTDIR}${includedir}/afs/nfs.h: nfs.h ${INSTALL} $? $@ @@ -271,7 +262,6 @@ dest: \ ${DEST}/lib/afs/libvlib.a \ ${DEST}/root.server/usr/afs/bin/salvager \ ${DEST}/root.server/usr/afs/bin/volinfo \ - ${DEST}/root.server/usr/afs/bin/voldump \ $(dest_FS_CONV_OSF40D) \ $(dest_XFS_SIZE_CHECK) \ $(dest_FS_CONV_SOL26) \ diff --git a/src/vol/vol-dump.c b/src/vol/vol-dump.c deleted file mode 100644 index cdb2430..0000000 --- a/src/vol/vol-dump.c +++ /dev/null @@ -1,872 +0,0 @@ -/* - * Copyright 2000, International Business Machines Corporation and others. - * All Rights Reserved. - * - * This software has been released under the terms of the IBM Public - * License. For details, see the LICENSE file in the top-level source - * directory or online at http://www.openafs.org/dl/license10.html - */ - -/* - System: VICE-TWO - Module: vol-dump.c - Institution: The Information Technology Center, Carnegie-Mellon University - - */ - -#include -#include - -RCSID - ("$Header$"); - -#include -#include -#include -#include -#include -#ifdef AFS_NT40_ENV -#include -#include -#include -#else -#include -#include -#include -#endif -#include - -#include -#include -#include "nfs.h" -#include -#include "lock.h" -#include "lwp.h" -#include -#include "ihandle.h" -#include "vnode.h" -#include "volume.h" -#include "partition.h" -#include "viceinode.h" -#include "volinodes.h" -#include -#include "acl.h" - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_STDLIB_H -#include -#endif - -#ifdef HAVE_FCNTL_H -#include -#endif - -#ifdef _AIX -#include -#endif - -#include - -#include "volser/volser.h" -#include "volser/volint.h" -#include "volser/dump.h" - -#define putint32(p, v) *p++ = v>>24, *p++ = v>>16, *p++ = v>>8, *p++ = v -#define putshort(p, v) *p++ = v>>8, *p++ = v - -#ifdef O_LARGEFILE -#define afs_stat stat64 -#define afs_fstat fstat64 -#define afs_open open64 -#else /* !O_LARGEFILE */ -#define afs_stat stat -#define afs_fstat fstat -#define afs_open open -#endif /* !O_LARGEFILE */ - -int VolumeChanged; /* needed by physio - leave alone */ -int verbose = 0; - -/* Forward Declarations */ -void HandleVolume(struct DiskPartition *partP, char *name, char *filename); -Volume *AttachVolume(struct DiskPartition *dp, char *volname, - register struct VolumeHeader *header); -static void DoMyVolDump(Volume * vp, struct DiskPartition *dp, - char *dumpfile); - -#ifndef AFS_NT40_ENV -#include "AFS_component_version_number.c" -#endif - -char name[VMAXPATHLEN]; - - -int -ReadHdr1(IHandle_t * ih, char *to, int size, u_int magic, u_int version) -{ - int bad = 0; - int code; - - code = IH_IREAD(ih, 0, to, size); - if (code != size) - return -1; - - return 0; -} - - -Volume * -AttachVolume(struct DiskPartition * dp, char *volname, - register struct VolumeHeader * header) -{ - register Volume *vp; - afs_int32 ec = 0; - - vp = (Volume *) calloc(1, sizeof(Volume)); - vp->specialStatus = 0; - vp->device = dp->device; - vp->partition = dp; - IH_INIT(vp->vnodeIndex[vLarge].handle, dp->device, header->parent, - header->largeVnodeIndex); - IH_INIT(vp->vnodeIndex[vSmall].handle, dp->device, header->parent, - header->smallVnodeIndex); - IH_INIT(vp->diskDataHandle, dp->device, header->parent, - header->volumeInfo); - IH_INIT(V_linkHandle(vp), dp->device, header->parent, header->linkTable); - vp->cacheCheck = 0; /* XXXX */ - vp->shuttingDown = 0; - vp->goingOffline = 0; - vp->nUsers = 1; - vp->header = (struct volHeader *)calloc(1, sizeof(*vp->header)); - ec = ReadHdr1(V_diskDataHandle(vp), (char *)&V_disk(vp), - sizeof(V_disk(vp)), VOLUMEINFOMAGIC, VOLUMEINFOVERSION); - if (!ec) { - struct IndexFileHeader iHead; - ec = ReadHdr1(vp->vnodeIndex[vSmall].handle, (char *)&iHead, - sizeof(iHead), SMALLINDEXMAGIC, SMALLINDEXVERSION); - } - if (!ec) { - struct IndexFileHeader iHead; - ec = ReadHdr1(vp->vnodeIndex[vLarge].handle, (char *)&iHead, - sizeof(iHead), LARGEINDEXMAGIC, LARGEINDEXVERSION); - } -#ifdef AFS_NAMEI_ENV - if (!ec) { - struct versionStamp stamp; - ec = ReadHdr1(V_linkHandle(vp), (char *)&stamp, sizeof(stamp), - LINKTABLEMAGIC, LINKTABLEVERSION); - } -#endif - if (ec) - return (Volume *) 0; - return vp; -} - - -static int -handleit(struct cmd_syndesc *as, char *arock) -{ - register struct cmd_item *ti; - int err = 0; - int volumeId = 0; - char *partName = 0; - char *fileName = NULL; - struct DiskPartition *partP = NULL; - char name1[128]; - char tmpPartName[20]; - - -#ifndef AFS_NT40_ENV -#if 0 - if (geteuid() != 0) { - fprintf(stderr, "voldump must be run as root; sorry\n"); - exit(1); - } -#endif -#endif - - if ((ti = as->parms[0].items)) - partName = ti->data; - if ((ti = as->parms[1].items)) - volumeId = atoi(ti->data); - if ((ti = as->parms[2].items)) - fileName = ti->data; - if ((ti = as->parms[3].items)) - verbose = 1; - - DInit(10); - - err = VAttachPartitions(); - if (err) { - fprintf(stderr, "%d partitions had errors during attach.\n", err); - } - - if (partName) { - if (strlen(partName) == 1) { - if (partName[0] >= 'a' && partName[0] <= 'z') { - strcpy(tmpPartName, "/vicepa"); - tmpPartName[6] = partName[0]; - partP = VGetPartition(tmpPartName, 0); - } - } else { - partP = VGetPartition(partName, 0); - } - if (!partP) { - fprintf(stderr, - "%s is not an AFS partition name on this server.\n", - partName); - exit(1); - } - } - - if (!volumeId) { - fprintf(stderr, "Must specify volume id!\n"); - exit(1); - } - - if (!partP) { - fprintf(stderr, "must specify vice partition.\n"); - exit(1); - } - - (void)afs_snprintf(name1, sizeof name1, VFORMAT, (unsigned long)volumeId); - HandleVolume(partP, name1, fileName); - return 0; -} - -void -HandleVolume(struct DiskPartition *dp, char *name, char *filename) -{ - struct VolumeHeader header; - struct VolumeDiskHeader diskHeader; - struct afs_stat status, stat; - register int fd; - Volume *vp; - IHandle_t *ih; - char headerName[1024]; - - afs_int32 n; - - (void)afs_snprintf(headerName, sizeof headerName, "%s/%s", - VPartitionPath(dp), name); - if ((fd = afs_open(headerName, O_RDONLY)) == -1 - || afs_fstat(fd, &status) == -1) { - fprintf(stderr, "Cannot read volume header %s\n", name); - close(fd); - exit(1); - } - n = read(fd, &diskHeader, sizeof(diskHeader)); - - if (n != sizeof(diskHeader) - || diskHeader.stamp.magic != VOLUMEHEADERMAGIC) { - fprintf(stderr, "Error reading volume header %s\n", name); - exit(1); - } - if (diskHeader.stamp.version != VOLUMEHEADERVERSION) { - fprintf(stderr, - "Volume %s, version number is incorrect; volume needs salvage\n", - name); - exit(1); - } - DiskToVolumeHeader(&header, &diskHeader); - - close(fd); - vp = AttachVolume(dp, name, &header); - if (!vp) { - fprintf(stderr, "Error attaching volume header %s\n", name); - exit(1); - } - - DoMyVolDump(vp, dp, filename); -} - - -int -main(int argc, char **argv) -{ - register struct cmd_syndesc *ts; - afs_int32 code; - - VInitVolumePackage(volumeUtility, 5, 5, DONT_CONNECT_FS, 0); - - ts = cmd_CreateSyntax(NULL, handleit, 0, - "Dump a volume to a 'vos dump' format file without using volserver"); - cmd_AddParm(ts, "-part", CMD_LIST, CMD_OPTIONAL, "AFS partition name"); - cmd_AddParm(ts, "-volumeid", CMD_LIST, CMD_OPTIONAL, "Volume id"); - cmd_AddParm(ts, "-file", CMD_LIST, CMD_OPTIONAL, "Dump filename"); - cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, - "Trace dump progress (very verbose)"); - code = cmd_Dispatch(argc, argv); - return code; -} - - - - -static int -DumpDouble(int dumpfd, char tag, register afs_uint32 value1, - register afs_uint32 value2) -{ - int res; - char tbuffer[9]; - register byte *p = (unsigned char *)tbuffer; - *p++ = tag; - putint32(p, value1); - putint32(p, value2); - - res = write(dumpfd, tbuffer, 9); - return ((res == 9) ? 0 : VOLSERDUMPERROR); -} - -static int -DumpInt32(int dumpfd, char tag, register afs_uint32 value) -{ - char tbuffer[5]; - register byte *p = (unsigned char *)tbuffer; - *p++ = tag; - putint32(p, value); - return ((write(dumpfd, tbuffer, 5) == 5) ? 0 : VOLSERDUMPERROR); -} - -static int -DumpString(int dumpfd, char tag, register char *s) -{ - register int n; - int code = 0; - code = write(dumpfd, &tag, 1); - if (code != 1) - return VOLSERDUMPERROR; - n = strlen(s) + 1; - code = write(dumpfd, s, n); - if (code != n) - return VOLSERDUMPERROR; - return 0; -} - - -static int -DumpArrayInt32(int dumpfd, char tag, register afs_uint32 * array, - register int nelem) -{ - char tbuffer[4]; - register afs_uint32 v; - int code = 0; - register byte *p = (unsigned char *)tbuffer; - *p++ = tag; - putshort(p, nelem); - code = write(dumpfd, tbuffer, 3); - if (code != 3) - return VOLSERDUMPERROR; - while (nelem--) { - p = (unsigned char *)tbuffer; - v = *array++; /*this was register */ - - putint32(p, v); - code = write(dumpfd, tbuffer, 4); - if (code != 4) - return VOLSERDUMPERROR; - } - return 0; -} - - - - -static int -DumpDumpHeader(int dumpfd, register Volume * vp, afs_int32 fromtime) -{ - int code = 0; - afs_int32 dumpTimes[2]; - - if (verbose) - fprintf(stderr, "dumping dump header\n"); - - if (!code) - code = DumpDouble(dumpfd, D_DUMPHEADER, DUMPBEGINMAGIC, DUMPVERSION); - - if (!code) - code = DumpInt32(dumpfd, 'v', V_id(vp)); - - if (!code) - code = DumpString(dumpfd, 'n', V_name(vp)); - - dumpTimes[0] = fromtime; - dumpTimes[1] = V_backupDate(vp); /* Until the time the clone was made */ - if (!code) - code = DumpArrayInt32(dumpfd, 't', (afs_uint32 *) dumpTimes, 2); - - return code; -} - - -static int -DumpEnd(int dumpfd) -{ - return (DumpInt32(dumpfd, D_DUMPEND, DUMPENDMAGIC)); -} - -static int -DumpByte(int dumpfd, char tag, byte value) -{ - char tbuffer[2]; - register byte *p = (unsigned char *)tbuffer; - *p++ = tag; - *p = value; - return ((write(dumpfd, tbuffer, 2) == 2) ? 0 : VOLSERDUMPERROR); -} - -static int -DumpTag(int dumpfd, register int tag) -{ - char p; - - p = tag; - return ((write(dumpfd, &p, 1) == 1) ? 0 : VOLSERDUMPERROR); - -} - -static int -DumpBool(int dumpfd, char tag, unsigned int value) -{ - char tbuffer[2]; - register byte *p = (unsigned char *)tbuffer; - *p++ = tag; - *p = value; - return ((write(dumpfd, tbuffer, 2) == 2) ? 0 : VOLSERDUMPERROR); -} - - - -static int -DumpVolumeHeader(int dumpfd, register Volume * vp) -{ - int code = 0; - - if (verbose) - fprintf(stderr, "dumping volume header\n"); - - if (!code) - code = DumpTag(dumpfd, D_VOLUMEHEADER); - if (!code) - code = DumpInt32(dumpfd, 'i', V_id(vp)); - if (!code) - code = DumpInt32(dumpfd, 'v', V_stamp(vp).version); - if (!code) - code = DumpString(dumpfd, 'n', V_name(vp)); - if (!code) - code = DumpBool(dumpfd, 's', V_inService(vp)); - if (!code) - code = DumpBool(dumpfd, 'b', V_blessed(vp)); - if (!code) - code = DumpInt32(dumpfd, 'u', V_uniquifier(vp)); - if (!code) - code = DumpByte(dumpfd, 't', (byte) V_type(vp)); - if (!code) - code = DumpInt32(dumpfd, 'p', V_parentId(vp)); - if (!code) - code = DumpInt32(dumpfd, 'c', V_cloneId(vp)); - if (!code) - code = DumpInt32(dumpfd, 'q', V_maxquota(vp)); - if (!code) - code = DumpInt32(dumpfd, 'm', V_minquota(vp)); - if (!code) - code = DumpInt32(dumpfd, 'd', V_diskused(vp)); - if (!code) - code = DumpInt32(dumpfd, 'f', V_filecount(vp)); - if (!code) - code = DumpInt32(dumpfd, 'a', V_accountNumber(vp)); - if (!code) - code = DumpInt32(dumpfd, 'o', V_owner(vp)); - if (!code) - code = DumpInt32(dumpfd, 'C', V_creationDate(vp)); /* Rw volume creation date */ - if (!code) - code = DumpInt32(dumpfd, 'A', V_accessDate(vp)); - if (!code) - code = DumpInt32(dumpfd, 'U', V_updateDate(vp)); - if (!code) - code = DumpInt32(dumpfd, 'E', V_expirationDate(vp)); - if (!code) - code = DumpInt32(dumpfd, 'B', V_backupDate(vp)); /* Rw volume backup clone date */ - if (!code) - code = DumpString(dumpfd, 'O', V_offlineMessage(vp)); - - /* - * We do NOT dump the detailed volume statistics residing in the old - * motd field, since we cannot tell from the info in a dump whether - * statistics data has been put there. Instead, we dump a null string, - * just as if that was what the motd contained. - */ - if (!code) - code = DumpString(dumpfd, 'M', ""); - if (!code) - code = - DumpArrayInt32(dumpfd, 'W', (afs_uint32 *) V_weekUse(vp), - sizeof(V_weekUse(vp)) / sizeof(V_weekUse(vp)[0])); - if (!code) - code = DumpInt32(dumpfd, 'D', V_dayUseDate(vp)); - if (!code) - code = DumpInt32(dumpfd, 'Z', V_dayUse(vp)); - return code; -} - -static int -DumpShort(int dumpfd, char tag, unsigned int value) -{ - char tbuffer[3]; - register byte *p = (unsigned char *)tbuffer; - *p++ = tag; - *p++ = value >> 8; - *p = value; - return ((write(dumpfd, tbuffer, 3) == 3) ? 0 : VOLSERDUMPERROR); -} - -static int -DumpByteString(int dumpfd, char tag, register byte * bs, register int nbytes) -{ - int code = 0; - - code = write(dumpfd, &tag, 1); - if (code != 1) - return VOLSERDUMPERROR; - code = write(dumpfd, (char *)bs, nbytes); - if (code != nbytes) - return VOLSERDUMPERROR; - return 0; -} - - -static int -DumpFile(int dumpfd, int vnode, FdHandle_t * handleP, struct VnodeDiskObject *v) -{ - int code = 0, failed_seek = 0, failed_write = 0; - afs_int32 pad = 0, offset; - afs_sfsize_t n, nbytes, howMany, howBig; - byte *p; -#ifndef AFS_NT40_ENV - struct afs_stat status; -#endif - afs_sfsize_t size, tmpsize; -#ifdef AFS_AIX_ENV -#include - struct statfs tstatfs; -#endif - - if (verbose) - fprintf(stderr, "dumping file for vnode %d\n", vnode); - -#ifdef AFS_NT40_ENV - howBig = _filelength(handleP->fd_fd); - howMany = 4096; - -#else - afs_fstat(handleP->fd_fd, &status); - howBig = status.st_size; - -#ifdef AFS_AIX_ENV - /* Unfortunately in AIX valuable fields such as st_blksize are - * gone from the stat structure. - */ - fstatfs(handleP->fd_fd, &tstatfs); - howMany = tstatfs.f_bsize; -#else - howMany = status.st_blksize; -#endif /* AFS_AIX_ENV */ -#endif /* AFS_NT40_ENV */ - - - size = FDH_SIZE(handleP); - - if (verbose) - fprintf(stderr, " howBig = %u, howMany = %u, fdh size = %u\n", - howBig, howMany, size); - -#ifdef AFS_LARGEFILE_ENV - { - afs_uint32 hi, lo; - SplitInt64(size, hi, lo); - if (hi == 0L) { - code = DumpInt32(dumpfd, 'f', lo); - } else { - code = DumpDouble(dumpfd, 'h', hi, lo); - } - } -#else /* !AFS_LARGEFILE_ENV */ - code = DumpInt32(dumpfd, 'f', size); -#endif /* !AFS_LARGEFILE_ENV */ - if (code) { - return VOLSERDUMPERROR; - } - - p = (unsigned char *)malloc(howMany); - if (!p) { - fprintf(stderr, "out of memory!\n"); - return VOLSERDUMPERROR; - } - - /* loop through whole file, while we still have bytes left, and no errors, in chunks of howMany bytes */ - for (nbytes = size; (nbytes && !failed_write); nbytes -= howMany) { - if (nbytes < howMany) - howMany = nbytes; - - /* Read the data - unless we know we can't */ - n = (failed_seek ? 0 : FDH_READ(handleP, p, howMany)); - - /* If read any good data and we null padded previously, log the - * amount that we had null padded. - */ - if ((n > 0) && pad) { - fprintf(stderr, "Null padding file %d bytes at offset %u\n", pad, - offset); - pad = 0; - } - - /* If didn't read enough data, null padd the rest of the buffer. This - * can happen if, for instance, the media has some bad spots. We don't - * want to quit the dump, so we start null padding. - */ - if (n < howMany) { - - if (verbose) fprintf(stderr, " read %u instead of %u bytes.\n", n, howMany); - - /* Record the read error */ - if (n < 0) { - n = 0; - fprintf(stderr, "Error %d reading inode %s for vnode %d\n", - errno, PrintInode(NULL, handleP->fd_ih->ih_ino), - vnode); - } else if (!pad) { - fprintf(stderr, "Error reading inode %s for vnode %d\n", - PrintInode(NULL, handleP->fd_ih->ih_ino), vnode); - } - - /* Pad the rest of the buffer with zeros. Remember offset we started - * padding. Keep total tally of padding. - */ - memset(p + n, 0, howMany - n); - if (!pad) - offset = (howBig - nbytes) + n; - pad += (howMany - n); - - /* Now seek over the data we could not get. An error here means we - * can't do the next read. - */ - failed_seek = FDH_SEEK(handleP, ((size - nbytes) + howMany), SEEK_SET); - if (failed_seek != ((size - nbytes) + howMany)) { - if (failed_seek < 0) { - fprintf(stderr, - "Error %d seeking in inode %s for vnode %d\n", - errno, PrintInode(NULL, handleP->fd_ih->ih_ino), - vnode); - } else { - fprintf(stderr, - "Error seeking in inode %s for vnode %d\n", - PrintInode(NULL, handleP->fd_ih->ih_ino), vnode); - failed_seek = -1; - } - } else { - failed_seek = 0; - } - } - - /* Now write the data out */ - if (write(dumpfd, (char *)p, howMany) != howMany) - failed_write = VOLSERDUMPERROR; - } - - if (pad) { /* Any padding we hadn't reported yet */ - fprintf(stderr, "Null padding file: %d bytes at offset %u\n", pad, - offset); - } - - free(p); - return failed_write; -} - - -static int -DumpVnode(int dumpfd, struct VnodeDiskObject *v, int volid, int vnodeNumber, - int dumpEverything, struct Volume *vp) -{ - int code = 0; - IHandle_t *ihP; - FdHandle_t *fdP; - - if (verbose) - fprintf(stderr, "dumping vnode %d\n", vnodeNumber); - - if (!v || v->type == vNull) - return code; - if (!code) - code = DumpDouble(dumpfd, D_VNODE, vnodeNumber, v->uniquifier); - if (!dumpEverything) - return code; - if (!code) - code = DumpByte(dumpfd, 't', (byte) v->type); - if (!code) - code = DumpShort(dumpfd, 'l', v->linkCount); /* May not need this */ - if (!code) - code = DumpInt32(dumpfd, 'v', v->dataVersion); - if (!code) - code = DumpInt32(dumpfd, 'm', v->unixModifyTime); - if (!code) - code = DumpInt32(dumpfd, 'a', v->author); - if (!code) - code = DumpInt32(dumpfd, 'o', v->owner); - if (!code && v->group) - code = DumpInt32(dumpfd, 'g', v->group); /* default group is 0 */ - if (!code) - code = DumpShort(dumpfd, 'b', v->modeBits); - if (!code) - code = DumpInt32(dumpfd, 'p', v->parent); - if (!code) - code = DumpInt32(dumpfd, 's', v->serverModifyTime); - if (v->type == vDirectory) { - acl_HtonACL(VVnodeDiskACL(v)); - if (!code) - code = - DumpByteString(dumpfd, 'A', (byte *) VVnodeDiskACL(v), - VAclDiskSize(v)); - } - - if (VNDISK_GET_INO(v)) { - IH_INIT(ihP, V_device(vp), V_parentId(vp), VNDISK_GET_INO(v)); - fdP = IH_OPEN(ihP); - if (fdP == NULL) { - fprintf(stderr, - "Unable to open inode %s for vnode %u (volume %i); not dumped, error %d\n", - PrintInode(NULL, VNDISK_GET_INO(v)), vnodeNumber, volid, - errno); - } - else - { - if (verbose) - fprintf(stderr, "about to dump inode %s for vnode %u\n", - PrintInode(NULL, VNDISK_GET_INO(v)), vnodeNumber); - code = DumpFile(dumpfd, vnodeNumber, fdP, v); - FDH_CLOSE(fdP); - } - IH_RELEASE(ihP); - } - - if (verbose) - fprintf(stderr, "done dumping vnode %d\n", vnodeNumber); - return code; -} - - -static int -DumpVnodeIndex(int dumpfd, Volume * vp, VnodeClass class, afs_int32 fromtime, - int forcedump) -{ - register int code = 0; - register struct VnodeClassInfo *vcp = &VnodeClassInfo[class]; - char buf[SIZEOF_LARGEDISKVNODE]; - struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf; - StreamHandle_t *file; - FdHandle_t *fdP; - int size; - int flag; - int offset = 0; - register int vnodeIndex, nVnodes = 0; - - fdP = IH_OPEN(vp->vnodeIndex[class].handle); - file = FDH_FDOPEN(fdP, "r+"); - size = OS_SIZE(fdP->fd_fd); - nVnodes = (size / vcp->diskSize) - 1; - - if (nVnodes > 0) { - STREAM_SEEK(file, vcp->diskSize, 0); - } else - nVnodes = 0; - for (vnodeIndex = 0; - nVnodes && STREAM_READ(vnode, vcp->diskSize, 1, file) == 1 && !code; - nVnodes--, vnodeIndex++, offset += vcp->diskSize) { - flag = forcedump || (vnode->serverModifyTime >= fromtime); - /* Note: the >= test is very important since some old volumes may not have - * a serverModifyTime. For an epoch dump, this results in 0>=0 test, which - * does dump the file! */ - if (verbose) - fprintf(stderr, "about to dump %s vnode %u (vnode offset = %u)\n", - class == vSmall ? "vSmall" : "vLarge", - bitNumberToVnodeNumber(vnodeIndex, class), offset); - if (!code) - code = - DumpVnode(dumpfd, vnode, V_id(vp), - bitNumberToVnodeNumber(vnodeIndex, class), flag, - vp); - } - STREAM_CLOSE(file); - FDH_CLOSE(fdP); - return code; -} - - - -/* A partial dump (no dump header) */ -static int -DumpPartial(int dumpfd, register Volume * vp, afs_int32 fromtime, - int dumpAllDirs) -{ - int code = 0; - - if (verbose) - fprintf(stderr, "about to dump the volume header\n"); - if (!code) - code = DumpVolumeHeader(dumpfd, vp); - - if (verbose) - fprintf(stderr, "about to dump the large vnode index\n"); - if (!code) - code = DumpVnodeIndex(dumpfd, vp, vLarge, fromtime, dumpAllDirs); - - if (verbose) - fprintf(stderr, "about to dump the small vnode index\n"); - if (!code) - code = DumpVnodeIndex(dumpfd, vp, vSmall, fromtime, 0); - return code; -} - - - -static void -DoMyVolDump(Volume * vp, struct DiskPartition *dp, char *dumpfile) -{ - int code = 0; - int fromtime = 0; - int dumpAllDirs = 0; - int dumpfd = 0; - - if (dumpfile) { - unlink(dumpfile); - dumpfd = - open(dumpfile, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR); - if (dumpfd < 0) { - fprintf(stderr, "Failed to open dump file! Exiting.\n"); - exit(1); - } - } else { - dumpfd = 1; /* stdout */ - } - - if (verbose) - fprintf(stderr, "about to dump the dump header\n"); - if (!code) - code = DumpDumpHeader(dumpfd, vp, fromtime); - - if (verbose) - fprintf(stderr, "about to dump volume contents\n"); - if (!code) - code = DumpPartial(dumpfd, vp, fromtime, dumpAllDirs); - - if (verbose) - fprintf(stderr, "about to dump the dump postamble\n"); - if (!code) - code = DumpEnd(dumpfd); - - if (verbose) - fprintf(stderr, "finished dump\n"); - close(dumpfd); /* might be closing stdout, no harm */ -} diff --git a/src/volser/Makefile.in b/src/volser/Makefile.in index f5d6db9..44bc734 100644 --- a/src/volser/Makefile.in +++ b/src/volser/Makefile.in @@ -39,11 +39,22 @@ LIBS=\ ${TOP_LIBDIR}/libusd.a \ ${TOP_LIBDIR}/util.a +VOLDUMP_LIBS = \ + ../vol/ihandle.o \ + ../vol/physio.o \ + ../vol/vlib.a \ + ${TOP_LIBDIR}/libcmd.a \ + ${TOP_LIBDIR}/util.a \ + ${TOP_LIBDIR}/libsys.a \ + ${TOP_LIBDIR}/libdir.a \ + ${TOP_LIBDIR}/liblwp.a \ + ${TOP_LIBDIR}/libacl.a + VSOBJS=vsprocs.o vsutils.o lockprocs.o volint.xdr.o volerr.o SOBJS=volmain.o volprocs.o physio.o common.o voltrans.o volerr.o \ volint.cs.o dumpstuff.o volint.ss.o volint.xdr.o -all: volserver vos restorevol \ +all: volserver vos restorevol voldump \ ${TOP_INCDIR}/afs/volser.h \ ${TOP_INCDIR}/afs/volint.h \ ${TOP_LIBDIR}/libvolser.a @@ -59,6 +70,9 @@ volserver: $(SOBJS) $(LIBS) ${TOP_LIBDIR}/libdir.a ${CC} ${DBUG} -o volserver $(SOBJS) ${TOP_LIBDIR}/libdir.a \ ${LDFLAGS} $(LIBS) ${XLIBS} +voldump: vol-dump.o ${VOLDUMP_LIBS} + ${CC} ${CFLAGS} -o voldump vol-dump.o ${VOLDUMP_LIBS} ${XLIBS} + libvolser.a: volint.cs.o $(VSOBJS) volint.ss.o AFS_component_version_number.o -$(RM) -f $@ $(AR) crv $@ volint.cs.o $(VSOBJS) volint.ss.o AFS_component_version_number.o @@ -106,6 +120,7 @@ lockprocs.o: lockprocs.c ${VINCLS} ${INTINCLS} ${RINCLS} # install: \ ${DESTDIR}${sbindir}/restorevol \ + ${DESTDIR}${sbindir}/voldump \ ${DESTDIR}${includedir}/afs/volser.h \ ${DESTDIR}${includedir}/afs/volint.h \ ${DESTDIR}${sbindir}/vos \ @@ -123,6 +138,9 @@ ${DEST}/include/afs/volint.h: volint.h ${DEST}/etc/restorevol: restorevol ${INSTALL} $? $@ +${DEST}/etc/voldump: voldump + ${INSTALL} $? $@ + ${DEST}/etc/vos ${DEST}/root.server/usr/afs/bin/vos: vos ${INSTALL} $? $@ @@ -137,13 +155,16 @@ ${DEST}/root.server/usr/afs/bin/volserver: volserver # clean: $(RM) -f *.o *.a core volserver volint.ss.c volint.cs.c volint.h \ - volint.xdr.c vos volser.h volerr.c AFS_component_version_number.c restorevol + volint.xdr.c vos volser.h volerr.c AFS_component_version_number.c restorevol voldump include ../config/Makefile.version ${DESTDIR}${sbindir}/restorevol: restorevol ${INSTALL} $? $@ +${DESTDIR}${sbindir}/voldump: voldump + ${INSTALL} $? $@ + ${DESTDIR}${includedir}/afs/volser.h: volser.h ${INSTALL} $? $@ @@ -173,6 +194,7 @@ ${TOP_LIBDIR}/libvolser.a: libvolser.a dest: \ ${DEST}/etc/restorevol \ + ${DEST}/etc/voldump \ ${DEST}/include/afs/volser.h \ ${DEST}/include/afs/volint.h \ ${DEST}/etc/vos \ diff --git a/src/volser/vol-dump.c b/src/volser/vol-dump.c new file mode 100644 index 0000000..39a1edd --- /dev/null +++ b/src/volser/vol-dump.c @@ -0,0 +1,871 @@ +/* + * Copyright 2000, International Business Machines Corporation and others. + * All Rights Reserved. + * + * This software has been released under the terms of the IBM Public + * License. For details, see the LICENSE file in the top-level source + * directory or online at http://www.openafs.org/dl/license10.html + */ + +/* + System: VICE-TWO + Module: vol-dump.c + Institution: The Information Technology Center, Carnegie-Mellon University + + */ + +#include +#include + +RCSID + ("$Header$"); + +#include +#include +#include +#include +#include +#ifdef AFS_NT40_ENV +#include +#include +#include +#else +#include +#include +#include +#endif +#include + +#include +#include +#include "nfs.h" +#include +#include "lock.h" +#include "lwp.h" +#include +#include "ihandle.h" +#include "vnode.h" +#include "volume.h" +#include "partition.h" +#include "viceinode.h" +#include +#include "acl.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef HAVE_FCNTL_H +#include +#endif + +#ifdef _AIX +#include +#endif + +#include + +#include "volser/volser.h" +#include "volser/volint.h" +#include "volser/dump.h" + +#define putint32(p, v) *p++ = v>>24, *p++ = v>>16, *p++ = v>>8, *p++ = v +#define putshort(p, v) *p++ = v>>8, *p++ = v + +#ifdef O_LARGEFILE +#define afs_stat stat64 +#define afs_fstat fstat64 +#define afs_open open64 +#else /* !O_LARGEFILE */ +#define afs_stat stat +#define afs_fstat fstat +#define afs_open open +#endif /* !O_LARGEFILE */ + +int VolumeChanged; /* needed by physio - leave alone */ +int verbose = 0; + +/* Forward Declarations */ +void HandleVolume(struct DiskPartition *partP, char *name, char *filename); +Volume *AttachVolume(struct DiskPartition *dp, char *volname, + register struct VolumeHeader *header); +static void DoMyVolDump(Volume * vp, struct DiskPartition *dp, + char *dumpfile); + +#ifndef AFS_NT40_ENV +#include "AFS_component_version_number.c" +#endif + +char name[VMAXPATHLEN]; + + +int +ReadHdr1(IHandle_t * ih, char *to, int size, u_int magic, u_int version) +{ + int bad = 0; + int code; + + code = IH_IREAD(ih, 0, to, size); + if (code != size) + return -1; + + return 0; +} + + +Volume * +AttachVolume(struct DiskPartition * dp, char *volname, + register struct VolumeHeader * header) +{ + register Volume *vp; + afs_int32 ec = 0; + + vp = (Volume *) calloc(1, sizeof(Volume)); + vp->specialStatus = 0; + vp->device = dp->device; + vp->partition = dp; + IH_INIT(vp->vnodeIndex[vLarge].handle, dp->device, header->parent, + header->largeVnodeIndex); + IH_INIT(vp->vnodeIndex[vSmall].handle, dp->device, header->parent, + header->smallVnodeIndex); + IH_INIT(vp->diskDataHandle, dp->device, header->parent, + header->volumeInfo); + IH_INIT(V_linkHandle(vp), dp->device, header->parent, header->linkTable); + vp->cacheCheck = 0; /* XXXX */ + vp->shuttingDown = 0; + vp->goingOffline = 0; + vp->nUsers = 1; + vp->header = (struct volHeader *)calloc(1, sizeof(*vp->header)); + ec = ReadHdr1(V_diskDataHandle(vp), (char *)&V_disk(vp), + sizeof(V_disk(vp)), VOLUMEINFOMAGIC, VOLUMEINFOVERSION); + if (!ec) { + struct IndexFileHeader iHead; + ec = ReadHdr1(vp->vnodeIndex[vSmall].handle, (char *)&iHead, + sizeof(iHead), SMALLINDEXMAGIC, SMALLINDEXVERSION); + } + if (!ec) { + struct IndexFileHeader iHead; + ec = ReadHdr1(vp->vnodeIndex[vLarge].handle, (char *)&iHead, + sizeof(iHead), LARGEINDEXMAGIC, LARGEINDEXVERSION); + } +#ifdef AFS_NAMEI_ENV + if (!ec) { + struct versionStamp stamp; + ec = ReadHdr1(V_linkHandle(vp), (char *)&stamp, sizeof(stamp), + LINKTABLEMAGIC, LINKTABLEVERSION); + } +#endif + if (ec) + return (Volume *) 0; + return vp; +} + + +static int +handleit(struct cmd_syndesc *as, char *arock) +{ + register struct cmd_item *ti; + int err = 0; + int volumeId = 0; + char *partName = 0; + char *fileName = NULL; + struct DiskPartition *partP = NULL; + char name1[128]; + char tmpPartName[20]; + + +#ifndef AFS_NT40_ENV +#if 0 + if (geteuid() != 0) { + fprintf(stderr, "voldump must be run as root; sorry\n"); + exit(1); + } +#endif +#endif + + if ((ti = as->parms[0].items)) + partName = ti->data; + if ((ti = as->parms[1].items)) + volumeId = atoi(ti->data); + if ((ti = as->parms[2].items)) + fileName = ti->data; + if ((ti = as->parms[3].items)) + verbose = 1; + + DInit(10); + + err = VAttachPartitions(); + if (err) { + fprintf(stderr, "%d partitions had errors during attach.\n", err); + } + + if (partName) { + if (strlen(partName) == 1) { + if (partName[0] >= 'a' && partName[0] <= 'z') { + strcpy(tmpPartName, "/vicepa"); + tmpPartName[6] = partName[0]; + partP = VGetPartition(tmpPartName, 0); + } + } else { + partP = VGetPartition(partName, 0); + } + if (!partP) { + fprintf(stderr, + "%s is not an AFS partition name on this server.\n", + partName); + exit(1); + } + } + + if (!volumeId) { + fprintf(stderr, "Must specify volume id!\n"); + exit(1); + } + + if (!partP) { + fprintf(stderr, "must specify vice partition.\n"); + exit(1); + } + + (void)afs_snprintf(name1, sizeof name1, VFORMAT, (unsigned long)volumeId); + HandleVolume(partP, name1, fileName); + return 0; +} + +void +HandleVolume(struct DiskPartition *dp, char *name, char *filename) +{ + struct VolumeHeader header; + struct VolumeDiskHeader diskHeader; + struct afs_stat status, stat; + register int fd; + Volume *vp; + IHandle_t *ih; + char headerName[1024]; + + afs_int32 n; + + (void)afs_snprintf(headerName, sizeof headerName, "%s/%s", + VPartitionPath(dp), name); + if ((fd = afs_open(headerName, O_RDONLY)) == -1 + || afs_fstat(fd, &status) == -1) { + fprintf(stderr, "Cannot read volume header %s\n", name); + close(fd); + exit(1); + } + n = read(fd, &diskHeader, sizeof(diskHeader)); + + if (n != sizeof(diskHeader) + || diskHeader.stamp.magic != VOLUMEHEADERMAGIC) { + fprintf(stderr, "Error reading volume header %s\n", name); + exit(1); + } + if (diskHeader.stamp.version != VOLUMEHEADERVERSION) { + fprintf(stderr, + "Volume %s, version number is incorrect; volume needs salvage\n", + name); + exit(1); + } + DiskToVolumeHeader(&header, &diskHeader); + + close(fd); + vp = AttachVolume(dp, name, &header); + if (!vp) { + fprintf(stderr, "Error attaching volume header %s\n", name); + exit(1); + } + + DoMyVolDump(vp, dp, filename); +} + + +int +main(int argc, char **argv) +{ + register struct cmd_syndesc *ts; + afs_int32 code; + + VInitVolumePackage(volumeUtility, 5, 5, DONT_CONNECT_FS, 0); + + ts = cmd_CreateSyntax(NULL, handleit, 0, + "Dump a volume to a 'vos dump' format file without using volserver"); + cmd_AddParm(ts, "-part", CMD_LIST, CMD_OPTIONAL, "AFS partition name"); + cmd_AddParm(ts, "-volumeid", CMD_LIST, CMD_OPTIONAL, "Volume id"); + cmd_AddParm(ts, "-file", CMD_LIST, CMD_OPTIONAL, "Dump filename"); + cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, + "Trace dump progress (very verbose)"); + code = cmd_Dispatch(argc, argv); + return code; +} + + + + +static int +DumpDouble(int dumpfd, char tag, register afs_uint32 value1, + register afs_uint32 value2) +{ + int res; + char tbuffer[9]; + register byte *p = (unsigned char *)tbuffer; + *p++ = tag; + putint32(p, value1); + putint32(p, value2); + + res = write(dumpfd, tbuffer, 9); + return ((res == 9) ? 0 : VOLSERDUMPERROR); +} + +static int +DumpInt32(int dumpfd, char tag, register afs_uint32 value) +{ + char tbuffer[5]; + register byte *p = (unsigned char *)tbuffer; + *p++ = tag; + putint32(p, value); + return ((write(dumpfd, tbuffer, 5) == 5) ? 0 : VOLSERDUMPERROR); +} + +static int +DumpString(int dumpfd, char tag, register char *s) +{ + register int n; + int code = 0; + code = write(dumpfd, &tag, 1); + if (code != 1) + return VOLSERDUMPERROR; + n = strlen(s) + 1; + code = write(dumpfd, s, n); + if (code != n) + return VOLSERDUMPERROR; + return 0; +} + + +static int +DumpArrayInt32(int dumpfd, char tag, register afs_uint32 * array, + register int nelem) +{ + char tbuffer[4]; + register afs_uint32 v; + int code = 0; + register byte *p = (unsigned char *)tbuffer; + *p++ = tag; + putshort(p, nelem); + code = write(dumpfd, tbuffer, 3); + if (code != 3) + return VOLSERDUMPERROR; + while (nelem--) { + p = (unsigned char *)tbuffer; + v = *array++; /*this was register */ + + putint32(p, v); + code = write(dumpfd, tbuffer, 4); + if (code != 4) + return VOLSERDUMPERROR; + } + return 0; +} + + + + +static int +DumpDumpHeader(int dumpfd, register Volume * vp, afs_int32 fromtime) +{ + int code = 0; + afs_int32 dumpTimes[2]; + + if (verbose) + fprintf(stderr, "dumping dump header\n"); + + if (!code) + code = DumpDouble(dumpfd, D_DUMPHEADER, DUMPBEGINMAGIC, DUMPVERSION); + + if (!code) + code = DumpInt32(dumpfd, 'v', V_id(vp)); + + if (!code) + code = DumpString(dumpfd, 'n', V_name(vp)); + + dumpTimes[0] = fromtime; + dumpTimes[1] = V_backupDate(vp); /* Until the time the clone was made */ + if (!code) + code = DumpArrayInt32(dumpfd, 't', (afs_uint32 *) dumpTimes, 2); + + return code; +} + + +static int +DumpEnd(int dumpfd) +{ + return (DumpInt32(dumpfd, D_DUMPEND, DUMPENDMAGIC)); +} + +static int +DumpByte(int dumpfd, char tag, byte value) +{ + char tbuffer[2]; + register byte *p = (unsigned char *)tbuffer; + *p++ = tag; + *p = value; + return ((write(dumpfd, tbuffer, 2) == 2) ? 0 : VOLSERDUMPERROR); +} + +static int +DumpTag(int dumpfd, register int tag) +{ + char p; + + p = tag; + return ((write(dumpfd, &p, 1) == 1) ? 0 : VOLSERDUMPERROR); + +} + +static int +DumpBool(int dumpfd, char tag, unsigned int value) +{ + char tbuffer[2]; + register byte *p = (unsigned char *)tbuffer; + *p++ = tag; + *p = value; + return ((write(dumpfd, tbuffer, 2) == 2) ? 0 : VOLSERDUMPERROR); +} + + + +static int +DumpVolumeHeader(int dumpfd, register Volume * vp) +{ + int code = 0; + + if (verbose) + fprintf(stderr, "dumping volume header\n"); + + if (!code) + code = DumpTag(dumpfd, D_VOLUMEHEADER); + if (!code) + code = DumpInt32(dumpfd, 'i', V_id(vp)); + if (!code) + code = DumpInt32(dumpfd, 'v', V_stamp(vp).version); + if (!code) + code = DumpString(dumpfd, 'n', V_name(vp)); + if (!code) + code = DumpBool(dumpfd, 's', V_inService(vp)); + if (!code) + code = DumpBool(dumpfd, 'b', V_blessed(vp)); + if (!code) + code = DumpInt32(dumpfd, 'u', V_uniquifier(vp)); + if (!code) + code = DumpByte(dumpfd, 't', (byte) V_type(vp)); + if (!code) + code = DumpInt32(dumpfd, 'p', V_parentId(vp)); + if (!code) + code = DumpInt32(dumpfd, 'c', V_cloneId(vp)); + if (!code) + code = DumpInt32(dumpfd, 'q', V_maxquota(vp)); + if (!code) + code = DumpInt32(dumpfd, 'm', V_minquota(vp)); + if (!code) + code = DumpInt32(dumpfd, 'd', V_diskused(vp)); + if (!code) + code = DumpInt32(dumpfd, 'f', V_filecount(vp)); + if (!code) + code = DumpInt32(dumpfd, 'a', V_accountNumber(vp)); + if (!code) + code = DumpInt32(dumpfd, 'o', V_owner(vp)); + if (!code) + code = DumpInt32(dumpfd, 'C', V_creationDate(vp)); /* Rw volume creation date */ + if (!code) + code = DumpInt32(dumpfd, 'A', V_accessDate(vp)); + if (!code) + code = DumpInt32(dumpfd, 'U', V_updateDate(vp)); + if (!code) + code = DumpInt32(dumpfd, 'E', V_expirationDate(vp)); + if (!code) + code = DumpInt32(dumpfd, 'B', V_backupDate(vp)); /* Rw volume backup clone date */ + if (!code) + code = DumpString(dumpfd, 'O', V_offlineMessage(vp)); + + /* + * We do NOT dump the detailed volume statistics residing in the old + * motd field, since we cannot tell from the info in a dump whether + * statistics data has been put there. Instead, we dump a null string, + * just as if that was what the motd contained. + */ + if (!code) + code = DumpString(dumpfd, 'M', ""); + if (!code) + code = + DumpArrayInt32(dumpfd, 'W', (afs_uint32 *) V_weekUse(vp), + sizeof(V_weekUse(vp)) / sizeof(V_weekUse(vp)[0])); + if (!code) + code = DumpInt32(dumpfd, 'D', V_dayUseDate(vp)); + if (!code) + code = DumpInt32(dumpfd, 'Z', V_dayUse(vp)); + return code; +} + +static int +DumpShort(int dumpfd, char tag, unsigned int value) +{ + char tbuffer[3]; + register byte *p = (unsigned char *)tbuffer; + *p++ = tag; + *p++ = value >> 8; + *p = value; + return ((write(dumpfd, tbuffer, 3) == 3) ? 0 : VOLSERDUMPERROR); +} + +static int +DumpByteString(int dumpfd, char tag, register byte * bs, register int nbytes) +{ + int code = 0; + + code = write(dumpfd, &tag, 1); + if (code != 1) + return VOLSERDUMPERROR; + code = write(dumpfd, (char *)bs, nbytes); + if (code != nbytes) + return VOLSERDUMPERROR; + return 0; +} + + +static int +DumpFile(int dumpfd, int vnode, FdHandle_t * handleP, struct VnodeDiskObject *v) +{ + int code = 0, failed_seek = 0, failed_write = 0; + afs_int32 pad = 0, offset; + afs_sfsize_t n, nbytes, howMany, howBig; + byte *p; +#ifndef AFS_NT40_ENV + struct afs_stat status; +#endif + afs_sfsize_t size, tmpsize; +#ifdef AFS_AIX_ENV +#include + struct statfs tstatfs; +#endif + + if (verbose) + fprintf(stderr, "dumping file for vnode %d\n", vnode); + +#ifdef AFS_NT40_ENV + howBig = _filelength(handleP->fd_fd); + howMany = 4096; + +#else + afs_fstat(handleP->fd_fd, &status); + howBig = status.st_size; + +#ifdef AFS_AIX_ENV + /* Unfortunately in AIX valuable fields such as st_blksize are + * gone from the stat structure. + */ + fstatfs(handleP->fd_fd, &tstatfs); + howMany = tstatfs.f_bsize; +#else + howMany = status.st_blksize; +#endif /* AFS_AIX_ENV */ +#endif /* AFS_NT40_ENV */ + + + size = FDH_SIZE(handleP); + + if (verbose) + fprintf(stderr, " howBig = %u, howMany = %u, fdh size = %u\n", + howBig, howMany, size); + +#ifdef AFS_LARGEFILE_ENV + { + afs_uint32 hi, lo; + SplitInt64(size, hi, lo); + if (hi == 0L) { + code = DumpInt32(dumpfd, 'f', lo); + } else { + code = DumpDouble(dumpfd, 'h', hi, lo); + } + } +#else /* !AFS_LARGEFILE_ENV */ + code = DumpInt32(dumpfd, 'f', size); +#endif /* !AFS_LARGEFILE_ENV */ + if (code) { + return VOLSERDUMPERROR; + } + + p = (unsigned char *)malloc(howMany); + if (!p) { + fprintf(stderr, "out of memory!\n"); + return VOLSERDUMPERROR; + } + + /* loop through whole file, while we still have bytes left, and no errors, in chunks of howMany bytes */ + for (nbytes = size; (nbytes && !failed_write); nbytes -= howMany) { + if (nbytes < howMany) + howMany = nbytes; + + /* Read the data - unless we know we can't */ + n = (failed_seek ? 0 : FDH_READ(handleP, p, howMany)); + + /* If read any good data and we null padded previously, log the + * amount that we had null padded. + */ + if ((n > 0) && pad) { + fprintf(stderr, "Null padding file %d bytes at offset %u\n", pad, + offset); + pad = 0; + } + + /* If didn't read enough data, null padd the rest of the buffer. This + * can happen if, for instance, the media has some bad spots. We don't + * want to quit the dump, so we start null padding. + */ + if (n < howMany) { + + if (verbose) fprintf(stderr, " read %u instead of %u bytes.\n", n, howMany); + + /* Record the read error */ + if (n < 0) { + n = 0; + fprintf(stderr, "Error %d reading inode %s for vnode %d\n", + errno, PrintInode(NULL, handleP->fd_ih->ih_ino), + vnode); + } else if (!pad) { + fprintf(stderr, "Error reading inode %s for vnode %d\n", + PrintInode(NULL, handleP->fd_ih->ih_ino), vnode); + } + + /* Pad the rest of the buffer with zeros. Remember offset we started + * padding. Keep total tally of padding. + */ + memset(p + n, 0, howMany - n); + if (!pad) + offset = (howBig - nbytes) + n; + pad += (howMany - n); + + /* Now seek over the data we could not get. An error here means we + * can't do the next read. + */ + failed_seek = FDH_SEEK(handleP, ((size - nbytes) + howMany), SEEK_SET); + if (failed_seek != ((size - nbytes) + howMany)) { + if (failed_seek < 0) { + fprintf(stderr, + "Error %d seeking in inode %s for vnode %d\n", + errno, PrintInode(NULL, handleP->fd_ih->ih_ino), + vnode); + } else { + fprintf(stderr, + "Error seeking in inode %s for vnode %d\n", + PrintInode(NULL, handleP->fd_ih->ih_ino), vnode); + failed_seek = -1; + } + } else { + failed_seek = 0; + } + } + + /* Now write the data out */ + if (write(dumpfd, (char *)p, howMany) != howMany) + failed_write = VOLSERDUMPERROR; + } + + if (pad) { /* Any padding we hadn't reported yet */ + fprintf(stderr, "Null padding file: %d bytes at offset %u\n", pad, + offset); + } + + free(p); + return failed_write; +} + + +static int +DumpVnode(int dumpfd, struct VnodeDiskObject *v, int volid, int vnodeNumber, + int dumpEverything, struct Volume *vp) +{ + int code = 0; + IHandle_t *ihP; + FdHandle_t *fdP; + + if (verbose) + fprintf(stderr, "dumping vnode %d\n", vnodeNumber); + + if (!v || v->type == vNull) + return code; + if (!code) + code = DumpDouble(dumpfd, D_VNODE, vnodeNumber, v->uniquifier); + if (!dumpEverything) + return code; + if (!code) + code = DumpByte(dumpfd, 't', (byte) v->type); + if (!code) + code = DumpShort(dumpfd, 'l', v->linkCount); /* May not need this */ + if (!code) + code = DumpInt32(dumpfd, 'v', v->dataVersion); + if (!code) + code = DumpInt32(dumpfd, 'm', v->unixModifyTime); + if (!code) + code = DumpInt32(dumpfd, 'a', v->author); + if (!code) + code = DumpInt32(dumpfd, 'o', v->owner); + if (!code && v->group) + code = DumpInt32(dumpfd, 'g', v->group); /* default group is 0 */ + if (!code) + code = DumpShort(dumpfd, 'b', v->modeBits); + if (!code) + code = DumpInt32(dumpfd, 'p', v->parent); + if (!code) + code = DumpInt32(dumpfd, 's', v->serverModifyTime); + if (v->type == vDirectory) { + acl_HtonACL(VVnodeDiskACL(v)); + if (!code) + code = + DumpByteString(dumpfd, 'A', (byte *) VVnodeDiskACL(v), + VAclDiskSize(v)); + } + + if (VNDISK_GET_INO(v)) { + IH_INIT(ihP, V_device(vp), V_parentId(vp), VNDISK_GET_INO(v)); + fdP = IH_OPEN(ihP); + if (fdP == NULL) { + fprintf(stderr, + "Unable to open inode %s for vnode %u (volume %i); not dumped, error %d\n", + PrintInode(NULL, VNDISK_GET_INO(v)), vnodeNumber, volid, + errno); + } + else + { + if (verbose) + fprintf(stderr, "about to dump inode %s for vnode %u\n", + PrintInode(NULL, VNDISK_GET_INO(v)), vnodeNumber); + code = DumpFile(dumpfd, vnodeNumber, fdP, v); + FDH_CLOSE(fdP); + } + IH_RELEASE(ihP); + } + + if (verbose) + fprintf(stderr, "done dumping vnode %d\n", vnodeNumber); + return code; +} + + +static int +DumpVnodeIndex(int dumpfd, Volume * vp, VnodeClass class, afs_int32 fromtime, + int forcedump) +{ + register int code = 0; + register struct VnodeClassInfo *vcp = &VnodeClassInfo[class]; + char buf[SIZEOF_LARGEDISKVNODE]; + struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf; + StreamHandle_t *file; + FdHandle_t *fdP; + int size; + int flag; + int offset = 0; + register int vnodeIndex, nVnodes = 0; + + fdP = IH_OPEN(vp->vnodeIndex[class].handle); + file = FDH_FDOPEN(fdP, "r+"); + size = OS_SIZE(fdP->fd_fd); + nVnodes = (size / vcp->diskSize) - 1; + + if (nVnodes > 0) { + STREAM_SEEK(file, vcp->diskSize, 0); + } else + nVnodes = 0; + for (vnodeIndex = 0; + nVnodes && STREAM_READ(vnode, vcp->diskSize, 1, file) == 1 && !code; + nVnodes--, vnodeIndex++, offset += vcp->diskSize) { + flag = forcedump || (vnode->serverModifyTime >= fromtime); + /* Note: the >= test is very important since some old volumes may not have + * a serverModifyTime. For an epoch dump, this results in 0>=0 test, which + * does dump the file! */ + if (verbose) + fprintf(stderr, "about to dump %s vnode %u (vnode offset = %u)\n", + class == vSmall ? "vSmall" : "vLarge", + bitNumberToVnodeNumber(vnodeIndex, class), offset); + if (!code) + code = + DumpVnode(dumpfd, vnode, V_id(vp), + bitNumberToVnodeNumber(vnodeIndex, class), flag, + vp); + } + STREAM_CLOSE(file); + FDH_CLOSE(fdP); + return code; +} + + + +/* A partial dump (no dump header) */ +static int +DumpPartial(int dumpfd, register Volume * vp, afs_int32 fromtime, + int dumpAllDirs) +{ + int code = 0; + + if (verbose) + fprintf(stderr, "about to dump the volume header\n"); + if (!code) + code = DumpVolumeHeader(dumpfd, vp); + + if (verbose) + fprintf(stderr, "about to dump the large vnode index\n"); + if (!code) + code = DumpVnodeIndex(dumpfd, vp, vLarge, fromtime, dumpAllDirs); + + if (verbose) + fprintf(stderr, "about to dump the small vnode index\n"); + if (!code) + code = DumpVnodeIndex(dumpfd, vp, vSmall, fromtime, 0); + return code; +} + + + +static void +DoMyVolDump(Volume * vp, struct DiskPartition *dp, char *dumpfile) +{ + int code = 0; + int fromtime = 0; + int dumpAllDirs = 0; + int dumpfd = 0; + + if (dumpfile) { + unlink(dumpfile); + dumpfd = + open(dumpfile, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR); + if (dumpfd < 0) { + fprintf(stderr, "Failed to open dump file! Exiting.\n"); + exit(1); + } + } else { + dumpfd = 1; /* stdout */ + } + + if (verbose) + fprintf(stderr, "about to dump the dump header\n"); + if (!code) + code = DumpDumpHeader(dumpfd, vp, fromtime); + + if (verbose) + fprintf(stderr, "about to dump volume contents\n"); + if (!code) + code = DumpPartial(dumpfd, vp, fromtime, dumpAllDirs); + + if (verbose) + fprintf(stderr, "about to dump the dump postamble\n"); + if (!code) + code = DumpEnd(dumpfd); + + if (verbose) + fprintf(stderr, "finished dump\n"); + close(dumpfd); /* might be closing stdout, no harm */ +} -- 1.9.4