* 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
* 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"
#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 bmbyte(bm,x) bm[(x)>>3]
+#define bmbit(x) (1 << ((x) & 7))
+
+#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)
+static void fixup(char *name, int l)
{
- name += 16;
- l -= 15;
+ name += 16;
+ l -= 15;
- while (l-- > 0) {
- name[0] = name[4];
- name++;
- }
+ 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_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_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;
+ 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;
}
- 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;
- }
+ 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;
-
- 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;
+ 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);
}
- return DSERR_DONE;
+ if (s->vuniq) s->vuniq[0] = de->uniq;
+ }
+ return DSERR_DONE;
}
* 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;
+
+ 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;
+
+ 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)
{
- 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_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);
+ 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;
}
* 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
#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,
* 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;
#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;
#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;
#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 */
-
- /* 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 *);
-
- 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 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 */
+ /* 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 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 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 */
/** 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;
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 *);
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 *);
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