upstream dumpscan changes

pull in code changes from upstream for dumpscan

Change-Id: Ib1bcba7a420d19c1bf27b2a5405aaee786e6cbd6
Reviewed-on: http://gerrit.openafs.org/1873
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>
This commit is contained in:
Derrick Brashear 2010-04-28 02:02:05 -04:00
parent d02f9a0b0b
commit 7f399f2cac
3 changed files with 454 additions and 323 deletions

View File

@ -2,7 +2,7 @@
* CMUCS AFStools
* dumpscan - routines for scanning and manipulating AFS volume dumps
*
* Copyright (c) 1998 Carnegie Mellon University
* Copyright (c) 1998, 2001, 2004 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
@ -26,11 +26,13 @@
* the rights to redistribute these changes.
*/
/* directory.c - Parse an AFS directory */
/* directory.c - AFS directory parsing and generation */
/* See the end of this file for a description of the directory format */
#include <errno.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include "dumpscan.h"
@ -41,140 +43,151 @@
#include <afs/dir.h>
struct dir_state {
unsigned char **dirpages;
int npages;
afs_dir_header *dh; /* Directory header */
afs_dir_page *page; /* Current page */
int pageno; /* Current page # */
int entno; /* Current (next avail) entry # */
int used; /* # entries used in this page */
};
static afs_dir_page page;
#define allocbit(x) (page.header.freebitmap[(x)>>3] & (1 << ((x) & 7)))
#define DPHE (DHE + 1)
#if 0
static void
fixup(char *name, int l)
{
name += 16;
l -= 15;
#define bmbyte(bm,x) bm[(x)>>3]
#define bmbit(x) (1 << ((x) & 7))
while (l-- > 0) {
name[0] = name[4];
name++;
}
#define allocbit(x) (bmbyte(page.header.freebitmap,x) & bmbit(x))
#define setallocbit(bm,x) (bmbyte(bm,x) |= bmbit(x))
#define DPHE (DHE + 1)
/* Hash function used in AFS directories. */
static int namehash(char *name, int buckets, int seed)
{
int hval = seed, tval;
while (*name) hval = (hval * 173) + *name++;
tval = hval & (buckets - 1);
return tval ? hval < 0 ? buckets - tval : tval : 0;
}
#if 0
static void fixup(char *name, int l)
{
name += 16;
l -= 15;
while (l-- > 0) {
name[0] = name[4];
name++;
}
}
#endif
afs_uint32
parse_directory(XFILE * X, dump_parser * p, afs_vnode * v, afs_uint32 size,
int toeof)
{
afs_dir_entry de;
int pgno, i, l, n;
afs_int32 r;
u_int64 where;
if (p->print_flags & DSPRINT_DIR) {
printf(" VNode Uniqifier Name\n");
printf(" ========== ========== ==============================\n");
afs_uint32 parse_directory(XFILE *X, dump_parser *p, afs_vnode *v,
afs_uint32 size, int toeof)
{
afs_dir_entry de;
int pgno, i, l, n;
afs_int32 r;
u_int64 where;
if (p->print_flags & DSPRINT_DIR) {
printf(" VNode Uniqifier Name\n");
printf(" ========== ========== ==============================\n");
}
if ((p->flags & DSFLAG_SEEK) && (r = xftell(X, &where))) return r;
for (pgno = 0; toeof || size; pgno++, size -= (toeof ? 0 : AFS_PAGESIZE)) {
if ((p->flags & DSFLAG_SEEK) && (r = xfseek(X, &where))) return r;
if ((r = xfread(X, &page, AFS_PAGESIZE))) {
if (toeof && r == ERROR_XFILE_EOF) break;
return r;
}
if ((p->flags & DSFLAG_SEEK) && (r = xftell(X, &where)))
return r;
for (pgno = 0; toeof || size; pgno++, size -= (toeof ? 0 : AFS_PAGESIZE)) {
if ((p->flags & DSFLAG_SEEK) && (r = xfseek(X, &where)))
return r;
if ((r = xfread(X, &page, AFS_PAGESIZE))) {
if (toeof && (r == ERROR_XFILE_EOF))
break;
return r;
}
if ((p->flags & DSFLAG_SEEK) && (r = xftell(X, &where)))
return r;
if (page.header.tag != htons(1234)) {
if (p->cb_error)
(p->cb_error) (DSERR_MAGIC, 1, p->err_refcon,
"Invalid page tag (%d) in page %d",
ntohs(page.header.tag), pgno);
return DSERR_MAGIC;
}
for (i = (pgno ? 1 : DPHE); i < EPP; i++) {
if (!allocbit(i))
continue;
if (page.entry[i].flag != FFIRST) {
if (p->cb_error)
(p->cb_error) (DSERR_MAGIC, 0, p->err_refcon,
"Invalid entry flag %d in entry %d/%d; skipping...",
page.entry[i].flag, pgno, i);
continue;
}
n = (EPP - i - 1) * 32 + 16;
for (l = 0; n && page.entry[i].name[l]; l++, n--);
if (page.entry[i].name[l]) {
if (p->cb_error)
(p->cb_error) (DSERR_FMT, 0, p->err_refcon,
"Filename too long in entry %d/%d; skipping page",
pgno, i);
break;
}
if ((p->flags & DSFLAG_SEEK) && (r = xftell(X, &where))) return r;
if (page.header.tag != htons(1234)) {
if (p->cb_error)
(p->cb_error)(DSERR_MAGIC, 1, p->err_refcon,
"Invalid page tag (%d) in page %d",
ntohs(page.header.tag), pgno);
return DSERR_MAGIC;
}
for (i = (pgno ? 1 : DPHE); i < EPP; i++) {
if (!allocbit(i)) continue;
if (page.entry[i].flag != FFIRST) {
if (p->cb_error)
(p->cb_error)(DSERR_MAGIC, 0, p->err_refcon,
"Invalid entry flag %d in entry %d/%d; skipping...",
page.entry[i].flag, pgno, i);
continue;
}
n = (EPP - i - 1) * 32 + 16;
for (l = 0; n && page.entry[i].name[l]; l++, n--);
if (page.entry[i].name[l]) {
if (p->cb_error)
(p->cb_error)(DSERR_FMT, 0, p->err_refcon,
"Filename too long in entry %d/%d; skipping page",
pgno, i);
break;
}
/* fixup(page.entry[i].name, l); */
if (pgno)
de.slot = i - 1 + (pgno - 1) * (EPP - 1) + (EPP - DPHE);
else
de.slot = i - DPHE;
de.name = page.entry[i].name;
de.vnode = ntohl(page.entry[i].vnode);
de.uniq = ntohl(page.entry[i].vunique);
if (p->print_flags & DSPRINT_DIR)
printf(" %10d %10d %s\n", de.vnode, de.uniq, de.name);
if (p->cb_dirent) {
r = (p->cb_dirent) (v, &de, X, p->refcon);
}
if (p->cb_dirent && (r = (p->cb_dirent) (v, &de, X, p->refcon)))
return r;
i += ((l + 16) >> 5);
}
if (pgno) de.slot = i - 1 + (pgno - 1) * (EPP - 1) + (EPP - DPHE);
else de.slot = i - DPHE;
de.name = page.entry[i].name;
de.vnode = ntohl(page.entry[i].vnode);
de.uniq = ntohl(page.entry[i].vunique);
if (p->print_flags & DSPRINT_DIR)
printf(" %10d %10d %s\n", de.vnode, de.uniq, de.name);
if (p->cb_dirent) {
r = (p->cb_dirent)(v, &de, X, p->refcon);
}
if (p->cb_dirent && (r = (p->cb_dirent)(v, &de, X, p->refcon)))
return r;
i += ((l + 16) >> 5);
}
if ((p->flags & DSFLAG_SEEK) && (r = xfseek(X, &where)))
return r;
return 0;
}
if ((p->flags & DSFLAG_SEEK) && (r = xfseek(X, &where))) return r;
return 0;
}
afs_uint32
ParseDirectory(XFILE * X, dump_parser * p, afs_uint32 size, int toeof)
afs_uint32 ParseDirectory(XFILE *X, dump_parser *p, afs_uint32 size, int toeof)
{
afs_uint32 r;
afs_uint32 r;
r = parse_directory(X, p, 0, size, toeof);
return r;
r = parse_directory(X, p, 0, size, toeof);
return r;
}
typedef struct {
char **name;
afs_uint32 *vnode;
afs_uint32 *vuniq;
char **name;
afs_uint32 *vnode;
afs_uint32 *vuniq;
} dirlookup_stat;
static afs_uint32
dirlookup_cb(afs_vnode * v, afs_dir_entry * de, XFILE * X, void *refcon)
static afs_uint32 dirlookup_cb(afs_vnode *v, afs_dir_entry *de,
XFILE *X, void *refcon)
{
dirlookup_stat *s = (dirlookup_stat *) refcon;
dirlookup_stat *s = (dirlookup_stat *)refcon;
if (s->name && s->name[0]) { /* Search by filename */
if (strcmp(de->name, s->name[0]))
return 0; /* Not it! */
if (s->vnode)
s->vnode[0] = de->vnode;
if (s->vuniq)
s->vuniq[0] = de->uniq;
} else if (s->vnode) { /* Search by vnode */
if (de->vnode != s->vnode[0])
return 0; /* Not it! */
if (s->name) {
s->name[0] = (char *)malloc(strlen(de->name) + 1);
if (!s->name[0])
return ENOMEM;
strcpy(s->name[0], de->name);
}
if (s->vuniq)
s->vuniq[0] = de->uniq;
if (s->name && s->name[0]) { /* Search by filename */
if (strcmp(de->name, s->name[0])) return 0; /* Not it! */
if (s->vnode) s->vnode[0] = de->vnode;
if (s->vuniq) s->vuniq[0] = de->uniq;
} else if (s->vnode) { /* Search by vnode */
if (de->vnode != s->vnode[0]) return 0; /* Not it! */
if (s->name) {
s->name[0] = (char *)malloc(strlen(de->name) + 1);
if (!s->name[0]) return ENOMEM;
strcpy(s->name[0], de->name);
}
return DSERR_DONE;
if (s->vuniq) s->vuniq[0] = de->uniq;
}
return DSERR_DONE;
}
@ -189,29 +202,131 @@ dirlookup_cb(afs_vnode * v, afs_dir_entry * de, XFILE * X, void *refcon)
* and size set to the length of the directory.
* Returns 0 on success, whether or not the entry is found.
*/
afs_uint32
DirectoryLookup(XFILE * X, dump_parser * p, afs_uint32 size, char **name,
afs_uint32 * vnode, afs_uint32 * vuniq)
afs_uint32 DirectoryLookup(XFILE *X, dump_parser *p, afs_uint32 size,
char **name, afs_uint32 *vnode, afs_uint32 *vuniq)
{
dump_parser my_p;
dirlookup_stat my_s;
afs_uint32 r;
dump_parser my_p;
dirlookup_stat my_s;
afs_uint32 r;
memset(&my_s, 0, sizeof(my_s));
my_s.name = name;
my_s.vnode = vnode;
my_s.vuniq = vuniq;
memset(&my_s, 0, sizeof(my_s));
my_s.name = name;
my_s.vnode = vnode;
my_s.vuniq = vuniq;
memset(&my_p, 0, sizeof(my_p));
my_p.refcon = (void *)&my_s;
my_p.err_refcon = p->err_refcon;
my_p.cb_error = p->cb_error;
my_p.cb_dirent = dirlookup_cb;
memset(&my_p, 0, sizeof(my_p));
my_p.refcon = (void *)&my_s;
my_p.err_refcon = p->err_refcon;
my_p.cb_error = p->cb_error;
my_p.cb_dirent = dirlookup_cb;
r = parse_directory(X, &my_p, 0, size, 0);
if (!r)
r = DSERR_DONE;
return handle_return(r, X, 0, p);
r = parse_directory(X, &my_p, 0, size, 0);
if (!r) r = DSERR_DONE;
return handle_return(r, X, 0, p);
}
static int allocpage(struct dir_state *ds, int reserve)
{
unsigned char **dirpages;
int i;
dirpages = malloc((ds->npages + 1) * sizeof(unsigned char *));
if (!dirpages) return ENOMEM;
if (ds->dirpages) {
memcpy(dirpages, ds->dirpages, ds->npages * sizeof(unsigned char *));
free(ds->dirpages);
}
ds->dirpages = dirpages;
ds->dirpages[ds->npages] = malloc(AFS_PAGESIZE);
if (!ds->dirpages[ds->npages]) return ENOMEM;
ds->pageno = ds->npages++;
ds->page = (afs_dir_page *)(ds->dirpages[ds->pageno]);
memset(ds->page, 0, AFS_PAGESIZE);
ds->page->header.tag = htons(AFS_DIR_MAGIC);
ds->entno = ds->used = reserve;
for (i = 0; i < reserve; i++)
setallocbit(ds->page->header.freebitmap, i);
return 0;
}
afs_uint32 Dir_Init(struct dir_state **dsp)
{
afs_uint32 r;
*dsp = malloc(sizeof(struct dir_state));
if (!*dsp) return ENOMEM;
memset(*dsp, 0, sizeof(struct dir_state));
if ((r = allocpage(*dsp, DPHE))) return r;
(*dsp)->dh = (afs_dir_header *)((*dsp)->page);
return 0;
}
afs_uint32 Dir_AddEntry(struct dir_state *ds, char *name,
afs_uint32 vnode, afs_uint32 unique)
{
afs_uint32 r;
int l = strlen(name) + 1;
int ne = l > 16 ? 1 + ((l - 16) / 32) + !!((l - 16) % 32) : 1;
int hash = namehash(name, NHASHENT, 0);
if (ne > EPP - 1) return ENAMETOOLONG;
if (ds->entno + ne > EPP) {
if (ds->pageno < 128) ds->dh->allomap[ds->pageno] = ds->used;
if ((r = allocpage(ds, 1))) return r;
}
ds->page->entry[ds->entno].flag = FFIRST;
ds->page->entry[ds->entno].next = ds->dh->hash[hash];
ds->page->entry[ds->entno].vnode = htonl(vnode);
ds->page->entry[ds->entno].vunique = htonl(unique);
strcpy(ds->page->entry[ds->entno].name, name);
ds->dh->hash[hash] = htons((ds->pageno * EPP) + ds->entno);
while (ne--) {
setallocbit(ds->page->header.freebitmap, ds->entno);
ds->used++;
ds->entno++;
}
return 0;
}
afs_uint32 Dir_Finalize(struct dir_state *ds)
{
int pages = ds->pageno + 1;
if (ds->pageno < 128) ds->dh->allomap[ds->pageno] = ds->used;
ds->dh->pagehdr.pgcount = htons(pages);
return 0;
}
afs_uint32 Dir_EmitData(struct dir_state *ds, XFILE *X, int dotag)
{
afs_uint32 r, size;
int i;
size = ds->npages * AFS_PAGESIZE;
if (dotag && (r = WriteTagInt32(X, VTAG_DATA, size))) return r;
for (i = 0; i < ds->npages; i++) {
if ((r = xfwrite(X, ds->dirpages[i], AFS_PAGESIZE))) return r;
}
return 0;
}
afs_uint32 Dir_Free(struct dir_state *ds)
{
int i;
for (i = 0; i < ds->npages; i++)
free(ds->dirpages[i]);
free(ds->dirpages);
free(ds);
return 0;
}

View File

@ -2,7 +2,7 @@
* CMUCS AFStools
* dumpscan - routines for scanning and manipulating AFS volume dumps
*
* Copyright (c) 1998 Carnegie Mellon University
* Copyright (c) 1998, 2001 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
@ -122,29 +122,38 @@
#define VTAG_DATA 'f'
#define AFS_DIR_EPP 64
#define AFS_DIR_MAGIC 1234
#define AFS_DIR_EPP 64
#define AFS_DIR_MAXPAGES 128
#define AFS_DIR_NHASH 128
typedef struct {
afs_uint16 pgcount;
afs_uint16 tag;
char freecount;
char freebitmap[AFS_DIR_EPP / 8];
char padding[32 - (5 + AFS_DIR_EPP / 8)];
afs_uint16 pgcount;
afs_uint16 tag;
char freecount;
char freebitmap[AFS_DIR_EPP/8];
char padding[32 - (5 + AFS_DIR_EPP/8)];
} afs_dir_pagehdr;
typedef struct {
char flag;
char length;
afs_uint16 next;
afs_uint32 vnode;
afs_uint32 vunique;
char name[16];
char padding[4];
afs_dir_pagehdr pagehdr;
char allomap[AFS_DIR_MAXPAGES];
afs_uint16 hash[AFS_DIR_NHASH];
} afs_dir_header;
typedef struct {
char flag;
char length;
afs_uint16 next;
afs_uint32 vnode;
afs_uint32 vunique;
char name[16];
char padding[4];
} afs_dir_direntry;
typedef union {
afs_dir_pagehdr header;
afs_dir_direntry entry[AFS_DIR_EPP];
afs_dir_pagehdr header;
afs_dir_direntry entry[AFS_DIR_EPP];
} afs_dir_page;
#endif /* _DUMPFMT_H_ */

View File

@ -2,7 +2,7 @@
* CMUCS AFStools
* dumpscan - routines for scanning and manipulating AFS volume dumps
*
* Copyright (c) 1998 Carnegie Mellon University
* Copyright (c) 1998, 2001, 2003 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
@ -39,21 +39,13 @@
#include <afs/nfs.h>
#include <afs/ihandle.h>
#include <afs/vnode.h>
#include <afs/cmd.h>
#include <afs/bnode.h>
#include <afs/cellconfig.h>
#include <afs/kautils.h>
#include <afs/pterror.h>
#include <afs/vlserver.h>
#include <afs/volser.h>
#include <ubik.h>
/* Random useful types */
typedef struct tagged_field tagged_field;
typedef struct tag_parse_info tag_parse_info;
typedef afs_uint32(*tag_parser) (XFILE *, unsigned char *, tagged_field *,
afs_uint32, tag_parse_info *, void *,
void *);
typedef afs_uint32 (*tag_parser)(XFILE *, unsigned char *, tagged_field *,
afs_uint32, tag_parse_info *, void *, void *);
typedef struct dir_state dir_state;
/* Error codes used within dumpscan.
* Any of the routines declared below, or callbacks used by them,
@ -77,20 +69,20 @@ typedef afs_uint32(*tag_parser) (XFILE *, unsigned char *, tagged_field *,
* functions should extract as much data as possible from the actual file
* to fill this in. */
typedef struct {
afs_uint32 version;
afs_uint32 from_date;
afs_uint32 to_date;
afs_uint32 dump_date;
afs_uint32 filenum;
unsigned char *server;
unsigned char *part;
unsigned char *volname;
afs_uint32 volid;
afs_uint32 dumplen;
afs_uint32 level;
afs_uint32 magic;
afs_uint32 cksum;
afs_uint32 flags;
afs_uint32 version;
afs_uint32 from_date;
afs_uint32 to_date;
afs_uint32 dump_date;
afs_uint32 filenum;
unsigned char *server;
unsigned char *part;
unsigned char *volname;
afs_uint32 volid;
u_int64 dumplen;
afs_uint32 level;
afs_uint32 magic;
afs_uint32 cksum;
afs_uint32 flags;
} backup_system_header;
@ -100,14 +92,14 @@ typedef struct {
#define F_DUMPHDR_FROM 0x00000004
#define F_DUMPHDR_TO 0x00000008
typedef struct {
u_int64 offset; /* Where in the file is it? */
afs_uint32 field_mask; /* What fields are present? */
afs_uint32 magic; /* Magic number */
afs_uint32 version; /* Dump format version */
afs_uint32 volid; /* VolID of volume in dump */
unsigned char *volname; /* Name of volume in dump */
afs_uint32 from_date; /* Reference date */
afs_uint32 to_date; /* Date of dump */
u_int64 offset; /* Where in the input stream is it? */
afs_uint32 field_mask; /* What fields are present? */
afs_uint32 magic; /* Magic number */
afs_uint32 version; /* Dump format version */
afs_uint32 volid; /* VolID of volume in dump */
unsigned char *volname; /* Name of volume in dump */
afs_uint32 from_date; /* Reference date */
afs_uint32 to_date; /* Date of dump */
} afs_dump_header;
@ -138,33 +130,33 @@ typedef struct {
#define F_VOLHDR_DAYUSE 0x00800000
#define F_VOLHDR_DAYUSE_DATE 0x01000000
typedef struct {
u_int64 offset; /* Where in the file is it? */
afs_uint32 field_mask; /* What fields are present? */
afs_uint32 volid; /* Volume ID */
afs_uint32 volvers; /* ?? */
unsigned char *volname; /* Volume Name */
int flag_inservice; /* Inservice flag (0 or not) */
int flag_blessed; /* Blessed to come online (0 or not) */
afs_uint32 voluniq; /* Volume uniquifier */
int voltype; /* Volume type */
afs_uint32 parent_volid; /* Parent volume ID */
afs_uint32 clone_volid; /* Clone volume ID */
afs_uint32 maxquota; /* Max quota */
afs_uint32 minquota; /* Min quota (obsolete) */
afs_uint32 diskused; /* Disk blocks used */
afs_uint32 nfiles; /* Number of files in volume */
afs_uint32 account_no; /* Account number (unused) */
afs_uint32 owner; /* Volume owner */
afs_uint32 create_date; /* Creation date of this copy */
afs_uint32 access_date; /* Last access */
afs_uint32 update_date; /* Last modification */
afs_uint32 expire_date; /* Expiration (unused) */
afs_uint32 backup_date; /* Last backup clone */
unsigned char *offline_msg; /* Offline message */
unsigned char *motd_msg; /* Volume MOTD */
afs_uint32 weekuse[7]; /* Weekuse data */
afs_uint32 dayuse; /* # accesses in last day */
afs_uint32 dayuse_date; /* Date for which dayuse is valid */
u_int64 offset; /* Where in the input stream is it? */
afs_uint32 field_mask; /* What fields are present? */
afs_uint32 volid; /* Volume ID */
afs_uint32 volvers; /* ?? */
unsigned char *volname; /* Volume Name */
int flag_inservice; /* Inservice flag (0 or not) */
int flag_blessed; /* Blessed to come online (0 or not) */
afs_uint32 voluniq; /* Volume uniquifier */
int voltype; /* Volume type */
afs_uint32 parent_volid; /* Parent volume ID */
afs_uint32 clone_volid; /* Clone volume ID */
afs_uint32 maxquota; /* Max quota */
afs_uint32 minquota; /* Min quota (obsolete) */
afs_uint32 diskused; /* Disk blocks used */
afs_uint32 nfiles; /* Number of files in volume */
afs_uint32 account_no; /* Account number (unused) */
afs_uint32 owner; /* Volume owner */
afs_uint32 create_date; /* Creation date of this copy */
afs_uint32 access_date; /* Last access */
afs_uint32 update_date; /* Last modification */
afs_uint32 expire_date; /* Expiration (unused) */
afs_uint32 backup_date; /* Last backup clone */
unsigned char *offline_msg; /* Offline message */
unsigned char *motd_msg; /* Volume MOTD */
afs_uint32 weekuse[7]; /* Weekuse data */
afs_uint32 dayuse; /* # accesses in last day */
afs_uint32 dayuse_date; /* Date for which dayuse is valid */
} afs_vol_header;
@ -179,146 +171,154 @@ typedef struct {
#define F_VNODE_MODE 0x00000080
#define F_VNODE_CDATE 0x00000100
#define F_VNODE_SDATE 0x00000200
#define F_VNODE_SIZE 0x00000800
#define F_VNODE_DATA 0x00001000
#define F_VNODE_ACL 0x00000400
#define F_VNODE_SIZE 0x00000800 /* Set if size is present */
#define F_VNODE_DATA 0x00001000 /* Set if size nonzero and data present */
#define F_VNODE_PARTIAL 0x00002000 /* Partial vnode continuation (no header) */
#define F_VNODE_LINK_TARGET 0x00004000 /* Symlink target present */
typedef struct {
u_int64 offset; /* Where in the file is it? */
afs_uint32 field_mask; /* What fields are present? */
afs_uint32 vnode; /* Vnode number */
afs_uint32 vuniq; /* Uniquifier */
int type; /* Vnode type */
afs_uint16 nlinks; /* Number of links (should be in 1 dir!) */
afs_uint32 parent; /* Parent vnode */
afs_uint32 datavers; /* Data version */
afs_uint32 author; /* Last writer */
afs_uint32 owner; /* Owner UID */
afs_uint32 group; /* Owning group */
afs_uint16 mode; /* UNIX mode bits */
afs_uint32 client_date; /* Last modified date from client */
afs_uint32 server_date; /* Last modified date on server */
afs_uint32 size; /* Size of data */
u_int64 d_offset; /* Where in the file is the data? */
unsigned char acl[SIZEOF_LARGEDISKVNODE - SIZEOF_SMALLDISKVNODE];
u_int64 offset; /* Where in the input stream is it? */
afs_uint32 field_mask; /* What fields are present? */
afs_uint32 vnode; /* Vnode number */
afs_uint32 vuniq; /* Uniquifier */
int type; /* Vnode type */
afs_uint16 nlinks; /* Number of links (should be in 1 dir!) */
afs_uint32 parent; /* Parent vnode */
afs_uint32 datavers; /* Data version */
afs_uint32 author; /* Last writer */
afs_uint32 owner; /* Owner UID */
afs_uint32 group; /* Owning group */
afs_uint16 mode; /* UNIX mode bits */
afs_uint32 client_date; /* Last modified date from client */
afs_uint32 server_date; /* Last modified date on server */
afs_uint32 size; /* Size of data */
u_int64 d_offset; /* Where in the input stream is the data? */
char *link_target; /* Target of symbolic link */
unsigned char acl[SIZEOF_LARGEDISKVNODE - SIZEOF_SMALLDISKVNODE];
} afs_vnode;
/** AFS directory entry **/
typedef struct {
int slot; /* Directory slot # (info only) */
char *name; /* Name of entry */
afs_uint32 vnode; /* Vnode number */
afs_uint32 uniq; /* Uniquifier */
int slot; /* Directory slot # (info only) */
char *name; /* Name of entry */
afs_uint32 vnode; /* Vnode number */
afs_uint32 uniq; /* Uniquifier */
} afs_dir_entry;
/** Tagged field definitions **/
#define DKIND_NOOP 0x00 /* No data */
#define DKIND_BYTE 0x10 /* 1 byte - decimal */
#define DKIND_HEX8 0x11 /* 1 byte - hex */
#define DKIND_CHAR 0x12 /* 1 byte - character */
#define DKIND_FLAG 0x13 /* 1 byte - true/false */
#define DKIND_INT16 0x20 /* 2 bytes - decimal */
#define DKIND_HEX16 0x21 /* 2 bytes - hex */
#define DKIND_INT32 0x30 /* 4 bytes - decimal */
#define DKIND_HEX32 0x31 /* 4 bytes - hex */
#define DKIND_TIME 0x32 /* 4 bytes - time */
#define DKIND_STRING 0x40 /* ASCIIZ string */
#define DKIND_SPECIAL 0x50 /* Custom parser */
#define DKIND_NOOP 0x00 /* No data */
#define DKIND_BYTE 0x10 /* 1 byte - decimal */
#define DKIND_HEX8 0x11 /* 1 byte - hex */
#define DKIND_CHAR 0x12 /* 1 byte - character */
#define DKIND_FLAG 0x13 /* 1 byte - true/false */
#define DKIND_INT16 0x20 /* 2 bytes - decimal */
#define DKIND_HEX16 0x21 /* 2 bytes - hex */
#define DKIND_OCT16 0x28 /* 2 bytes - octal */
#define DKIND_INT32 0x30 /* 4 bytes - decimal */
#define DKIND_HEX32 0x31 /* 4 bytes - hex */
#define DKIND_TIME 0x32 /* 4 bytes - time */
#define DKIND_OCT32 0x38 /* 4 bytes - octal */
#define DKIND_STRING 0x40 /* ASCIIZ string */
#define DKIND_SPECIAL 0x50 /* Custom parser */
#define DKIND_MASK (~0x0f)
struct tag_parse_info {
void *err_refcon;
afs_uint32(*cb_error) (afs_uint32, int, void *, char *, ...);
afs_uint32 flags;
void *err_refcon;
afs_uint32 (*cb_error)(afs_uint32, int, void *, char *, ...);
afs_uint32 flags;
#define TPFLAG_SKIP 0x0001
#define TPFLAG_RSKIP 0x0002
int shift_offset;
u_int64 shift_start;
int shift_offset;
u_int64 shift_start;
};
struct tagged_field {
char tag; /* Tag character */
int kind; /* Kind of object */
char *label; /* Label to use (for debugging) */
tag_parser func; /* Parser function (for DKIND_SPECIAL) */
void *refptr; /* Reference pointer (for parser's use) */
int refarg; /* Reference argument (for parser's use) */
char tag; /* Tag character */
int kind; /* Kind of object */
char *label; /* Label to use (for debugging) */
tag_parser func; /* Parser function (for DKIND_SPECIAL) */
void *refptr; /* Reference pointer (for parser's use) */
int refarg; /* Reference argument (for parser's use) */
};
/** Control structure for parsing volume dumps **/
typedef struct {
/* Callback functions:
* Whenever a "complex" object is parsed, we call a callback function.
* The callback gets a pointer to the complex object, the file pointer
* for the dump we're parsing, and the value of refcon in this structure.
* Callbacks should return 0 if all is well, non-0 to abort the dump.
* By convention, positive numbers should be errno values, and negative
* numbers can be used for other things. It is OK to _try_ to seek anywhere
* in the file. Beware, though, that the input is not always seekable.
* Also, note that the structures passed to these callbacks are going to
* go away after the callback returns. There is no way to prevent this;
* make a copy if you want one.
*/
void *refcon;
afs_uint32(*cb_bckhdr) (backup_system_header *, XFILE *, void *); /* Backup */
afs_uint32(*cb_dumphdr) (afs_dump_header *, XFILE *, void *); /* Dump hdr */
afs_uint32(*cb_volhdr) (afs_vol_header *, XFILE *, void *); /* Volume hdr */
afs_uint32(*cb_vnode_dir) (afs_vnode *, XFILE *, void *); /* Directory */
afs_uint32(*cb_vnode_file) (afs_vnode *, XFILE *, void *); /* File */
afs_uint32(*cb_vnode_link) (afs_vnode *, XFILE *, void *); /* Symlink */
afs_uint32(*cb_vnode_empty) (afs_vnode *, XFILE *, void *); /* vnode+uniq */
afs_uint32(*cb_vnode_wierd) (afs_vnode *, XFILE *, void *); /* Unknown type */
/* Callback functions:
* Whenever a "complex" object is parsed, we call a callback function.
* The callback gets a pointer to the complex object, the file pointer
* for the dump we're parsing, and the value of refcon in this structure.
* Callbacks should return 0 if all is well, non-0 to abort the dump.
* By convention, positive numbers should be errno values, and negative
* numbers can be used for other things. It is OK to _try_ to seek anywhere
* in the file. Beware, though, that the input is not always seekable.
* Also, note that the structures passed to these callbacks are going to
* go away after the callback returns. There is no way to prevent this;
* make a copy if you want one.
*/
void *refcon;
afs_uint32 (*cb_bckhdr)(backup_system_header *, XFILE *, void *); /* Backup Header */
afs_uint32 (*cb_dumphdr)(afs_dump_header *, XFILE *, void *); /* Dump Header */
afs_uint32 (*cb_volhdr)(afs_vol_header *, XFILE *, void *); /* Volume Header */
afs_uint32 (*cb_vnode_dir)(afs_vnode *, XFILE *, void *); /* Directory Vnode */
afs_uint32 (*cb_vnode_file)(afs_vnode *, XFILE *, void *); /* File Vnode */
afs_uint32 (*cb_vnode_link)(afs_vnode *, XFILE *, void *); /* Symlink Vnode */
afs_uint32 (*cb_vnode_empty)(afs_vnode *, XFILE *, void *); /* vnode+uniq only */
afs_uint32 (*cb_vnode_wierd)(afs_vnode *, XFILE *, void *); /* Unknown type */
afs_uint32 (*cb_file_data)(afs_vnode *, XFILE *, void *); /* File Data */
afs_uint32 (*cb_dir_data)(afs_vnode *, XFILE *, void *); /* Directory Data */
afs_uint32 (*cb_link_data)(afs_vnode *, XFILE *, void *); /* Symlink Data */
/* This function is called when there is an error in the dump. */
/* (cb_error)(errno, fatal, refcon, msg_fmt, msg_args...) */
void *err_refcon; /* If set, use instead of refcon for dir entries */
afs_uint32(*cb_error) (afs_uint32, int, void *, char *, ...);
/* This function is called when there is an error in the dump. */
/* (cb_error)(errno, fatal, refcon, msg_fmt, msg_args...) */
void *err_refcon; /* If set, use instead of refcon for dir entries */
afs_uint32 (*cb_error)(afs_uint32, int, void *, char *, ...);
/* This function is called for each directory entry, if set */
afs_uint32(*cb_dirent) (afs_vnode *, afs_dir_entry *, XFILE *, void *);
/* This function is called for each directory entry, if set */
afs_uint32 (*cb_dirent)(afs_vnode *, afs_dir_entry *, XFILE *, void *);
int flags; /* Flags and options */
#define DSFLAG_SEEK 0x0001 /* Input file is seekable */
int flags; /* Flags and options */
#define DSFLAG_SEEK 0x0001 /* Input file is seekable */
int print_flags; /* Flags to control what is printed */
#define DSPRINT_BCKHDR 0x0001 /* Print backup system header */
#define DSPRINT_DUMPHDR 0x0002 /* Print AFS dump header */
#define DSPRINT_VOLHDR 0x0004 /* Print AFS volume header */
#define DSPRINT_ITEM 0x0010 /* Print top-level tags */
#define DSPRINT_VNODE 0x0020 /* Print vnode attributes */
#define DSPRINT_ACL 0x0040 /* Print directory ACL's */
#define DSPRINT_DIR 0x0080 /* Print directory contents */
#define DSPRINT_DEBUG 0x0100 /* Print debugging info */
#define DSPRINT_PATH 0x0200 /* Print vnode paths */
int print_flags; /* Flags to control what is printed */
#define DSPRINT_BCKHDR 0x0001 /* Print backup system header */
#define DSPRINT_DUMPHDR 0x0002 /* Print AFS dump header */
#define DSPRINT_VOLHDR 0x0004 /* Print AFS volume header */
#define DSPRINT_ITEM 0x0010 /* Print top-level tags */
#define DSPRINT_VNODE 0x0020 /* Print vnode attributes */
#define DSPRINT_ACL 0x0040 /* Print directory ACL's */
#define DSPRINT_DIR 0x0080 /* Print directory contents */
#define DSPRINT_DEBUG 0x0100 /* Print debugging info */
#define DSPRINT_PATH 0x0200 /* Print vnode paths */
int repair_flags; /* Flags to control what is repaired.
* Most of these _require_ DSFLAG_SEEK */
#define DSFIX_SKIP 0x0001 /* Try to skip null tags */
#define DSFIX_RSKIP 0x0002 /* Seek back to fing skipped tags */
#define DSFIX_VDSYNC 0x0004 /* Resync location after vnode data */
#define DSFIX_VFSYNC 0x0008 /* Try to resync after bad vnode */
int repair_flags; /* Flags to control what is repaired.
* Most of these _require_ DSFLAG_SEEK */
#define DSFIX_SKIP 0x0001 /* Try to skip null tags */
#define DSFIX_RSKIP 0x0002 /* Seek back to fing skipped tags */
#define DSFIX_VDSYNC 0x0004 /* Resync location after vnode data */
#define DSFIX_VFSYNC 0x0008 /* Try to resync after bad vnode */
/** Things below this point for internal use only **/
afs_uint32 vol_uniquifier;
afs_uint32 vol_uniquifier;
} dump_parser;
/** Hash table and control info for pathname manipulation **/
typedef struct vhash_ent {
struct vhash_ent *next; /* Pointer to next entry */
afs_uint32 vnode; /* VNode number */
afs_uint32 parent; /* Parent VNode number */
u_int64 v_offset; /* Offset to start of vnode */
u_int64 d_offset; /* Offset to data (0 if none) */
afs_uint32 d_size; /* Size of data */
struct vhash_ent *next; /* Pointer to next entry */
afs_uint32 vnode; /* VNode number */
afs_uint32 parent; /* Parent VNode number */
u_int64 v_offset; /* Offset to start of vnode */
u_int64 d_offset; /* Offset to data (0 if none) */
afs_uint32 d_size; /* Size of data */
} vhash_ent;
typedef struct {
afs_uint32 n_vnodes; /* Number of vnodes in volume */
afs_uint32 n_dirs; /* Number of file vnodes */
afs_uint32 n_files; /* Number of directory vnodes */
int hash_size; /* Hash table size (bits) */
vhash_ent **hash_table; /* Hash table */
dump_parser *p; /* Dump parser to use */
afs_uint32 n_vnodes; /* Number of vnodes in volume */
afs_uint32 n_dirs; /* Number of file vnodes */
afs_uint32 n_files; /* Number of directory vnodes */
int hash_size; /* Hash table size (bits) */
vhash_ent **hash_table; /* Hash table */
dump_parser *p; /* Dump parser to use */
} path_hashinfo;
@ -338,17 +338,17 @@ extern afs_uint32 WriteString(XFILE *, unsigned char *);
extern afs_uint32 WriteTagByte(XFILE *, unsigned char, unsigned char);
extern afs_uint32 WriteTagInt16(XFILE *, unsigned char, afs_uint16);
extern afs_uint32 WriteTagInt32(XFILE *, unsigned char, afs_uint32);
extern afs_uint32 WriteTagInt32Pair(XFILE *, unsigned char, afs_uint32,
afs_uint32);
extern afs_uint32 WriteTagInt32Pair(XFILE *, unsigned char, afs_uint32, afs_uint32);
extern afs_uint32 WriteTagString(XFILE *, unsigned char, unsigned char *);
/* parsetag.c - Parse tagged data */
extern afs_uint32 ParseTaggedData(XFILE *, tagged_field *, unsigned char *,
tag_parse_info *, void *, void *);
tag_parse_info *, void *, void *);
/* stagehdr.c - Parse and dump Stage dump headers */
extern afs_uint32 ParseStageHdr(XFILE *, unsigned char *,
backup_system_header *);
extern afs_uint32 DumpStagehdr(XFILE *, backup_system_header *);
extern afs_uint32 ParseStageHdr(XFILE *, unsigned char *, backup_system_header *);
extern afs_uint32 ParseStageV20Hdr(XFILE *, unsigned char *, backup_system_header *);
extern afs_uint32 DumpStageV20Hdr(XFILE *, backup_system_header *);
/* backuphdr.c - Parse and print backup system headers */
extern void PrintBackupHdr(backup_system_header *);
@ -360,10 +360,16 @@ extern afs_uint32 ParseVolumeHeader(XFILE *, dump_parser *);
extern afs_uint32 ParseVNode(XFILE *, dump_parser *);
/* directory.c - Directory parsing and lookup */
/* directory.c - Directory parsing, lookup, and generation */
extern afs_uint32 ParseDirectory(XFILE *, dump_parser *, afs_uint32, int);
extern afs_uint32 DirectoryLookup(XFILE *, dump_parser *, afs_uint32, char **,
afs_uint32 *, afs_uint32 *);
extern afs_uint32 DirectoryLookup(XFILE *, dump_parser *, afs_uint32,
char **, afs_uint32 *, afs_uint32 *);
extern afs_uint32 Dir_Init(dir_state **);
extern afs_uint32 Dir_AddEntry(dir_state *, char *, afs_uint32, afs_uint32);
extern afs_uint32 Dir_Finalize(dir_state *);
extern afs_uint32 Dir_EmitData(dir_state *, XFILE *, int);
extern afs_uint32 Dir_Free(dir_state *ds);
/* dump.c - Dump parts of a volume dump */
extern afs_uint32 DumpDumpHeader(XFILE *, afs_dump_header *);
@ -371,12 +377,13 @@ extern afs_uint32 DumpVolumeHeader(XFILE *, afs_vol_header *);
extern afs_uint32 DumpVNode(XFILE *, afs_vnode *);
extern afs_uint32 DumpVnodeData(XFILE *, char *, afs_uint32);
extern afs_uint32 CopyVnodeData(XFILE *, XFILE *, afs_uint32);
extern afs_uint32 DumpVNodeData(XFILE *OX, char *buf, afs_uint32 size);
extern afs_uint32 DumpDumpEnd(XFILE *OX);
/* pathname.c - Follow and construct pathnames */
extern afs_uint32 Path_PreScan(XFILE *, path_hashinfo *, int);
extern void Path_FreeHashTable(path_hashinfo *);
extern afs_uint32 Path_Follow(XFILE *, path_hashinfo *, char *, vhash_ent *);
extern afs_uint32 Path_Build(XFILE *, path_hashinfo *, afs_uint32, char **,
int);
extern afs_uint32 Path_Build(XFILE *, path_hashinfo *, afs_uint32, char **, int);
#endif