Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 23 May 2012 20:59:31 +0000
From:      gpf@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r236229 - soc2012/gpf/misc
Message-ID:  <20120523205931.AA7891065672@hub.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gpf
Date: Wed May 23 20:59:30 2012
New Revision: 236229
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=236229

Log:
  test_checksum.c to test validity of .pefs.checksum file.
  
  output from this program's pefs_print_hash_table() should be
  checked against output from sbin/pefs' pefs_print_hash_table().
  They should match of course. Code just passed a test with a 100
  files.
  

Added:
  soc2012/gpf/misc/
  soc2012/gpf/misc/test_checksum.c

Added: soc2012/gpf/misc/test_checksum.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2012/gpf/misc/test_checksum.c	Wed May 23 20:59:30 2012	(r236229)
@@ -0,0 +1,412 @@
+/*-
+ * Copyright (c) 2012 Efstratios Karatzas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+ 
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/endian.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <err.h>
+
+
+#define PEFS_INTEGRITY_DEBUG
+#if defined (PEFS_INTEGRITY_DEBUG)
+#define dprintf(a)		printf a
+#else
+#define dprintf(a)      (void)0
+#endif
+
+#define NARGS 2
+#define ERROR 1
+#define MAXPATHLEN 1024
+#define PEFS_CHECKSUM_FILE_VERSION 0xDD
+#define PEFS_HASH_BYTE_ALIGNMENT 512
+
+LIST_HEAD(file_header_head, file_header);
+TAILQ_HEAD(checksum_head, checksum);
+
+struct checksum_file_header {
+        uint8_t version;
+        uint8_t reserved;
+        uint8_t hash_len;
+        uint8_t hash_algo[8];
+        uint8_t offset_to_hash_table;
+        uint32_t hash_table_size;
+};
+
+struct checksum {
+	unsigned char *hash;
+	TAILQ_ENTRY(checksum) checksum_entries;
+};
+
+struct file_header {
+	uint32_t nhashes;
+	uint64_t file_id;
+	char path[MAXPATHLEN];
+	LIST_ENTRY(file_header) bucket_entries;
+	uint32_t offset_to_checksums;
+	struct checksum_head checksums;
+};
+
+struct bucket {
+	struct file_header_head file_headers;
+	uint32_t offset_to_chain;
+	uint32_t nelements;
+	uint32_t elements_loaded;
+};
+
+struct hash_table {
+	struct bucket *buckets;
+	uint32_t size; /* how many buckets */
+	uint32_t nelements;
+};
+
+
+static int
+pefs_allocate_hash_table(struct hash_table *checksum_hash_tablep, uint32_t size)
+{
+	uint32_t i;
+
+	checksum_hash_tablep->size = size;
+	checksum_hash_tablep->buckets = malloc (size * sizeof(struct bucket));
+
+	if (checksum_hash_tablep->buckets == NULL) {
+		perror("memory allocation error");
+		return (ERROR);
+	}
+
+	for (i = 0; i < checksum_hash_tablep->size; i++) {
+		checksum_hash_tablep->buckets[i].nelements = 0;
+		checksum_hash_tablep->buckets[i].elements_loaded = 0;
+		LIST_INIT(&(checksum_hash_tablep->buckets[i].file_headers));
+	}
+
+	return (0);
+}
+
+static void
+pefs_add_to_bucket(struct bucket *bucketp, struct file_header *fhp)
+{
+	struct file_header *elementp;
+	struct file_header *last;
+
+	if (bucketp->elements_loaded == 0)
+		LIST_INSERT_HEAD(&(bucketp->file_headers), fhp, bucket_entries);
+	else {
+		LIST_FOREACH(elementp, &(bucketp->file_headers), bucket_entries) {
+			last = elementp;
+		}
+		LIST_INSERT_AFTER(last, fhp, bucket_entries);
+	}
+
+	bucketp->elements_loaded++;
+}
+
+static void
+pefs_add_to_file_header(struct file_header *fhp, struct checksum *csp)
+{
+	TAILQ_INSERT_TAIL(&(fhp->checksums), csp, checksum_entries);
+}
+
+/* for debugging purposes */
+static void
+pefs_print_hash_table(struct hash_table *checksum_hash_tablep, uint8_t hash_len)
+{
+	struct file_header *fhp;
+	struct checksum *csp;
+	uint32_t i,j;
+
+	printf("\n+++Printing Hash Table+++\n\n");
+	for (i = 0; i < checksum_hash_tablep->size; i++) {
+		printf("\nbucket %d with elements: %u\n", i, checksum_hash_tablep->buckets[i].nelements);
+		LIST_FOREACH(fhp, &(checksum_hash_tablep->buckets[i].file_headers), bucket_entries) {
+			printf("\tid = %d!\tnhashes = %d\n", (int)fhp->file_id, fhp->nhashes);
+			TAILQ_FOREACH(csp, &(fhp->checksums), checksum_entries) {
+				printf("\t\tdigest=");
+				for (j = 0; j < hash_len; j++)
+					printf("%02x", csp->hash[j]);
+				printf("\n");
+			}
+		}
+	}
+}
+
+static int
+pefs_read_checksum_file_header(int fdin, struct checksum_file_header *cfhp)
+{
+	uint32_t bytes, hash_table_size;
+
+	bytes = read(fdin, &(cfhp->version), sizeof(cfhp->version));
+	if (bytes != sizeof(cfhp->version)) {
+		perror("error reading from .pefs.checksum");
+		return (ERROR);
+	}
+
+	bytes = read(fdin, &(cfhp->reserved), sizeof(cfhp->reserved));
+	if (bytes != sizeof(cfhp->reserved)) {
+		perror("error reading from .pefs.checksum");
+		return (ERROR);
+	}
+
+	bytes = read(fdin, &(cfhp->hash_len), sizeof(cfhp->hash_len));
+	if (bytes != sizeof(cfhp->hash_len)) {
+		perror("error reading from .pefs.checksum");
+		return (ERROR);
+	}
+
+	bytes = read(fdin, cfhp->hash_algo, sizeof(cfhp->hash_algo));
+	if (bytes != sizeof(cfhp->hash_algo)) {
+		perror("error reading from .pefs.checksum");
+		return (ERROR);
+	}
+
+	bytes = read(fdin, &(cfhp->offset_to_hash_table), sizeof(cfhp->offset_to_hash_table));
+	if (bytes != sizeof(cfhp->offset_to_hash_table)) {
+		perror("error reading from .pefs.checksum");
+		return (ERROR);
+	}
+
+	bytes = read(fdin, &hash_table_size, sizeof(hash_table_size));
+	if (bytes != sizeof(hash_table_size)) {
+		perror("error reading from .pefs.checksum");
+		return (ERROR);
+	}
+	cfhp->hash_table_size = le32toh(hash_table_size);
+
+	dprintf(("+++printing checksum file header info+++\n"));
+	dprintf(("version %X\nhash_len %d\nhash_algo %s\n", cfhp->version, cfhp->hash_len, cfhp->hash_algo));
+	dprintf(("offset to hash table %d\nhash table size %d\n", cfhp->offset_to_hash_table, cfhp->hash_table_size));
+
+	return (0);
+}
+
+static int
+pefs_read_bucket(int fdin, struct bucket *bp, uint32_t *buckets_offset)
+{
+	uint32_t offset_to_chain, nelements;
+	int bytes;
+
+	//dprintf(("bucket offset = %d\n", *buckets_offset));
+
+	bytes = pread(fdin, &offset_to_chain, sizeof(offset_to_chain), *buckets_offset);
+	if (bytes != sizeof(offset_to_chain)) {
+		perror("error reading from .pefs.checksum");
+		return (ERROR);
+	}
+	bp->offset_to_chain = le32toh(offset_to_chain);
+	(*buckets_offset)+= sizeof(offset_to_chain);
+
+	bytes = pread(fdin, &nelements, sizeof(nelements), *buckets_offset);
+	if (bytes != sizeof(nelements)) {
+		perror("error reading from .pefs.checksum");
+		return (ERROR);
+	}
+	bp->nelements = le32toh(nelements);
+	(*buckets_offset)+= sizeof(nelements);
+
+	//dprintf(("\n++priting bucket info++\n"));
+	//dprintf(("offset to chain %d\nnelements %d\n", bp->offset_to_chain, bp->nelements));
+
+	return (0);
+}
+
+static int
+pefs_read_file_header(int fdin, struct file_header *fhp, uint32_t *fh_offset)
+{
+	uint64_t file_id;
+	uint32_t nhashes, offset_to_checksums;
+	int bytes;
+
+	bytes = pread(fdin, &nhashes, sizeof(nhashes), *fh_offset);
+	if (bytes != sizeof(nhashes)) {
+		perror("error reading from .pefs.checksum");
+		return (ERROR);
+	}
+	fhp->nhashes = le32toh(nhashes);
+	(*fh_offset)+= sizeof(nhashes);
+
+	bytes = pread(fdin, &offset_to_checksums, sizeof(offset_to_checksums), *fh_offset);
+	if (bytes != sizeof(offset_to_checksums)) {
+		perror("error reading from .pefs.checksum");
+		return (ERROR);
+	}
+	fhp->offset_to_checksums = le32toh(offset_to_checksums);
+	(*fh_offset)+= sizeof(offset_to_checksums);
+	
+	bytes = pread(fdin, &file_id, sizeof(file_id), *fh_offset);
+	if (bytes != sizeof(file_id)) {
+		perror("error reading from .pefs.checksum");
+		return (ERROR);
+	}
+	fhp->file_id = le64toh(file_id);
+	(*fh_offset)+= sizeof(file_id);
+	
+	//dprintf(("\nfile header offset = %d\n", *fh_offset));
+	//dprintf(("\n++priting file header info++\n"));
+	//dprintf(("nhashes %d\noffset_to_checksums %d\n", fhp->nhashes, fhp->offset_to_checksums));
+	//dprintf(("file id %d\n", (int)fhp->file_id));
+
+	return (0);
+}
+
+static int
+pefs_read_hash(int fdin, struct checksum *csp, uint32_t *hashes_offset, uint8_t hash_len)
+{
+	int bytes;
+
+	bytes = pread(fdin, csp->hash, hash_len, *hashes_offset);
+	if (bytes != hash_len) {
+		perror("error reading from .pefs.checksum");
+		return (ERROR);
+	}
+	(*hashes_offset)+= hash_len;
+	
+	//dprintf(("hashes offset = %d\n", *hashes_offset));
+	//dprintf(("hash %s\n", csp->hash));
+
+	return (0);
+}
+
+static int
+pefs_read_checksum_file(int fdin, struct checksum_file_header *cfhp, struct hash_table *chtp)
+{
+	struct bucket *bp;
+	struct checksum *csp;
+	struct file_header *fhp;
+	uint32_t i, j, k, buckets_offset, fh_offset, hashes_offset;
+	int error;
+
+	error = pefs_read_checksum_file_header(fdin, cfhp);
+	if (error != 0)
+		return (error);
+
+	error = pefs_allocate_hash_table(chtp, cfhp->hash_table_size);
+	if (error != 0)
+		return (error);
+
+	/* this points to where the buckets start */
+	buckets_offset = cfhp->offset_to_hash_table;
+
+	for (i = 0; i < chtp->size; i++) {
+		bp = &chtp->buckets[i];
+		error = pefs_read_bucket(fdin, bp, &buckets_offset);
+		if (error != 0)
+			return (error);
+
+		fh_offset = bp->offset_to_chain;
+
+		for (j = 0; j < bp->nelements; j++) {
+			fhp = malloc(sizeof(struct file_header));
+			if (fhp == NULL) {
+				perror("malloc");
+				return (ERROR);
+			}
+
+			error = pefs_read_file_header(fdin, fhp, &fh_offset);
+			if (error != 0)
+				return (ERROR);
+
+			TAILQ_INIT(&(fhp->checksums));
+			hashes_offset = fhp->offset_to_checksums;
+			pefs_add_to_bucket(bp, fhp);
+
+			for (k = 0; k < fhp->nhashes; k++) {
+				csp = malloc(sizeof(struct checksum));
+				if (csp == NULL) {
+					perror("malloc");
+					return (ERROR);
+				}
+				csp->hash = malloc(cfhp->hash_len);
+				if (csp->hash == NULL) {
+					perror("malloc");
+					return (ERROR);
+				}
+
+				error = pefs_read_hash(fdin, csp, &hashes_offset, cfhp->hash_len);
+				if (error != 0)
+					return (error);
+				
+				pefs_add_to_file_header(fhp, csp);
+			}
+		}
+	}
+
+	return (0);
+}
+
+static void
+usage(char *argv[])
+{
+	printf("usage: %s /path/to/.pefs.checksum\n", argv[0]);
+}
+
+/*
+ * XXXgpf: Purpose of code is to test validity of a .pefs.checksum file.
+ * Output from this program's pefs_print_hash_table() is checked against 
+ * output from sbin/pefs' pefs_print_hash_table(). They should match.
+ * 
+ */
+int
+main(int argc, char *argv[])
+{
+	char checksum_path[MAXPATHLEN];
+	struct hash_table checksum_hash_table;
+	struct checksum_file_header cfh;
+	int error, fdin;
+
+	if (argc != NARGS) {
+		usage(argv);
+		return (ERROR);
+	}
+
+	strlcpy(checksum_path, argv[1], sizeof(checksum_path));
+	fdin = open(checksum_path, O_RDONLY);
+	if (fdin == -1) {
+		perror("cannot open checksum file");
+		return (ERROR);
+	}
+
+	error = pefs_read_checksum_file(fdin, &cfh, &checksum_hash_table);
+
+	/* this output should be the same as the one from sbin/pefs */
+	pefs_print_hash_table(&checksum_hash_table, cfh.hash_len);
+
+	close(fdin);
+
+	return (error);
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120523205931.AA7891065672>