socsvn commit: r236233 - soc2012/gpf/pefs_kmod/sbin/pefs
gpf at FreeBSD.org
gpf at FreeBSD.org
Wed May 23 21:04:11 UTC 2012
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);
More information about the svn-soc-all
mailing list