/* * CMUCS AFStools * dumpscan - routines for scanning and manipulating AFS volume dumps * * Copyright (c) 1998, 2001, 2003 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie Mellon * the rights to redistribute these changes. */ /* dumpscan.h - Public interface */ #ifndef _DUMPSCAN_H_ #define _DUMPSCAN_H_ #include "intNN.h" #include "xfiles.h" #include #include #include #include #include /* 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 struct dir_state dir_state; /* Error codes used within dumpscan. * Any of the routines declared below, or callbacks used by them, * may signal a system error by returning the error number, or * some other error by returning a com_err code. Note that * ParseTaggedData does _not_ return DSERR_TAG; instead, it returns * 0, assuming the tag will be handled at a higher level. * * In addition, these errors may be reported to the caller of * ParseDumpFile using the error callback. Such reports will be * issued whether or not error recovery is possible or attempted. * * NB: These errors are now in dumpscan_errs.h */ /* Backup system dump header */ /* Right now, this looks a lot like an old stage header. Eventually, it * should contain enough fields to fully represent headers from old or * new stage, Transarc, or other backup systems, and the appropriate read * 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; u_int64 dumplen; afs_uint32 level; afs_uint32 magic; afs_uint32 cksum; afs_uint32 flags; } backup_system_header; /** AFS dump header **/ #define F_DUMPHDR_VOLID 0x00000001 #define F_DUMPHDR_VOLNAME 0x00000002 #define F_DUMPHDR_FROM 0x00000004 #define F_DUMPHDR_TO 0x00000008 typedef struct { 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; /** AFS volume header **/ #define F_VOLHDR_VOLID 0x00000001 #define F_VOLHDR_VOLVERS 0x00000002 #define F_VOLHDR_VOLNAME 0x00000004 #define F_VOLHDR_INSERV 0x00000008 #define F_VOLHDR_BLESSED 0x00000010 #define F_VOLHDR_VOLUNIQ 0x00000020 #define F_VOLHDR_VOLTYPE 0x00000040 #define F_VOLHDR_PARENT 0x00000080 #define F_VOLHDR_CLONE 0x00000100 #define F_VOLHDR_MAXQ 0x00000200 #define F_VOLHDR_MINQ 0x00000400 #define F_VOLHDR_DISKUSED 0x00000800 #define F_VOLHDR_NFILES 0x00001000 #define F_VOLHDR_ACCOUNT 0x00002000 #define F_VOLHDR_OWNER 0x00004000 #define F_VOLHDR_CREATE_DATE 0x00008000 #define F_VOLHDR_ACCESS_DATE 0x00010000 #define F_VOLHDR_UPDATE_DATE 0x00020000 #define F_VOLHDR_EXPIRE_DATE 0x00040000 #define F_VOLHDR_BACKUP_DATE 0x00080000 #define F_VOLHDR_OFFLINE_MSG 0x00100000 #define F_VOLHDR_MOTD 0x00200000 #define F_VOLHDR_WEEKUSE 0x00400000 #define F_VOLHDR_DAYUSE 0x00800000 #define F_VOLHDR_DAYUSE_DATE 0x01000000 typedef struct { 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; /** AFS vnode **/ #define F_VNODE_TYPE 0x00000001 #define F_VNODE_NLINKS 0x00000002 #define F_VNODE_PARENT 0x00000004 #define F_VNODE_DVERS 0x00000008 #define F_VNODE_AUTHOR 0x00000010 #define F_VNODE_OWNER 0x00000020 #define F_VNODE_GROUP 0x00000040 #define F_VNODE_MODE 0x00000080 #define F_VNODE_CDATE 0x00000100 #define F_VNODE_SDATE 0x00000200 #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 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 */ } 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_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; #define TPFLAG_SKIP 0x0001 #define TPFLAG_RSKIP 0x0002 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) */ }; /** 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 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; } 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 */ } 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 */ } path_hashinfo; /** Function prototypes **/ /** Only the functions declared below are public interfaces **/ /** Maybe someday, I'll write man pages for these **/ /* primitive.c - I/O primitives */ extern afs_uint32 ReadByte(XFILE *, unsigned char *); extern afs_uint32 ReadInt16(XFILE *, afs_uint16 *); extern afs_uint32 ReadInt32(XFILE *, afs_uint32 *); extern afs_uint32 ReadString(XFILE *, unsigned char **); extern afs_uint32 WriteByte(XFILE *, unsigned char); extern afs_uint32 WriteInt16(XFILE *, afs_uint16); extern afs_uint32 WriteInt32(XFILE *, afs_uint32); 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 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 *); /* stagehdr.c - Parse and dump Stage dump headers */ 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 *); /* parsedump.c - Parse all or part of a volume dump */ extern afs_uint32 ParseDumpFile(XFILE *, dump_parser *); extern afs_uint32 ParseDumpHeader(XFILE *, dump_parser *); extern afs_uint32 ParseVolumeHeader(XFILE *, dump_parser *); extern afs_uint32 ParseVNode(XFILE *, dump_parser *); /* 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 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 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); #endif