hw2/Makefile CC := gcc SRCD := src TSTD := tests BLDD := build BIND := bin INCD := include MAIN := $(BLDD)/main.o ALL_SRCF := $(shell find $(SRCD) -type f -name *.c) ALL_OBJF := $(patsubst...

s


hw2/Makefile CC := gcc SRCD := src TSTD := tests BLDD := build BIND := bin INCD := include MAIN := $(BLDD)/main.o ALL_SRCF := $(shell find $(SRCD) -type f -name *.c) ALL_OBJF := $(patsubst $(SRCD)/%,$(BLDD)/%,$(ALL_SRCF:.c=.o)) ALL_FUNCF := $(filter-out $(MAIN) $(AUX), $(ALL_OBJF)) TEST_SRC := $(shell find $(TSTD) -type f -name *.c) INC := -I $(INCD) CFLAGS := -Wall -Werror -Wno-unused-variable -Wno-unused-function -MMD COLORF := -DCOLOR DFLAGS := -g -DDEBUG -DCOLOR PRINT_STAMENTS := -DERROR -DSUCCESS -DWARN -DINFO STD := -std=gnu11 TEST_LIB := -lcriterion LIBS := CFLAGS += $(STD) $(OPTIONS) EXEC := finddup TEST_EXEC := $(EXEC)_tests .PHONY: clean all setup debug all: setup $(BIND)/$(EXEC) $(BIND)/$(TEST_EXEC) debug: CFLAGS += $(DFLAGS) $(PRINT_STAMENTS) $(COLORF) debug: all setup: $(BIND) $(BLDD) $(BIND): mkdir -p $(BIND) $(BLDD): mkdir -p $(BLDD) $(BIND)/$(EXEC): $(ALL_OBJF) $(CC) $^ -o $@ $(LIBS) $(BIND)/$(TEST_EXEC): $(ALL_FUNCF) $(TEST_SRC) $(CC) $(CFLAGS) $(INC) $(ALL_FUNCF) $(TEST_SRC) $(TEST_LIB) $(LIBS) -o $@ $(BLDD)/%.o: $(SRCD)/%.c $(CC) $(CFLAGS) $(INC) -c -o $@ $< clean:="" rm="" -rf="" $(bldd)="" $(bind)="" .precious:="" $(bldd)/*.d="" -include="" $(bldd)/*.d="" hw2/tests/rsrc/larger_test_names="" tests/rsrc/test_tree/file2="" tests/rsrc/test_tree/binary1="" tests/rsrc/test_tree/subdir2/file2="" tests/rsrc/test_tree/file1="" tests/rsrc/test_tree/file2.dup1="" tests/rsrc/test_tree/subdir1/file1="" tests/rsrc/test_tree/file1.dup="" tests/rsrc/test_tree/nonexistent="" tests/rsrc/test_tree/file1.lnk="" tests/rsrc/test_tree/file2.dup2="" tests/rsrc/test_tree/binary2="" tests/rsrc/test_tree/empty1="" tests/rsrc/test_tree/file2.lnk="" tests/rsrc/test_tree/empty="" hw2/tests/rsrc/valgrind_uninitialized_test.out="" list="" of="" files="" with="" duplicate="" contents="" (includes="" hard="" links)="" file:="" tests/rsrc/test_tree/file1="" dup:="" tests/rsrc/test_tree/file1.dup="" hw2/tests/rsrc/test_tree/subdir1/file1="" this="" is="" file="" content="" 1="" hw2/tests/rsrc/binary_test_names="" tests/rsrc/test_tree/binary1="" tests/rsrc/test_tree/binary2="" hw2/tests/rsrc/test_tree/subdir2/file2="" this="" is="" file="" content="" 2="" hw2/tests/rsrc/test_tree/file1.lnk="" this="" is="" file="" content="" 1="" hw2/doc/finddup.1c="" .th="" finddup="" 1="" local="" .sh="" name="" finddup="" -="" find="" duplicate="" files="" in="" a="" list="" .sh="" synopsis="" finddup="" [options]="" filename="" .sh="" description="" .ds="" fd="" \fbfinddup\fp="" \*(fd="" reads="" a="" list="" of="" filenames="" from="" the="" named="" file="" and="" scans="" them,="" building="" a="" list="" of="" duplicate="" files="" and="" hard="" links.="" these="" are="" then="" written="" to="" stdout="" for="" the="" user's="" information.="" this="" can="" be="" used="" to="" reduce="" disk="" usage,="" etc.="" .ss="" options="" -l="" -="" don't="" show="" info="" on="" hard="" links="" -d="" -="" debug.="" may="" be="" used="" more="" than="" once="" for="" more="" info="" .ss="" how="" it="" works="" \*(fd="" stats="" each="" name="" and="" saves="" the="" file="" length,="" device,="" and="" inode.="" it="" then="" sorts="" the="" list="" and="" builds="" a="" crc="" for="" each="" file="" which="" has="" the="" same="" length="" as="" another="" file.="" for="" files="" which="" have="" the="" same="" length="" and="" crc,="" a="" byte="" by="" byte="" comparison="" is="" done="" to="" be="" sure="" that="" they="" are="" duplicates.="" .sp="" the="" crc="" step="" for="" n="" files="" of="" size="" s="" bytes="" requires="" reading="" n*s="" total="" bytes,="" while="" the="" byte="" by="" byte="" check="" must="" be="" done="" for="" every="" file="" against="" every="" other,="" and="" read="" s*n*(n-1)="" bytes.="" thus="" the="" crc="" is="" a="" large="" timesaver="" in="" most="" cases.="" .sh="" examples="" $="" find="" u="" -type="" f="" -print=""> file.list.tmp $ finddup file.list.tmp .SH FILES Only the file with the filenames. .SH SEE ALSO find(1). .SH DIAGNOSTICS If files are named in the specification file but not present they will be ignored. If an existing file can not be read the program will terminate rather than generate an incomplete list of duplicates. .SH LIMITATIONS An option to generate a partial list could be added when a file can't be accessed. An option to list only duplites which are not hard links could be added. .SH AUTHOR Bill Davidsen, [email protected] .SH Copyright Copyright (c) 1991 by Bill Davidsen, all rights reserved. This program may be freely used and distributed in its original form. Modified versions must be distributed with the original unmodified source code, and redistribution of the original code or any derivative program may not be restricted. hw2/tests/hw2_tests.c #include #include #include #include #define TEST_TIMEOUT 15 #define TEST_REF_DIR "tests/rsrc" #define TEST_OUTPUT_DIR "tests.out" extern int errors, warnings; static char program_options[500]; static char test_output_subdir[100]; static char test_log_outfile[100]; /* * Sets up to run a test. * Initialize various filenames, using the name of the test as a base, * and then initialize and run a command to remove old output from this test * and to make sure that the test output directory exists. */ int setup_test(char *name) { char cmd[500]; sprintf(test_log_outfile, "%s/%s", TEST_OUTPUT_DIR, name); sprintf(test_output_subdir, "%s/%s", TEST_OUTPUT_DIR, name); sprintf(cmd, "rm -f %s.out %s.err; rm -fr %s; mkdir -p %s", test_log_outfile, test_log_outfile, test_output_subdir, test_output_subdir); fprintf(stderr, "setup(%s)\n", cmd); return system(cmd); } /* * Run the program as a "black box" using system(). * A shell command is constructed and run that first performs test setup, * then runs the program to be tested with input redirected from a test input file * and standard and error output redirected to separate output files. */ int run_using_system(char *name, char *pre_cmd, char *valgrind_cmd) { char cmd[500]; setup_test(name); sprintf(cmd, "%s%s bin/finddup %s > %s.out 2> %s.err", pre_cmd, valgrind_cmd, program_options, test_log_outfile, test_log_outfile); fprintf(stderr, "run(%s)\n", cmd); return system(cmd); } void assert_normal_exit(int status) { cr_assert_eq(status, 0, "The program did not exit normally (status = 0x%x).\n", status); } void assert_error_exit(int status) { cr_assert_eq(WEXITSTATUS(status), 0xff, "The program did not exit with status 0xff (status was 0x%x).\n", status); } /* * Compare the standard output from the program being tested with reference output, * after first possibly using "grep" to remove lines that match a filter pattern. */ void assert_outfile_matches(char *name, char *filter) { char cmd[500]; if(filter) { sprintf(cmd, "grep -v '%s' %s.out > %s_A.out; grep -v '%s' %s/%s.out > %s_B.out; " "diff --ignore-tab-expansion --ignore-trailing-space --ignore-space-change --ignore-blank-lines %s_A.out %s_B.out", filter, test_log_outfile, name, filter, TEST_REF_DIR, name, name, name, name); } else { sprintf(cmd, "diff --ignore-tab-expansion --ignore-trailing-space --ignore-space-change --ignore-blank-lines %s.out %s/%s.out", test_log_outfile, TEST_REF_DIR, name); } int err = system(cmd); cr_assert_eq(err, 0, "The output was not what was expected (diff exited with status %d).\n", WEXITSTATUS(err)); } /* * Compare the standard error output from the program being tested with reference output, * after first possibly using "grep" to remove lines that match a filter pattern. */ void assert_errfile_matches(char *name, char *filter) { char cmd[500]; if(filter) { sprintf(cmd, "grep -v '%s' %s.err > %s_A.err; grep -v '%s' %s/%s.err > %s_B.err; " "diff ---ignore-tab-expansion --ignore-trailing-space --ignore-space-change --ignore-blank-lines %s_A.err %s_B.err", filter, test_log_outfile, name, filter, TEST_REF_DIR, name, name, name, name); } else { sprintf(cmd, "diff --ignore-tab-expansion --ignore-trailing-space --ignore-space-change --ignore-blank-lines %s.err %s/%s.err", test_log_outfile, TEST_REF_DIR, name); } int err = system(cmd); cr_assert_eq(err, 0, "The output was not what was expected (diff exited with status %d).\n", WEXITSTATUS(err)); } void assert_no_valgrind_errors(int status) { cr_assert_neq(WEXITSTATUS(status), 37, "Valgrind reported errors -- see %s.err", test_log_outfile); } /* * Tests the basic program operation. */ Test(base_suite, quick_test) { char *name = "quick_test"; sprintf(program_options, "tests/rsrc/quick_test_names"); int err = run_using_system(name, "", ""); assert_normal_exit(err); assert_outfile_matches(name, NULL); assert_errfile_matches(name, NULL); } /* * This test sets up a test tree that contains "hard links" to the same file. * These should be correctly identified as such by the program. */ Test(base_suite, hard_links_test) { char *name = "hard_links_test"; system("rm -f tests/rsrc/test_tree/file1.lnk tests/rsrc/test_tree/file2.lnk; " "ln tests/rsrc/test_tree/file1 tests/rsrc/test_tree/file1.lnk; " "ln tests/rsrc/test_tree/file2 tests/rsrc/test_tree/file2.lnk"); sprintf(program_options, "tests/rsrc/hard_links_test_names"); int err = run_using_system(name, "", ""); assert_normal_exit(err); assert_outfile_matches(name, NULL); assert_errfile_matches(name, NULL); } /* * Tests correct behavior of the program on binary files. */ Test(base_suite, binary_test) { char *name = "binary_test"; sprintf(program_options, "tests/rsrc/binary_test_names"); int err = run_using_system(name, "", ""); assert_normal_exit(err); assert_outfile_matches(name, NULL); assert_errfile_matches(name, NULL); } /* * Tests the basic program operation with a larger set of files, containing * examples of various types of potential issues. */ Test(base_suite, larger_test) { char *name = "larger_test"; sprintf(program_options, "tests/rsrc/larger_test_names"); int err = run_using_system(name, "", ""); assert_normal_exit(err); assert_outfile_matches(name, NULL); assert_errfile_matches(name, NULL); } /* * This test runs valgrind to check for the use of uninitialized variables. */ Test(base_suite, valgrind_uninitialized_test) { char *name = "valgrind_uninitialized_test"; sprintf(program_options, "tests/rsrc/quick_test_names"); int err = run_using_system(name, "", "valgrind --leak-check=no --undef-value-errors=yes --error-exitcode=37"); assert_no_valgrind_errors(err); assert_normal_exit(err); assert_outfile_matches(name, NULL); } /* * This test runs valgrind to check for memory leaks. */ Test(base_suite, valgrind_leak_test) { char *name = "valgrind_leak_test"; sprintf(program_options, "tests/rsrc/quick_test_names"); int err = run_using_system(name, "", "valgrind --leak-check=full --undef-value-errors=no --error-exitcode=37"); assert_no_valgrind_errors(err); assert_normal_exit(err); assert_outfile_matches(name, NULL); } hw2/tests/rsrc/test_tree/file2 This is file content 2 hw2/tests/rsrc/quick_test_names tests/rsrc/test_tree/file1 tests/rsrc/test_tree/file1.dup tests/rsrc/test_tree/file2 hw2/src/crc32.c /* * DO NOT MODIFY THE CONTENTS OF THIS FILE. * IT WILL BE REPLACED DURING GRADING */ #include #include #include // Derived from https://rosettacode.org/wiki/CRC-32#Library uint32_t rc_crc32(uint32_t crc, const char *buf, size_t len) { static uint32_t table[256]; static int have_table = 0; uint32_t rem; uint8_t octet; int i, j; const char *p, *q; /* This check is not thread safe; there is no mutex. */ if (have_table == 0) { /* Calculate CRC table. */ for (i = 0; i < 256;="" i++)="" {="" rem="i;" *="" remainder="" from="" polynomial="" division="" */="" for="" (j="0;" j="">< 8;="" j++)="" {="" if="" (rem="" &="" 1)="" {="" rem="">>= 1; rem ^= 0xedb88320; } else rem >>= 1; } table[i] = rem; } have_table = 1; } crc
Sep 21, 2021
SOLUTION.PDF

Get Answer To This Question

Related Questions & Answers

More Questions »

Submit New Assignment

Copy and Paste Your Assignment Here