Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 23 May 2012 21:04:09 +0000
From:      gpf@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r236233 - soc2012/gpf/pefs_kmod/sbin/pefs
Message-ID:  <20120523210409.11BDC1065672@hub.freebsd.org>

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

Log:
  write everything to .pefs.checksum. Seems to be working.
  

Modified:
  soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c

Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c
==============================================================================
--- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c	Wed May 23 20:51:21 2012	(r236232)
+++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c	Wed May 23 21:04:08 2012	(r236233)
@@ -28,6 +28,7 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <sys/endian.h>
 #include <sys/mount.h>
 #include <sys/queue.h>
 #include <sys/types.h>
@@ -50,16 +51,32 @@
 
 #include "pefs_ctl.h"
 
-#define PEFS_INTEGRITY_DEBUG
+//#define PEFS_INTEGRITY_DEBUG
 #if defined (PEFS_INTEGRITY_DEBUG)
 #define dprintf(a)		printf a
 #else
 #define dprintf(a)      (void)0
 #endif
 
+#define PEFS_CHECKSUM_FILE_VERSION 0xDD
+#define PEFS_HASH_BYTE_ALIGNMENT 512
+
 LIST_HEAD(file_header_head, file_header);
 TAILQ_HEAD(checksum_head, checksum);
 
+#define PEFS_CFH_SIZE 16
+#define PEFS_FH_SIZE 16
+#define PEFS_BUCKET_SIZE 8
+
+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;
@@ -70,17 +87,20 @@
 	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;
 };
 
 struct hash_table {
 	struct bucket *buckets;
-	uint32_t size;
+	uint32_t size; /* how many buckets */
+	uint32_t nelements;
 };
 
 static int
@@ -170,6 +190,7 @@
 	 * XXXgpf: needs optimization
 	 */
 	checksum_hash_tablep->size = nelements;
+	checksum_hash_tablep->nelements = nelements;
 	checksum_hash_tablep->buckets = malloc (nelements * sizeof(struct bucket));
 
 	if (checksum_hash_tablep->buckets == NULL) {
@@ -214,6 +235,7 @@
 		}
 
 	bucketp->nelements++;
+	/* XXXgpf: Turn them into void */
 	return (0);
 }
 
@@ -242,16 +264,17 @@
 	struct checksum *csp;
 	uint32_t i,j;
 
-	dprintf(("\n+++Printing Hash Table+++\n\n"));
+	printf("\n+++Printing Hash Table+++\n\n");
 	for (i = 0; i < checksum_hash_tablep->size; i++) {
-		dprintf(("\nbucket %d with elements: %u\n", i, checksum_hash_tablep->buckets[i].nelements));
+		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) {
-			dprintf(("\tpath=%s!\t id = %d!\tnhashes = %d\n", fhp->path, (int)fhp->file_id, fhp->nhashes));
+			//printf(("\tpath=%s!\t id = %d!\tnhashes = %d\n", fhp->path, (int)fhp->file_id, fhp->nhashes));
+			printf("\tid = %d!\tnhashes = %d\n", (int)fhp->file_id, fhp->nhashes);
 			TAILQ_FOREACH(csp, &(fhp->checksums), checksum_entries) {
-				dprintf(("\t\tdigest="));
+				printf("\t\tdigest=");
 				for (j = 0; j < hash_len; j++)
-					dprintf(("%02x", csp->hash[j]));
-				dprintf(("\n"));
+					printf("%02x", csp->hash[j]);
+				printf("\n");
 			}
 		}
 	}
@@ -386,11 +409,206 @@
 	return (error);
 }
 
+
+static int
+pefs_write_checksum_file_header(int fdout, struct checksum_file_header *cfhp)
+{
+	uint32_t bytes, hash_table_size;
+
+	cfhp->offset_to_hash_table = PEFS_CFH_SIZE;
+
+	bytes = write(fdout, &(cfhp->version), sizeof(cfhp->version));
+	if (bytes != sizeof(cfhp->version)) {
+		warn("error writing to .pefs.checksum");
+		return (PEFS_ERR_IO);
+	}
+
+	bytes = write(fdout, &(cfhp->reserved), sizeof(cfhp->reserved));
+	if (bytes != sizeof(cfhp->reserved)) {
+		warn("error writing to .pefs.checksum");
+		return (PEFS_ERR_IO);
+	}
+
+	bytes = write(fdout, &(cfhp->hash_len), sizeof(cfhp->hash_len));
+	if (bytes != sizeof(cfhp->hash_len)) {
+		warn("error writing to .pefs.checksum");
+		return (PEFS_ERR_IO);
+	}
+
+	bytes = write(fdout, cfhp->hash_algo, sizeof(cfhp->hash_algo));
+	if (bytes != sizeof(cfhp->hash_algo)) {
+		warn("error writing to .pefs.checksum");
+		return (PEFS_ERR_IO);
+	}
+
+	bytes = write(fdout, &(cfhp->offset_to_hash_table), sizeof(cfhp->offset_to_hash_table));
+	if (bytes != sizeof(cfhp->offset_to_hash_table)) {
+		warn("error writing to .pefs.checksum");
+		return (PEFS_ERR_IO);
+	}
+
+	hash_table_size = htole32(cfhp->hash_table_size);
+	bytes = write(fdout, &hash_table_size, sizeof(hash_table_size));
+	if (bytes != sizeof(hash_table_size)) {
+		warn("error writing to .pefs.checksum");
+		return (PEFS_ERR_IO);
+	}
+
+	return (0);
+}
+
+static int
+pefs_write_bucket(int fdout, struct bucket *bp, uint32_t *buckets_offset)
+{
+	uint32_t offset_to_chain, nelements;
+	int bytes;
+
+	offset_to_chain = htole32(bp->offset_to_chain);
+	bytes = pwrite(fdout, &offset_to_chain, sizeof(offset_to_chain), *buckets_offset);
+	if (bytes != sizeof(offset_to_chain)) {
+		warn("error writing to .pefs.checksum");
+		return (PEFS_ERR_IO);
+	}
+	(*buckets_offset)+= sizeof(offset_to_chain);
+
+	nelements = htole32(bp->nelements);
+	bytes = pwrite(fdout, &nelements, sizeof(nelements), *buckets_offset);
+	if (bytes != sizeof(nelements)) {
+		warn("error writing to .pefs.checksum");
+		return (PEFS_ERR_IO);
+	}
+	(*buckets_offset)+= sizeof(nelements);
+
+	return (0);
+}
+
+/*
+ * XXXgpf: [TODO] take a look at chained offsets
+ */
+static int
+pefs_write_file_header(int fdout, struct file_header *fhp, uint32_t *fh_offset)
+{
+	uint64_t file_id;
+	uint32_t nhashes, offset_to_checksums;
+	int bytes;
+
+	nhashes = htole32(fhp->nhashes);
+	bytes = pwrite(fdout, &nhashes, sizeof(nhashes), *fh_offset);
+	if (bytes != sizeof(nhashes)) {
+		warn("error writing to .pefs.checksum");
+		return (PEFS_ERR_IO);
+	}
+	(*fh_offset)+= sizeof(nhashes);
+
+	offset_to_checksums = htole32(fhp->offset_to_checksums);
+	bytes = pwrite(fdout, &offset_to_checksums, sizeof(offset_to_checksums), *fh_offset);
+	if (bytes != sizeof(offset_to_checksums)) {
+		warn("error writing to .pefs.checksum");
+		return (PEFS_ERR_IO);
+	}
+	(*fh_offset)+= sizeof(offset_to_checksums);
+
+	file_id = htole64(fhp->file_id);
+	bytes = pwrite(fdout, &file_id, sizeof(file_id), *fh_offset);
+	if (bytes != sizeof(file_id)) {
+		warn("error writing to .pefs.checksum");
+		return (PEFS_ERR_IO);
+	}
+	(*fh_offset)+= sizeof(file_id);
+
+	return (0);
+}
+
+static int
+pefs_write_hash(int fdout, struct checksum *csp, uint32_t *hashes_offset, uint8_t hash_len)
+{
+	int bytes;
+
+	bytes = pwrite(fdout, csp->hash, hash_len, *hashes_offset);
+	if (bytes != hash_len) {
+		warn("error writing to .pefs.checksum");
+		return (PEFS_ERR_IO);
+	}
+	(*hashes_offset)+= hash_len;
+
+	return (0);
+}
+
+/*
+ * All data member writes are done separately so as to avoid alignment problems.
+ * Writes are always in little endian byte order.
+ *
+ * TODO more comments about internal structure of file
+ */
+static int
+pefs_write_checksum_file(int fdout, struct checksum_file_header *cfhp, struct hash_table *chtp)
+{
+	struct bucket *bp;
+	struct checksum *csp;
+	struct file_header *fhp;
+	uint32_t i, buckets_offset, fh_offset, hashes_offset;
+	int error;
+
+	error = pefs_write_checksum_file_header(fdout, cfhp);
+	if (error != 0)
+		return (error);
+
+	/* this points to where the buckets start */
+	buckets_offset = cfhp->offset_to_hash_table;
+
+	/* this points to where the buckets stop and the file headers start */
+	fh_offset = buckets_offset;
+	fh_offset+= chtp->size * PEFS_BUCKET_SIZE;
+
+	/* this points to where the file headers stop and the checksums start */
+	hashes_offset = fh_offset;
+	hashes_offset+= chtp->nelements * PEFS_FH_SIZE;
+	if (hashes_offset % PEFS_HASH_BYTE_ALIGNMENT != 0)
+		hashes_offset+= PEFS_HASH_BYTE_ALIGNMENT - (hashes_offset % PEFS_HASH_BYTE_ALIGNMENT);
+
+	for (i = 0; i < chtp->size; i++) {
+		bp = &chtp->buckets[i];
+		bp->offset_to_chain = fh_offset;
+		error = pefs_write_bucket(fdout, bp, &buckets_offset);
+		if (error != 0)
+			return (error);
+
+		LIST_FOREACH(fhp, &(chtp->buckets[i].file_headers), bucket_entries) {
+			fhp->offset_to_checksums = hashes_offset;
+			error = pefs_write_file_header(fdout, fhp, &fh_offset);
+			if (error != 0)
+				return (error);
+
+			TAILQ_FOREACH(csp, &(fhp->checksums), checksum_entries) {
+				error = pefs_write_hash(fdout, csp, &hashes_offset, cfhp->hash_len);
+				if (error != 0)
+					return (error);
+			}
+		}
+	}
+
+	return (0);
+}
+
+static void
+pefs_init_checksum_file_header(struct checksum_file_header *cfhp, const char *algo,
+		uint8_t hash_len, struct hash_table *chtp)
+{
+	cfhp->hash_len = hash_len;
+	cfhp->hash_table_size = chtp->size;
+	cfhp->version = PEFS_CHECKSUM_FILE_VERSION;
+	strlcpy(cfhp->hash_algo, algo, sizeof(cfhp->hash_algo));
+}
+
+/*
+ * XXXgpf: [TODO] proper comment header, I am sleepy Z_Z
+ */
 int
 pefs_create_checksum_file(FILE *fpin, char *fsroot, const char *algo)
 {
 	char checksum_path[MAXPATHLEN];
 	struct hash_table checksum_hash_table;
+	struct checksum_file_header cfh;
 	const EVP_MD *md;
 	int error, fdout;
 	uint8_t hash_len;
@@ -416,9 +634,9 @@
 	if (error != 0)
 		goto out;
 
-	/* XXXgpf: [TODO] write the in memory db to .pefs.checksum */
-	/* man byteorder(9) */
-	/* error = pefs_write_checksum_file(&checksum_hash_table, fdout, ...); */
+	pefs_init_checksum_file_header(&cfh, algo, hash_len, &checksum_hash_table);
+
+	error = pefs_write_checksum_file(fdout, &cfh, &checksum_hash_table);
 
 out:
 	close(fdout);



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