-# Makefile for shredcompare tools
+# Makefile for comparator tools
SOURCES = shredtree.c shredcompare.c main.c md5.c md5.h
CFLAGS=-g
-all: shredtree
+all: comparator
main.o: main.c shred.h
$(CC) -c $(CFLAGS) main.c
$(CC) -c $(CFLAGS) shredtree.c
shredcompare.o: shredcompare.c shred.h
$(CC) -c $(CFLAGS) shredcompare.c
-shredtree: main.o shredtree.o md5.o shredcompare.o
- $(CC) main.o shredtree.o md5.o shredcompare.o -o shredtree
+comparator: main.o shredtree.o md5.o shredcompare.o
+ $(CC) main.o shredtree.o md5.o shredcompare.o -o comparator
clean:
- rm -f shredtree shredcompare shredtree.o md5.o shredcompare.o TEST1 TEST2
-
-test-a: shredtree
- shredtree -f -c test1 >TEST1
- shredtree -f -c test2 >TEST2
- shredtree TEST1 TEST2
-test-b: shredtree
- shredtree -f -c test3 >TEST1
- shredtree -f -c test4 >TEST2
- shredtree TEST1 TEST2
-
-goodtest: shredtree
- shredtree -f -c -d ~/src/unix src5r4/src/ucbhead >src5r4.shif
- shredtree -f -c -d ~/src/unix linux-2.6.0-test4/include/linux >linux-2.6.0-test4.shif
- shredtree src5r4.shif linux-2.6.0-test4.shif
-
-bigtest: shredtree
- shredtree -f -c -d ~/src/unix src5r4 >src5r4.shif
- shredtree -f -c -d ~/src/unix linux-2.6.0-test4 >linux-2.6.0-test4.shif
- shredtree src5r4.shif linux-2.6.0-test4.shif >TEST.LOG
+ rm -f comparator shredtree.o md5.o shredcompare.o TEST1 TEST2
+
+test-a: comparator
+ comparator -f -c test1 >TEST1
+ comparator -f -c test2 >TEST2
+ comparator TEST1 TEST2
+test-b: comparator
+ comparator -f -c test3 >TEST1
+ comparator -f -c test4 >TEST2
+ comparator TEST1 TEST2
+
+goodtest: comparator
+ comparator -f -c -d ~/src/unix src5r4/src/ucbhead >src5r4.shif
+ comparator -f -c -d ~/src/unix linux-2.6.0-test4/include/linux >linux-2.6.0-test4.shif
+ comparator src5r4.shif linux-2.6.0-test4.shif
+
+bigtest: comparator
+ comparator -f -c -d ~/src/unix src5r4 >src5r4.shif
+ comparator -f -c -d ~/src/unix linux-2.6.0-test4 >linux-2.6.0-test4.shif
+ comparator src5r4.shif linux-2.6.0-test4.shif >TEST.LOG
int debug = 0;
int shredsize = 5;
-/* globally visible data; chunk_buffer should be a malloc area set by the caller */
-int file_count, chunk_count;
+/* globally visible data */
+int file_count, chunk_count, sort_count;
struct hash_t *chunk_buffer;
+struct sorthash_t *sort_buffer;
struct item
{
}
shred;
-static void emit_chunk(shred *display, int linecount)
-/* emit chunk corresponding to current display; modifies globals chunk_buffer and chunk_count */
+static struct hash_t emit_chunk(shred *display, int linecount)
+/* emit chunk corresponding to current display */
{
struct md5_ctx ctx;
int i, firstline;
unsigned char *cp;
+ struct hash_t out;
if (debug)
{
}
}
- chunk_buffer = (struct hash_t *)realloc(chunk_buffer,
- sizeof(struct hash_t) * (chunk_count+1));
-
/* build completed chunk onto end of array */
md5_init_ctx(&ctx);
for (i = 0; i < shredsize; i++)
if (display[i].line)
md5_process_bytes(display[i].line, strlen(display[i].line), &ctx);
- md5_finish_ctx(&ctx, (void *)&chunk_buffer[chunk_count].hash);
+ md5_finish_ctx(&ctx, (void *)&out.hash);
for (i = shredsize - 1; i >= 0; i--)
if (display[i].line)
firstline = i;
firstline = display[firstline].number;
- chunk_buffer[chunk_count].start = TONET(firstline);
- chunk_buffer[chunk_count].end = TONET(linecount);
- chunk_count++;
+ out.start = TONET(firstline);
+ out.end = TONET(linecount);
+
+ return(out);
+}
+
+/*
+ * We differentiate these two functions in order to avaid the memory
+ * overhead of the extra (char *) when assembling shred lists to be written
+ * to a file. This is only worth bothering with because the data sets
+ * can get quite large.
+ */
+
+static void filehook(struct hash_t hash, const char *file)
+/* hook to store only hashes */
+{
+ chunk_buffer = (struct hash_t *)realloc(chunk_buffer,
+ sizeof(struct hash_t) * (chunk_count+1));
+
+ chunk_buffer[chunk_count++] = hash;
+}
+
+
+static void corehook(struct hash_t hash, const char *file)
+/* hook to store hash and file */
+{
+ sort_buffer = (struct sorthash_t *)realloc(sort_buffer,
+ sizeof(struct sorthash_t) * (sort_count+1));
+
+ sort_buffer[sort_count].hash = hash;
+ sort_buffer[sort_count].file = (char *)file;
+ sort_count++;
}
-static void shredfile(const char *file)
-/* emit hash section for specified file; modifies globals chunk_buffer and chunk_count */
+
+static void shredfile(const char *file,
+ void (*hook)(struct hash_t, const char *))
+/* emit hash section for specified file */
{
FILE *fp;
char buf[BUFSIZ];
/* flush completed chunk */
if (accepted >= shredsize)
- emit_chunk(display, linecount);
+ hook(emit_chunk(display, linecount), file);
/* shreds in progress are shifted down */
free(display[0].line);
display[shredsize-1].line = NULL;
}
if (linecount < shredsize)
- emit_chunk(display, linecount);
+ hook(emit_chunk(display, linecount), file);
free(display);
fclose(fp);
return strcmp(*(char **)a, *(char **)b);
}
-void generate_shredfile(const char *tree, FILE *ofp)
-/* generate shred file for given tree */
+static char **sorted_file_list(const char *tree)
+/* generate a sorted list of files under the given tree */
{
char **place, **list;
- u_int32_t netfile_count;
-
- fputs("#SHIF-A 1.0\n", ofp);
- fputs("Generator-Program: shredtree 1.0\n", ofp);
- fputs("Hash-Method: MD5\n", ofp);
- fprintf(ofp, "Normalization: %s\n", rws ? "remove_whitespace" : "none");
- fprintf(ofp, "Shred-Size: %d\n", shredsize);
- fputs("%%\n", ofp);
/* make file list */
ftw(tree, treewalker, 16);
/* the objective -- sort */
qsort(list, file_count, sizeof(char *), stringsort);
+}
+
+void generate_shredfile(const char *tree, FILE *ofp)
+/* generate shred file for given tree */
+{
+ char **place, **list;
+ u_int32_t netfile_count;
+
+ list = sorted_file_list(tree);
+
+ fputs("#SHIF-A 1.0\n", ofp);
+ fputs("Generator-Program: shredtree 1.0\n", ofp);
+ fputs("Hash-Method: MD5\n", ofp);
+ fprintf(ofp, "Normalization: %s\n", rws ? "remove_whitespace" : "none");
+ fprintf(ofp, "Shred-Size: %d\n", shredsize);
+ fputs("%%\n", ofp);
- /* generate the list */
netfile_count = htonl(file_count);
fwrite(&netfile_count, sizeof(u_int32_t), 1, ofp);
for (place = list; place < list + file_count; place++)
/* shredfile adds data to chunk_buffer */
chunk_buffer = (struct hash_t *)calloc(sizeof(struct hash_t), 1);
chunk_count = 0;
- shredfile(*place);
+ shredfile(*place, filehook);
/* the actual output */
fputs(*place, ofp);
}
}
+struct sorthash_t *generate_shredlist(const char *tree)
+/* generate an in-core list of sorthash structures */
+{
+ char **place, **list;
+
+ sort_buffer = (struct sorthash_t*)calloc(sizeof(struct sorthash_t),1);
+ sort_count = 0;
+
+ list = sorted_file_list(tree);
+ for (place = list; place < list + file_count; place++)
+ shredfile(*place, corehook);
+
+ /* caller is responsible for freeing this */
+ return(sort_buffer);
+}
+
/* shredtree.c ends here */