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>