#include <roken.h>
#include <ctype.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <string.h>
-#ifdef AFS_NT40_ENV
-#include <fcntl.h>
-#include <time.h>
-#include <io.h>
-#else
-#include <sys/param.h>
-#include <sys/file.h>
-#include <sys/time.h>
-#endif
-#include <afs/cmd.h>
+#include <afs/cmd.h>
#include <rx/xdr.h>
+#include <rx/rx_queue.h>
#include <afs/afsint.h>
#include <afs/nfs.h>
#include <afs/errors.h>
#include <afs/dir.h>
#include <afs/com_err.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#ifdef _AIX
-#include <time.h>
-#endif
-
-#include <dirent.h>
-
#include "volser.h"
#include "volint.h"
#include "dump.h"
int VolumeChanged; /* needed by physio - leave alone */
int verbose = 0;
+static int enable_padding; /* Pad errors with NUL bytes */
/* Forward Declarations */
-void HandleVolume(struct DiskPartition64 *partP, char *name, char *filename, int fromtime);
-Volume *AttachVolume(struct DiskPartition64 *dp, char *volname,
- struct VolumeHeader *header);
+static void HandleVolume(struct DiskPartition64 *partP, char *name,
+ char *filename, int fromtime);
+static Volume *AttachVolume(struct DiskPartition64 *dp, char *volname,
+ struct VolumeHeader *header);
static void DoMyVolDump(Volume * vp, struct DiskPartition64 *dp,
char *dumpfile, int fromtime);
char name[VMAXPATHLEN];
-int
+static int
ReadHdr1(IHandle_t * ih, char *to, int size, u_int magic, u_int version)
{
int code;
}
-Volume *
+static Volume *
AttachVolume(struct DiskPartition64 * dp, char *volname,
struct VolumeHeader * header)
{
vp->shuttingDown = 0;
vp->goingOffline = 0;
vp->nUsers = 1;
- vp->header = (struct volHeader *)calloc(1, sizeof(*vp->header));
+ vp->header = calloc(1, sizeof(*vp->header));
ec = ReadHdr1(V_diskDataHandle(vp), (char *)&V_disk(vp),
sizeof(V_disk(vp)), VOLUMEINFOMAGIC, VOLUMEINFOVERSION);
if (!ec) {
afs_int32 code;
-#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))
return code;
}
}
+ if (as->parms[5].items != NULL) { /* -pad-errors */
+ enable_padding = 1;
+ }
DInit(10);
return 0;
}
-void
+static void
HandleVolume(struct DiskPartition64 *dp, char *name, char *filename, int fromtime)
{
struct VolumeHeader header;
}
DoMyVolDump(vp, dp, filename, fromtime);
+
+ free(vp);
}
"trying to continue anyway\n");
}
- ts = cmd_CreateSyntax(NULL, handleit, NULL,
+ ts = cmd_CreateSyntax(NULL, handleit, NULL, 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, "-verbose", CMD_FLAG, CMD_OPTIONAL,
"Trace dump progress (very verbose)");
cmd_AddParm(ts, "-time", CMD_SINGLE, CMD_OPTIONAL, "dump from time");
+ cmd_AddParm(ts, "-pad-errors", CMD_FLAG, CMD_OPTIONAL,
+ "pad i/o errors with NUL bytes");
code = cmd_Dispatch(argc, argv);
return code;
}
code = DumpString(dumpfd, 'n', V_name(vp));
dumpTimes[0] = fromtime;
- dumpTimes[1] = V_backupDate(vp); /* Until the time the clone was made */
+ switch (V_type(vp)) {
+ case readwriteVolume:
+ dumpTimes[1] = V_updateDate(vp); /* until last update */
+ break;
+ case readonlyVolume:
+ dumpTimes[1] = V_creationDate(vp); /* until clone was updated */
+ break;
+ case backupVolume:
+ /* until backup was made */
+ dumpTimes[1] = V_backupDate(vp) != 0 ? V_backupDate(vp) :
+ V_creationDate(vp);
+ break;
+ default:
+ code = EINVAL;
+ }
if (!code)
code = DumpArrayInt32(dumpfd, 't', (afs_uint32 *) dumpTimes, 2);
static int
DumpFile(int dumpfd, int vnode, FdHandle_t * handleP, struct VnodeDiskObject *v)
{
- int code = 0, failed_seek = 0, failed_write = 0;
+ int code = 0;
afs_int32 pad = 0;
afs_foff_t offset = 0;
afs_sfsize_t nbytes, howBig;
- ssize_t n;
+ ssize_t n = 0;
size_t howMany;
afs_foff_t howFar = 0;
byte *p;
afs_ino_str_t stmp;
#ifndef AFS_NT40_ENV
struct afs_stat status;
+#else
+ LARGE_INTEGER fileSize;
#endif
afs_sfsize_t size;
#ifdef AFS_AIX_ENV
fprintf(stderr, "dumping file for vnode %d\n", vnode);
#ifdef AFS_NT40_ENV
- howBig = _filelength(handleP->fd_fd);
+ if (!GetFileSizeEx(handleP->fd_fd, &fileSize)) {
+ Log("DumpFile: GetFileSizeEx returned error code %d on descriptor %d\n", GetLastError(), handleP->fd_fd);
+ return VOLSERDUMPERROR;
+ }
+ howBig = fileSize.QuadPart;
howMany = 4096;
#else
return VOLSERDUMPERROR;
}
- p = (unsigned char *)malloc(howMany);
+ p = 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) {
+ for (nbytes = size; (nbytes && !code); ) {
if (nbytes < howMany)
howMany = nbytes;
- /* Read the data - unless we know we can't */
- n = (failed_seek ? 0 : FDH_PREAD(handleP, p, howMany, howFar));
- howFar += n;
+ n = FDH_PREAD(handleP, p, howMany, howFar);
/* If read any good data and we null padded previously, log the
* amount that we had null padded.
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", (unsigned)n, (unsigned)howMany);
-
- /* Record the read error */
- if (n < 0) {
- n = 0;
- fprintf(stderr, "Error %d reading inode %s for vnode %d\n",
- errno, PrintInode(stmp, handleP->fd_ih->ih_ino),
- vnode);
- } else if (!pad) {
- fprintf(stderr, "Error reading inode %s for vnode %d\n",
+ if (n < 0) {
+ fprintf(stderr, "Error %d reading inode %s for vnode %d\n",
+ errno, PrintInode(stmp, handleP->fd_ih->ih_ino),
+ vnode);
+ code = VOLSERDUMPERROR;
+ }
+ if (n == 0) {
+ if (pad == 0) {
+ fprintf(stderr, "Unexpected EOF reading inode %s for vnode %d\n",
PrintInode(stmp, handleP->fd_ih->ih_ino), vnode);
}
+ code = VOLSERDUMPERROR;
+ }
- /* Pad the rest of the buffer with zeros. Remember offset we started
- * padding. Keep total tally of padding.
+ if (code != 0 && enable_padding) {
+ /*
+ * If our read failed, NUL-pad 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 NUL padding.
*/
- memset(p + n, 0, howMany - n);
+ memset(p, 0, howMany);
+
+ /* Remember the offset where we started padding, and keep a total
+ * tally of how much padding we've done. */
if (!pad)
- offset = (howBig - nbytes) + n;
- pad += (howMany - n);
+ offset = howFar;
+ pad += howMany;
- /* Now seek over the data we could not get. An error here means we
- * can't do the next read.
- */
- howFar = ((size - nbytes) + howMany);
+ /* Pretend we read 'howMany' bytes. */
+ n = howMany;
+ code = 0;
+ }
+ if (code != 0) {
+ break;
}
+ howFar += n;
+ nbytes -= n;
+
/* Now write the data out */
- if (write(dumpfd, (char *)p, howMany) != howMany)
- failed_write = VOLSERDUMPERROR;
+ if (write(dumpfd, (char *)p, n) != n)
+ code = VOLSERDUMPERROR;
}
if (pad) { /* Any padding we hadn't reported yet */
}
free(p);
- return failed_write;
+ return code;
}
static int
-DumpVnode(int dumpfd, struct VnodeDiskObject *v, int volid, int vnodeNumber,
+DumpVnode(int dumpfd, struct VnodeDiskObject *v, VolumeId volid, int vnodeNumber,
int dumpEverything, struct Volume *vp)
{
int code = 0;
if (!code)
code = DumpInt32(dumpfd, 's', v->serverModifyTime);
if (v->type == vDirectory) {
- acl_HtonACL(VVnodeDiskACL(v));
+ code = acl_HtonACL(VVnodeDiskACL(v));
+ if (code) {
+ fprintf(stderr, "Skipping invalid acl in vnode %u (volume %"AFS_VOLID_FMT")\n",
+ vnodeNumber, afs_printable_VolumeId_lu(volid));
+ }
if (!code)
code =
DumpByteString(dumpfd, 'A', (byte *) VVnodeDiskACL(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(stmp, VNDISK_GET_INO(v)), vnodeNumber, volid,
- errno);
+ "Unable to open inode %s for vnode %u "
+ "(volume %"AFS_VOLID_FMT"); not dumped, error %d\n",
+ PrintInode(stmp, VNDISK_GET_INO(v)), vnodeNumber,
+ afs_printable_VolumeId_lu(volid), errno);
}
else
{
fdP = IH_OPEN(vp->vnodeIndex[class].handle);
file = FDH_FDOPEN(fdP, "r+");
- size = OS_SIZE(fdP->fd_fd);
+ size = FDH_SIZE(fdP);
nVnodes = (size / vcp->diskSize) - 1;
if (nVnodes > 0) {