Example #1
0
/*** THIS FUNCTION INTENDED FOR INTERNAL USE ONLY ***/
int
handle_return(int r, XFILE * X, unsigned char tag, dump_parser * p)
{
    u_int64 where, xwhere;

    switch (r) {
    case 0:
	if (p->cb_error) {
	    xftell(X, &where);
	    sub64_32(xwhere, where, 1);
	    (p->cb_error) (DSERR_TAG, 1, p->err_refcon,
			   (tag > 0x20 && tag < 0x7f)
			   ? "Unexpected tag '%c' at %s = 0x%s" :
			   "Unexpected tag 0x%02x at %s = 0x%s", tag,
			   decimate_int64(&xwhere, 0), hexify_int64(&xwhere,
								    0));
	}
	return DSERR_TAG;

    case ERROR_XFILE_EOF:
	if (p->cb_error) {
	    xftell(X, &where);
	    (p->cb_error) (ERROR_XFILE_EOF, 1, p->err_refcon,
			   "Unexpected EOF at %s = 0x%s",
			   decimate_int64(&where, 0), hexify_int64(&where,
								   0));
	}
	return ERROR_XFILE_EOF;

    case ENOMEM:
	if (p->cb_error) {
	    xftell(X, &where);
	    (p->cb_error) (ENOMEM, 1, p->err_refcon,
			   "Out of memory at %s = 0x%s",
			   decimate_int64(&where, 0), hexify_int64(&where,
								   0));
	}
	return ENOMEM;

    case DSERR_DONE:
	return 0;

    default:
	/* For other negative valuees, the callback was already done */
	if (r > 0 && p->cb_error)
	    (p->cb_error) (r, 1, p->err_refcon,
			   "System error %d reading dump file", r);
	return r;
    }
}
Example #2
0
/* Parse a dump header, including its tagged attributes, and call the
 * dump-header callback, if one is defined.
 */
static afs_uint32
parse_dumphdr(XFILE * X, unsigned char *tag, tagged_field * field,
	      afs_uint32 value, tag_parse_info * pi, void *g_refcon,
	      void *l_refcon)
{
    dump_parser *p = (dump_parser *) g_refcon;
    afs_dump_header hdr;
    dt_uint64 where;
    afs_uint32 r;

    memset(&hdr, 0, sizeof(hdr));
    if ((r = xftell(X, &where)))
	return r;
    sub64_32(hdr.offset, where, 1);

    if ((r = ReadInt32(X, &hdr.magic)))
	return r;
    if ((r = ReadInt32(X, &hdr.version)))
	return r;

    if (hdr.magic != DUMPBEGINMAGIC) {
	if (p->cb_error)
	    (p->cb_error) (DSERR_MAGIC, 1, p->err_refcon,
			   "Invalid magic number (0x%08x) in dump header",
			   hdr.magic);
	return DSERR_MAGIC;
    }
    if (hdr.version != DUMPVERSION) {
	if (p->cb_error)
	    (p->cb_error) (DSERR_MAGIC, 1, p->err_refcon,
			   "Unknown dump format version (%d) in dump header",
			   hdr.version);
	return DSERR_MAGIC;
    }

    if (p->print_flags & DSPRINT_DUMPHDR)
	printf("%s [%s = 0x%s]\n", field->label,
	       decimate_int64(&hdr.offset, 0), hexify_int64(&hdr.offset, 0));
    if (p->print_flags & DSPRINT_DUMPHDR) {
	printf(" Magic number: 0x%08x\n", hdr.magic);
	printf(" Version:      %d\n", hdr.version);
    }
    r = ParseTaggedData(X, dumphdr_fields, tag, pi, g_refcon, (void *)&hdr);

    if (!r && p->cb_dumphdr) {
	r = xftell(X, &where);
	if (!r)
	    r = (p->cb_dumphdr) (&hdr, X, p->refcon);
	if (p->flags & DSFLAG_SEEK) {
	    if (!r)
		r = xfseek(X, &where);
	    else
		xfseek(X, &where);
	}
    }
    if (hdr.field_mask & F_DUMPHDR_VOLNAME)
	free(hdr.volname);
    return r;
}
Example #3
0
static afs_uint32
resync_vnode(XFILE * X, dump_parser * p, afs_vnode * v, int start, int limit)
{
    dt_uint64 where, expected_where;
    afs_uint32 r;
    int i;

    if ((r = xftell(X, &expected_where)))
	return r;
    cp64(where, expected_where);

    r = match_next_vnode(X, p, &where, v->vnode);
    if (r && r != DSERR_FMT)
	return r;
    if (r)
	for (i = -start; i < limit; i++) {
	    add64_32(where, expected_where, i);
	    r = match_next_vnode(X, p, &where, v->vnode);
	    if (!r)
		break;
	    if (r != DSERR_FMT)
		return r;
	}
    if (r) {
	if (p->cb_error)
	    (p->cb_error) (r, 1, p->err_refcon,
			   "Unable to resync after vnode %d [%s = 0x%s]",
			   v->vnode, decimate_int64(&expected_where, 0),
			   hexify_int64(&expected_where, 0));
	return r;
    }
    if (ne64(where, expected_where) && p->cb_error) {
	(p->cb_error) (DSERR_FMT, 0, p->err_refcon,
		       "Vnode after %d not in expected location", v->vnode);
	(p->cb_error) (DSERR_FMT, 0, p->err_refcon,
		       "Expected location: %s = 0x%s",
		       decimate_int64(&expected_where, 0),
		       hexify_int64(&expected_where, 0));
	(p->cb_error) (DSERR_FMT, 0, p->err_refcon,
		       "Actual location: %s = 0x%s", decimate_int64(&where,
								    0),
		       hexify_int64(&where, 0));
    }
    return xfseek(X, &where);
}
Example #4
0
/* Parse a volume header, including any tagged attributes, and call the
 * volume-header callback, if one is defined.
 */
afs_uint32
parse_volhdr(XFILE * X, unsigned char *tag, tagged_field * field,
	     afs_uint32 value, tag_parse_info * pi, void *g_refcon,
	     void *l_refcon)
{
    dump_parser *p = (dump_parser *) g_refcon;
    afs_vol_header hdr;
    u_int64 where;
    afs_uint32 r;

    memset(&hdr, 0, sizeof(hdr));
    if (r = xftell(X, &where))
	return r;
    sub64_32(hdr.offset, where, 1);
    if (p->print_flags & DSPRINT_VOLHDR)
	printf("%s [%s = 0x%s]\n", field->label,
	       decimate_int64(&hdr.offset, 0), hexify_int64(&hdr.offset, 0));

    r = ParseTaggedData(X, volhdr_fields, tag, pi, g_refcon, (void *)&hdr);

    if (!r && p->cb_volhdr) {
	if (r = xftell(X, &where))
	    return r;
	r = (p->cb_volhdr) (&hdr, X, p->refcon);
	if (p->flags & DSFLAG_SEEK) {
	    if (!r)
		r = xfseek(X, &where);
	    else
		xfseek(X, &where);
	}
    }
    if (hdr.field_mask & F_VOLHDR_VOLUNIQ)
	p->vol_uniquifier = hdr.voluniq;
    if (hdr.field_mask & F_VOLHDR_VOLNAME)
	free(hdr.volname);
    if (hdr.field_mask & F_VOLHDR_OFFLINE_MSG)
	free(hdr.offline_msg);
    if (hdr.field_mask & F_VOLHDR_MOTD)
	free(hdr.motd_msg);
    return r;
}
Example #5
0
/* Parse or skip over the vnode data */
static afs_uint32
parse_vdata(XFILE * X, unsigned char *tag, tagged_field * field,
	    afs_uint32 value, tag_parse_info * pi, void *g_refcon,
	    void *l_refcon)
{
    dump_parser *p = (dump_parser *) g_refcon;
    afs_vnode *v = (afs_vnode *) l_refcon;
    static char *symlink_buf = 0;
    static int symlink_size = 0;
    afs_uint32 r;

    if ((r = ReadInt32(X, &v->size)))
	return r;
    v->field_mask |= F_VNODE_SIZE;

    if (v->size) {
	v->field_mask |= F_VNODE_DATA;
	if ((r = xftell(X, &v->d_offset)))
	    return r;
	if (p->print_flags & DSPRINT_VNODE)
	    printf("%s%d (0x%08x) bytes at %s (0x%s)\n", field->label,
		   v->size, v->size, decimate_int64(&v->d_offset, 0),
		   hexify_int64(&v->d_offset, 0));

	switch (v->type) {
	case vSymlink:
	    if (v->size > symlink_size) {
		if (symlink_buf)
		    symlink_buf = realloc(symlink_buf, v->size + 1);
		else
		    symlink_buf = (char *)malloc(v->size + 1);
		symlink_size = symlink_buf ? v->size : 0;
	    }
	    if (symlink_buf) {
		if ((r = xfread(X, symlink_buf, v->size)))
		    return r;
		symlink_buf[v->size] = 0;
		if (p->print_flags & DSPRINT_VNODE)
		    printf(" Target:       %s\n", symlink_buf);
	    } else {
		/* Call the callback here, because it's non-fatal */
		if (p->cb_error)
		    (p->cb_error) (ENOMEM, 0, p->err_refcon,
				   "Out of memory reading symlink");
		if ((r = xfskip(X, v->size)))
		    return r;
	    }
	    break;

	case vDirectory:
	    if (p->cb_dirent || (p->print_flags & DSPRINT_DIR)) {
		if ((r = parse_directory(X, p, v, v->size, 0)))
		    return r;
		break;
	    }

	default:
	    if ((r = xfskip(X, v->size)))
		return r;
	}
    } else if (p->print_flags & DSPRINT_VNODE) {
	printf("%sEmpty\n", field->label);
    }
    if (p->repair_flags & DSFIX_VDSYNC) {
	r = resync_vnode(X, p, v, 10, 15);
	if (r)
	    return r;
    }
    return ReadByte(X, tag);
}
Example #6
0
/* Parse a VNode, including any tagged attributes and data, and call the
 * appropriate callback, if one is defined.
 */
afs_uint32
parse_vnode(XFILE * X, unsigned char *tag, tagged_field * field,
	    afs_uint32 value, tag_parse_info * pi, void *g_refcon,
	    void *l_refcon)
{
    dump_parser *p = (dump_parser *) g_refcon;
    afs_uint32(*cb) (afs_vnode *, XFILE *, void *);
    dt_uint64 where, offset2k;
    afs_vnode v;
    afs_uint32 r;


    if ((r = xftell(X, &where)))
	return r;
    memset(&v, 0, sizeof(v));
    sub64_32(v.offset, where, 1);
    if ((r = ReadInt32(X, &v.vnode)))
	return r;
    if ((r = ReadInt32(X, &v.vuniq)))
	return r;

    mk64(offset2k, 0, 2048);
    if (!LastGoodVNode
	|| ((p->flags & DSFLAG_SEEK) && v.vnode == 1
	    && lt64(v.offset, offset2k)))
	LastGoodVNode = -1;

    if (p->print_flags & DSPRINT_ITEM) {
	printf("%s %d/%d [%s = 0x%s]\n", field->label, v.vnode, v.vuniq,
	       decimate_int64(&where, 0), hexify_int64(&where, 0));
    }

    r = ParseTaggedData(X, vnode_fields, tag, pi, g_refcon, (void *)&v);

    /* Try to resync, if requested */
    if (!r && (p->repair_flags & DSFIX_VFSYNC)) {
	afs_uint32 drop;
	dt_uint64 xwhere;

	if ((r = xftell(X, &where)))
	    return r;
	sub64_32(xwhere, where, 1);

	/* Are we at the start of a valid vnode (or dump end)? */
	r = match_next_vnode(X, p, &xwhere, v.vnode);
	if (r && r != DSERR_FMT)
	    return r;
	if (r) {		/* Nope. */
	    /* Was _this_ a valid vnode?  If so, we can keep it and search for
	     * the next one.  Otherwise, we throw it out, and start the search
	     * at the starting point of this vnode.
	     */
	    drop = r = match_next_vnode(X, p, &v.offset, LastGoodVNode);
	    if (r && r != DSERR_FMT)
		return r;
	    if (!r) {
		add64_32(where, v.offset, 1);
		if ((r = xfseek(X, &v.offset)))
		    return r;
	    } else {
		if ((r = xfseek(X, &xwhere)))
		    return r;
	    }
	    if ((r = resync_vnode(X, p, &v, 0, 1024)))
		return r;
	    if ((r = ReadByte(X, tag)))
		return r;
	    if (drop) {
		if (p->cb_error)
		    (p->cb_error) (DSERR_FMT, 0, p->err_refcon,
				   "Dropping vnode %d", v.vnode);
		return 0;
	    }
	} else {
	    if ((r = xfseek(X, &where)))
		return r;
	}
    }
    LastGoodVNode = v.vnode;

    if (!r) {
	if (v.field_mask & F_VNODE_TYPE)
	    switch (v.type) {
	    case vFile:
		cb = p->cb_vnode_file;
		break;
	    case vDirectory:
		cb = p->cb_vnode_dir;
		break;
	    case vSymlink:
		cb = p->cb_vnode_link;
		break;
	    default:
		cb = p->cb_vnode_wierd;
		break;
	} else
	    cb = p->cb_vnode_empty;
	if (cb) {
	    dt_uint64 where;

	    if ((r = xftell(X, &where)))
		return r;
	    r = (cb) (&v, X, p->refcon);
	    if (p->flags & DSFLAG_SEEK) {
		if (!r)
		    r = xfseek(X, &where);
		else
		    xfseek(X, &where);
	    }
	}
    }
    return r;
}
Example #7
0
/* Parse a file containing tagged data and attributes **/
afs_uint32
ParseTaggedData(XFILE * X, tagged_field * fields, unsigned char *tag,
		tag_parse_info * pi, void *g_refcon, void *l_refcon)
{
    int i = -1;
    afs_uint32 r, val;
    afs_uint16 val16;
    unsigned char val8;
    unsigned char *strval;

    for (;;) {
	if (i < 0 || (fields[i].kind & DKIND_MASK) != DKIND_SPECIAL) {
	    /* Need to read in a tag */
	    if ((r = ReadByte(X, tag)))
		return r;
	}

	/* Simple error recovery - if we encounter a 0, it can never be
	 * a valid tag.  If TPFLAG_SKIP is set, we can skip over any
	 * such null bytes, and process whatever tag we find beyond.
	 * In addition, if TPFLAG_RSKIP is set, then the next time
	 * we encounter a 0, try skipping backwards.  That seems to
	 * work much of the time.
	 */
	if (!*tag && pi->shift_offset && (pi->flags & TPFLAG_RSKIP)) {
	    u_int64 where, tmp64a, tmp64b;
	    char buf1[21], buf2[21], buf3[21];
	    char *p1, *p2, *p3;

	    if ((r = xftell(X, &tmp64a)))
		return r;
	    sub64_32(where, tmp64a, pi->shift_offset + 1);
	    if ((r = xfseek(X, &where)))
		return r;
	    if (pi->cb_error) {
		(pi->cb_error) (DSERR_FMT, 0, pi->err_refcon,
				"Inserted %d bytes before offset %d",
				pi->shift_offset, decimate_int64(&where, 0));
		add64_32(tmp64a, pi->shift_start, pi->shift_offset);
		p1 = decimate_int64(&tmp64a, buf1);
		sub64_64(tmp64b, where, tmp64a);
		p2 = decimate_int64(&tmp64b, buf2);
		p3 = decimate_int64(&pi->shift_start, buf3);
		(pi->cb_error) (DSERR_FMT, 0, pi->err_refcon,
				">>> SHIFT start=%s length=%s target=%s", p1,
				p2, p3);
	    }
	    pi->shift_offset = 0;
	    if ((r = ReadByte(X, tag)))
		return r;
	}
	if (!*tag && (pi->flags & TPFLAG_SKIP)) {
	    int count = 0;
	    u_int64 where, tmp64a;

	    if ((r = xftell(X, &where)))
		return r;

	    while (!*tag) {
		if ((r = ReadByte(X, tag)))
		    return r;
		count++;
	    }
	    pi->shift_offset += count;
	    cp64(pi->shift_start, where);
	    if (pi->cb_error) {
		sub64_32(tmp64a, where, 1);
		(pi->cb_error) (DSERR_FMT, 0, pi->err_refcon,
				"Skipped %d bytes at offset %s", count,
				decimate_int64(&tmp64a, 0));
	    }
	}

	for (i = 0; fields[i].tag && fields[i].tag != *tag; i++);
	if (!fields[i].tag)
	    return 0;

	switch (fields[i].kind & DKIND_MASK) {
	case DKIND_NOOP:
	    if (fields[i].func) {
		r = (fields[i].func) (X, 0, fields + i, 0, pi, g_refcon,
				      l_refcon);
		if (r)
		    return r;
	    }
	    break;

	case DKIND_BYTE:
	    if ((r = ReadByte(X, &val8)))
		return r;
	    if (fields[i].func) {
		r = (fields[i].func) (X, 0, fields + i, val8, pi, g_refcon,
				      l_refcon);
		if (r)
		    return r;
	    }
	    break;

	case DKIND_INT16:
	    if ((r = ReadInt16(X, &val16)))
		return r;
	    if (fields[i].func) {
		r = (fields[i].func) (X, 0, fields + i, val16, pi, g_refcon,
				      l_refcon);
		if (r)
		    return r;
	    }
	    break;

	case DKIND_INT32:
	    if ((r = ReadInt32(X, &val)))
		return r;
	    if (fields[i].func) {
		r = (fields[i].func) (X, 0, fields + i, val, pi, g_refcon,
				      l_refcon);
		if (r)
		    return r;
	    }
	    break;

	case DKIND_STRING:
	    if ((r = ReadString(X, &strval)))
		return r;
	    if (fields[i].func) {
		r = (fields[i].func) (X, strval, fields + i, 0, pi, g_refcon,
				      l_refcon);
		if (r != DSERR_KEEP)
		    free(strval);
		if (r && r != DSERR_KEEP)
		    return r;
	    } else
		free(strval);
	    break;

	case DKIND_SPECIAL:
	    if (fields[i].func) {
		r = (fields[i].func) (X, tag, fields + i, 0, pi, g_refcon,
				      l_refcon);
		if (r)
		    return r;
	    } else
		i = -1;
	}
    }
}