unix C code

profileSixGoddess
assign3-starter.tgz

assign3/cmpsc311_hashtable.h

#ifndef CMPSC311_HASHTABLE_INCLUDED #define CMPSC311_HASHTABLE_INCLUDED //////////////////////////////////////////////////////////////////////////////// // // File : cmpsc311_hashtable.h // Description : This is a generic hashtable implementation used for // data structure storage and access. //// // Author : Patrick McDaniel // Created : Sun Feb 5 08:56:10 EDT 2017 // // Includes #include <stdint.h> // Defines #define HT_COOKIE_VALUE 0xa3a3 typedef unsigned long HtIndexValue; // Hash table entry structure typedef struct HtEntry { uint16_t cookie; // This is a cookie value to detect memory corruption HtIndexValue index; // This is the "key value" index of the object void *block; // This is the data block of the stored item struct HtEntry *prev; // This is the previous item in the local chain struct HtEntry *next; // This is the next item in the local chain } HtEntryData; // Hash table structure typedef struct { uint16_t htTableSize; // The the bits in the hash values HtEntryData **hasHTable; // This is the hash table itself } HTable; // Hash table iterator typedef struct { HTable *table; // The table we are iterating through uint16_t idx; // The current index into the hash table HtEntryData *ptr; // The pointer into the linked list at the index } HtIterator; // // Hashtable Interface int initHasHTable( HTable *ht, uint16_t bits ); // This function initializes the hash table to a width of 2^(bits) width int cleanupHasHTable( HTable *ht ); // Cleanup the hash table int insertValueInHasHTable( HTable *ht, HtIndexValue idx, void *blk ); // Insert a value into the hashtable of value idx, block size blk void * findValueInHasHTable( HTable *ht, HtIndexValue idx ); // Find a block for a particular index value in the table void * deleteValueFromHasHTable( HTable *ht, HtIndexValue idx ); // Delete a value from the hashtable of value idx, return it // // Iterator Functions int initHasHTableIterator( HTable *ht, HtIterator *it ); // Initialize the iterator void * iterateHasHTable( HtIterator *it ); // Iterate through the hash table (pass NULL to start at beginning), // returns the next value in the table // // Unit Testing int hashTableUnitTest( void ); // Perform a test of the hash table functionality #endif

assign3/crud_file_io.h

#ifndef CRUD_FILE_IO_INCLUDED #define CRUD_FILE_IO_INCLUDED //////////////////////////////////////////////////////////////////////////////// // // File : crud_file_io.h // Description : This is the header file for the standardized IO functions // for used to access the CRUD storage system. // // Author : Patrick McDaniel // Last Modified : Tue Sep 16 19:38:42 EDT 2014 // // Include files #include <stdint.h> // // Interface functions int16_t crud_open(char *path); // This function opens the file and returns a file handle int16_t crud_close(int16_t fd); // This function closes the file int32_t crud_read(int16_t fd, void *buf, int32_t count); // Reads "count" bytes from the file handle "fh" into the buffer "buf" int32_t crud_write(int16_t fd, void *buf, int32_t count); // Writes "count" bytes to the file handle "fh" from the buffer "buf" int32_t crud_seek(int16_t fd, uint32_t loc); // Seek to specific point in the file // // Unit testing for the module int crudIOUnitTest(void); // Perform a test of the CRUD IO implementation #endif

assign3/Makefile

# # CMPSC311 - Spring 2017 # Assignment #3 Makeeil # # # Variables ARCHIVE=ar CC=gcc LINK=gcc CFLAGS=-c -Wall -I. -fpic -g LINKFLAGS=-L. -g LIBFLAGS=-shared -Wall LINKLIBS=-lcrud -lgcrypt DEPFILE=Makefile.dep # Files to build CRUD_SIM_OBJFILES= crud_sim.o \ crud_file_io.o TARGETS= crud_sim # Suffix rules .SUFFIXES: .c .o .c.o: $(CC) $(CFLAGS) -o $@ $< # Productions all : $(TARGETS) crud_sim : $(CRUD_SIM_OBJFILES) libcrud.a $(LINK) $(LINKFLAGS) -o $@ $(CRUD_SIM_OBJFILES) $(LINKLIBS) # Do dependency generation depend : $(DEPFILE) $(DEPFILE) : $(CRUD_SIM_OBJFILES:.o=.c) gcc -MM $(CFLAGS) $(CRUD_SIM_OBJFILES:.o=.c) > $(DEPFILE) # Cleanup clean: rm -f $(TARGETS) $(CRUD_SIM_OBJFILES) # Dependancies

assign3/cmpsc311_log.h

#ifndef CMPSC311_LOG_INCLUDED #define CMPSC311_LOG_INCLUDED //////////////////////////////////////////////////////////////////////////////// // // File : cmpsc311_log.h // Description : This is the logging service for the CMPSC311 utility // library. It provides access enable log events, // whose levels are registered by the calling programs. // // Note: The log process works on a bit-vector of levels, and all // functions operate on bit masks of levels (lvl). Log entries are // given a level which is checked at run-time. If the log level is // enabled, then the entry it written to the log, and not otherwise. // // Author : Patrick McDaniel // Created : Sun Sep 05 10:19:45 EDT 2017 // // Include files #include <stdio.h> #include <stdarg.h> // // Library Constants #define LOG_SERVICE_NAME "cmpsc311.log" // Default log levels #define LOG_ERROR_LEVEL 1 #define LOG_ERROR_LEVEL_DESC "ERROR" #define LOG_WARNING_LEVEL 2 #define LOG_WARNING_LEVEL_DESC "WARNING" #define LOG_INFO_LEVEL 4 #define LOG_INFO_LEVEL_DESC "INFO" #define LOG_OUTPUT_LEVEL 8 #define LOG_OUTPUT_LEVEL_DESC "OUTPUT" #define MAX_RESERVE_LEVEL LOG_INFO_LEVEL #define MAX_LOG_LEVEL 32 #define DEFAULT_LOG_LEVEL LOG_ERROR_LEVEL|LOG_WARNING_LEVEL|LOG_OUTPUT_LEVEL #define MAX_LOG_MESSAGE_SIZE 1024 #define CMPSC311_LOG_STDOUT 1 #define CMPSC311_LOG_STDERR 2 // // Interface // // Basic logging interfaces unsigned long registerLogLevel( const char *descriptor, int enable ); // Register a new log level void enableLogLevels( unsigned long lvl ); // Turn on different log levels void disableLogLevels( unsigned long lvl ); // Turn off different log levels int levelEnabled( unsigned long lvl ); // Are any of the log levels turned on? void setEchoDescriptor( int eh ); // Set a file handle to echo content to int initializeLogWithFilename( const char *logname ); // Create a log with a given filename int initializeLogWithFilehandle( int out ); // Create a log with a fixed file handle // // Logging functions int logMessage( unsigned long lvl, const char *fmt, ...); // Log a "printf"-style message int vlogMessage( unsigned long lvl, const char *fmt, va_list args ); // Log call the vararg list version // // Assert functions #define CMPSC_ASSERT0(expr,x) logAssert(expr, __FILE__, __LINE__, x); #define CMPSC_ASSERT1(expr,x,y) logAssert(expr, __FILE__, __LINE__, x, y); #define CMPSC_ASSERT2(expr,x,y,z) logAssert(expr, __FILE__, __LINE__, x, y, z); int logAssert( int expr, const char *file, int line, const char *fmt, ...); // Log a "printf"-style message where ASSERT fails #endif

assign3/crud_file_io.o

assign3/libcrud.a

crud_driver.o

cmpsc311_log.o

cmpsc311_util.o

cmpsc311_hashtable.o

assign3/cmpsc311_util.h

#ifndef CMPSC311_UTIL_INCLUDED #define CMPSC311_UTIL_INCLUDED //////////////////////////////////////////////////////////////////////////////// // // File : cmpsc311_util.h // Description : This is a set of general-purpose utility functions we use // for the 311 homework assignments. // // Author : Patrick McDaniel // Created : Sat Sep 21 06:47:40 EDT 2013 // // Change Log: // // 10/11/13 Added the timer comparison function definition (PDM) // // Includes #include <stdint.h> #include <gcrypt.h> // Defines #define CMPSC311_HASH_TYPE GCRY_MD_SHA1 #define CMPSC311_HASH_LENGTH (gcry_md_get_algo_dlen(CMPSC311_HASH_TYPE)) // Functional prototypes int generate_md5_signature( unsigned char *buf, uint32_t size, unsigned char *sig, uint32_t *sigsz ); // Generate MD5 signature from buffer int bufToString( unsigned char *buf, uint32_t blen, unsigned char *str, uint32_t slen ); // Convert the buffer into a readable hex string uint32_t getRandomValue( uint32_t min, uint32_t max ); // Using strong randomness, generate random number long compareTimes( struct timeval * tm1, struct timeval * tm2 ); // Compare two timer values #endif

assign3/crud_sim.c

//////////////////////////////////////////////////////////////////////////////// // // File : crudsim.c // Description : This is the main program for the CMPSC311 programming // assignment #3 (beginning of CRUD interface). // // Author : Patrick McDaniel // Last Modified : Sun Feb 05 07:13:21 EDT 2017 // // Include Files #include <stdio.h> #include <stdint.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> // Project Includes #include <crud_driver.h> #include <crud_file_io.h> #include <cmpsc311_log.h> #include <cmpsc311_util.h> #include <cmpsc311_hashtable.h> // Defines #define CRUD_ARGUMENTS "hvul:" #define USAGE \ "USAGE: crud [-h] [-v] [-l <logfile>] [-c <sz>] <workload-file>\n" \ "\n" \ "where:\n" \ " -h - help mode (display this message)\n" \ " -u - run the unit tests instead of the simulator\n" \ " -v - verbose output\n" \ " -l - write log messages to the filename <logfile>\n" \ "\n" \ " <workload-file> - file contain the workload to simulate\n" \ "\n" \ // // Functions //////////////////////////////////////////////////////////////////////////////// // // Function : main // Description : The main function for the CRUD simulator // // Inputs : argc - the number of command line parameters // argv - the parameters // Outputs : 0 if successful test, -1 if failure int main( int argc, char *argv[] ) { // Local variables int ch, verbose = 0, unit_tests = -0, log_initialized = 0; uint32_t cache_size = 1024; // Defaults to 1024 cache lines // Process the command line parameters while ((ch = getopt(argc, argv, CRUD_ARGUMENTS)) != -1) { switch (ch) { case 'h': // Help, print usage fprintf( stderr, USAGE ); return( -1 ); case 'v': // Verbose Flag verbose = 1; break; case 'u': // Unit Tests Flag unit_tests = 1; break; case 'l': // Set the log filename initializeLogWithFilename( optarg ); log_initialized = 1; break; case 'c': // Set cache line size if ( sscanf( optarg, "%u", &cache_size ) != 1 ) { logMessage( LOG_ERROR_LEVEL, "Bad cache size [%s]", argv[optind] ); } break; default: // Default (unknown) fprintf( stderr, "Unknown command line option (%c), aborting.\n", ch ); return( -1 ); } } // Setup the log as needed if ( ! log_initialized ) { initializeLogWithFilehandle( CMPSC311_LOG_STDERR ); } if ( verbose ) { enableLogLevels( LOG_INFO_LEVEL ); } // If we are running the unit tests, do that if ( unit_tests ) { // Enable verbose, run the tests and check the results if ( crudIOUnitTest() ) { logMessage( LOG_ERROR_LEVEL, "CRUD unit tests failed.\n\n" ); } else { logMessage( LOG_INFO_LEVEL, "CRUD unit tests completed successfully.\n\n" ); } } else { // The filename should be the next option if ( optind >= argc ) { // No filename fprintf( stderr, "Missing command line parameters, use -h to see usage, aborting.\n" ); return( -1 ); } // Run the simulation logMessage( LOG_INFO_LEVEL, "CRUD simulation not used for this assignment [PLEASE RUN UNIT TEST] .\n\n" ); } // Return successfully return( 0 ); }

assign3/crud_file_io.c

//////////////////////////////////////////////////////////////////////////////// // // File : crud_file_io.h // Description : This is the implementation of the standardized IO functions // for used to access the CRUD storage system. // // Author : Patrick McDaniel // Last Modified : Sun Feb 05 19:38:42 EDT 2017 // // Includes #include <malloc.h> #include <string.h> // Project Includes #include <crud_file_io.h> #include <crud_driver.h> #include <cmpsc311_log.h> #include <cmpsc311_util.h> // // Defines #define CIO_UNIT_TEST_MAX_WRITE_SIZE 1024 #define CRUD_IO_UNIT_TEST_ITERATIONS 10240 // Type for UNIT test interface typedef enum { CIO_UNIT_TEST_READ = 0, CIO_UNIT_TEST_WRITE = 1, CIO_UNIT_TEST_APPEND = 2, CIO_UNIT_TEST_SEEK = 3, } CRUD_UNIT_TEST_TYPE; // // Implementation //////////////////////////////////////////////////////////////////////////////// // // Function : crud_open // Description : This function opens the file and returns a file handle // // Inputs : path - the path "in the storage array" // Outputs : file handle if successful, -1 if failure int16_t crud_open(char *path) { } //////////////////////////////////////////////////////////////////////////////// // // Function : crud_close // Description : This function closes the file // // Inputs : fd - the file handle of the object to close // Outputs : 0 if successful, -1 if failure int16_t crud_close(int16_t fh) { } //////////////////////////////////////////////////////////////////////////////// // // Function : crud_read // Description : Reads up to "count" bytes from the file handle "fh" into the // buffer "buf". // // Inputs : fd - the file descriptor for the read // buf - the buffer to place the bytes into // count - the number of bytes to read // Outputs : the number of bytes read or -1 if failures int32_t crud_read(int16_t fd, void *buf, int32_t count) { } ////////////////////////////////////////////////////////////////////////////////////////// // // Function : crud_write // Description : Writes "count" bytes to the file handle "fh" from the // buffer "buf" // // Inputs : fd - the file descriptor for the file to write to // buf - the buffer to write // count - the number of bytes to write // Outputs : the number of bytes written or -1 if failure int32_t crud_write(int16_t fd, void *buf, int32_t count) { } //////////////////////////////////////////////////////////////////////////////// // // Function : crud_seek // Description : Seek to specific point in the file // // Inputs : fd - the file descriptor for the file to seek // loc - offset from beginning of file to seek to // Outputs : 0 if successful or -1 if failure int32_t crud_seek(int16_t fd, uint32_t loc) { } // // Unit Test Function //////////////////////////////////////////////////////////////////////////////// // // Function : crudIOUnitTest // Description : Perform a test of the CRUD IO implementation // // Inputs : None // Outputs : 0 if successful or -1 if failure int crudIOUnitTest(void) { // Local variables uint8_t ch; int16_t fh, i; int32_t cio_utest_length, cio_utest_position, count, bytes, expected; char *cio_utest_buffer, *tbuf; CRUD_UNIT_TEST_TYPE cmd; char lstr[1024]; // Setup some operating buffers, zero out the mirrored file contents cio_utest_buffer = malloc(CRUD_MAX_OBJECT_SIZE); tbuf = malloc(CRUD_MAX_OBJECT_SIZE); memset(cio_utest_buffer, 0x0, CRUD_MAX_OBJECT_SIZE); cio_utest_length = 0; cio_utest_position = 0; // Start by opening a file fh = crud_open("temp_file.txt"); if (fh == -1) { logMessage(LOG_ERROR_LEVEL, "CRUD_IO_UNIT_TEST : Failure open operation."); return(-1); } // Now do a bunch of operations for (i=0; i<CRUD_IO_UNIT_TEST_ITERATIONS; i++) { // Pick a random command if (cio_utest_length == 0) { cmd = CIO_UNIT_TEST_WRITE; } else { cmd = getRandomValue(CIO_UNIT_TEST_READ, CIO_UNIT_TEST_SEEK); } // Execute the command switch (cmd) { case CIO_UNIT_TEST_READ: // read a random set of data count = getRandomValue(0, cio_utest_length); logMessage(LOG_INFO_LEVEL, "CRUD_IO_UNIT_TEST : read %d at position %d", bytes, cio_utest_position); bytes = crud_read(fh, tbuf, count); if (bytes == -1) { logMessage(LOG_ERROR_LEVEL, "CRUD_IO_UNIT_TEST : Read failure."); return(-1); } // Compare to what we expected if (cio_utest_position+count > cio_utest_length) { expected = cio_utest_length-cio_utest_position; } else { expected = count; } if (bytes != expected) { logMessage(LOG_ERROR_LEVEL, "CRUD_IO_UNIT_TEST : short/long read of [%d!=%d]", bytes, expected); return(-1); } if ( (bytes > 0) && (memcmp(&cio_utest_buffer[cio_utest_position], tbuf, bytes)) ) { bufToString((unsigned char *)tbuf, bytes, (unsigned char *)lstr, 1024 ); logMessage(LOG_INFO_LEVEL, "CIO_UTEST R: %s", lstr); bufToString((unsigned char *)&cio_utest_buffer[cio_utest_position], bytes, (unsigned char *)lstr, 1024 ); logMessage(LOG_INFO_LEVEL, "CIO_UTEST U: %s", lstr); logMessage(LOG_ERROR_LEVEL, "CRUD_IO_UNIT_TEST : read data mismatch (%d)", bytes); return(-1); } logMessage(LOG_INFO_LEVEL, "CRUD_IO_UNIT_TEST : read %d match", bytes); // update the position pointer cio_utest_position += bytes; break; case CIO_UNIT_TEST_APPEND: // Append data onto the end of the file // Create random block, check to make sure that the write is not too large ch = getRandomValue(0, 0xff); count = getRandomValue(1, CIO_UNIT_TEST_MAX_WRITE_SIZE); if (cio_utest_length+count >= CRUD_MAX_OBJECT_SIZE) { // Log, seek to end of file, create random value logMessage(LOG_INFO_LEVEL, "CRUD_IO_UNIT_TEST : append of %d bytes [%x]", count, ch); logMessage(LOG_INFO_LEVEL, "CRUD_IO_UNIT_TEST : seek to position %d", cio_utest_length); if (crud_seek(fh, cio_utest_length)) { logMessage(LOG_ERROR_LEVEL, "CRUD_IO_UNIT_TEST : seek failed [%d].", cio_utest_length); return(-1); } cio_utest_position = cio_utest_length; memset(&cio_utest_buffer[cio_utest_position], ch, count); // Now write bytes = crud_write(fh, &cio_utest_buffer[cio_utest_position], count); if (bytes != count) { logMessage(LOG_ERROR_LEVEL, "CRUD_IO_UNIT_TEST : append failed [%d].", count); return(-1); } cio_utest_length = cio_utest_position += bytes; } break; case CIO_UNIT_TEST_WRITE: // Write random block to the file ch = getRandomValue(0, 0xff); count = getRandomValue(1, CIO_UNIT_TEST_MAX_WRITE_SIZE); // Check to make sure that the write is not too large if (cio_utest_length+count < CRUD_MAX_OBJECT_SIZE) { // Log the write, perform it logMessage(LOG_INFO_LEVEL, "CRUD_IO_UNIT_TEST : write of %d bytes [%x]", count, ch); memset(&cio_utest_buffer[cio_utest_position], ch, count); bytes = crud_write(fh, &cio_utest_buffer[cio_utest_position], count); if (bytes!=count) { logMessage(LOG_ERROR_LEVEL, "CRUD_IO_UNIT_TEST : write failed [%d].", count); return(-1); } cio_utest_position += bytes; if (cio_utest_position > cio_utest_length) { cio_utest_length = cio_utest_position; } } break; case CIO_UNIT_TEST_SEEK: count = getRandomValue(0, cio_utest_length); logMessage(LOG_INFO_LEVEL, "CRUD_IO_UNIT_TEST : seek to position %d", count); if (crud_seek(fh, count)) { logMessage(LOG_ERROR_LEVEL, "CRUD_IO_UNIT_TEST : seek failed [%d].", count); return(-1); } cio_utest_position = count; break; default: // This should never happen CMPSC_ASSERT0(0, "CRUD_IO_UNIT_TEST : illegal test command."); break; } #if DEEP_DEBUG // VALIDATION STEP: ENSURE OUR LOCAL IS LIKE OBJECT STORE CrudRequest request; CrudResponse response; CrudOID oid; CRUD_REQUEST_TYPES req; uint32_t length; uint8_t res, flags; // Make a fake request to get file handle, then check it request = construct_crud_request(file_table[0].object_handle, CRUD_READ, CRUD_MAX_OBJECT_SIZE, 0, 0); response = crud_bus_request(request, tbuf); if ((deconstruct_crud_request(response, &oid, &req, &length, &flags, &res) != 0) || (res != 0)) { logMessage(LOG_ERROR_LEVEL, "Read failure, bad CRUD response [%x]", response); return(-1); } if ( (cio_utest_length != length) || (memcmp(cio_utest_buffer, tbuf, length)) ) { logMessage(LOG_ERROR_LEVEL, "Buffer/Object cross validation failed [%x]", response); bufToString((unsigned char *)tbuf, length, (unsigned char *)lstr, 1024 ); logMessage(LOG_INFO_LEVEL, "CIO_UTEST VR: %s", lstr); bufToString((unsigned char *)cio_utest_buffer, length, (unsigned char *)lstr, 1024 ); logMessage(LOG_INFO_LEVEL, "CIO_UTEST VU: %s", lstr); return(-1); } // Print out the buffer bufToString((unsigned char *)cio_utest_buffer, cio_utest_length, (unsigned char *)lstr, 1024 ); logMessage(LOG_INFO_LEVEL, "CIO_UTEST: %s", lstr); #endif } // Close the files and cleanup buffers, assert on failure if (crud_close(fh)) { logMessage(LOG_ERROR_LEVEL, "CRUD_IO_UNIT_TEST : Failure read comparison block.", fh); return(-1); } free(cio_utest_buffer); free(tbuf); // Return successfully return(0); }

assign3/crud_sim.o

assign3/crud_driver.h

#ifndef CRUD_DRIVER_INCLUDED #define CRUD_DRIVER_INCLUDED //////////////////////////////////////////////////////////////////////////////// // // File : crud_driver.h // Description : This is the header file for the driver implementation // of the CRUD storage system. // // Author : Patrick McDaniel // Last Modified : Sat Sep 6 08:24:25 EDT 2014 // // Includes #include <stdint.h> // Defines #define CRUD_MAX_OBJECT_SIZE 0xfffff #define CRUD_NO_OBJECT 0 // // Type definitions typedef uint32_t CrudOID; // This is the request object identifier (unique to object) // These are the request types typedef enum { CRUD_INIT = 0, // Initialize the CRUD interface CRUD_CREATE = 1, // Create a new object CRUD_READ = 2, // Read an object CRUD_UPDATE = 3, // Update the object CRUD_DELETE = 4, // Delete an object CRUD_UNKNOWN = 5, // Unknown type CRUD_MAXVAL = 6, // Max value } CRUD_REQUEST_TYPES; const char *CRUD_REQUEST_TYPE_LABLES[CRUD_MAXVAL]; // CRUD request and response types typedef uint64_t CrudRequest; typedef uint64_t CrudResponse; /* Request/Response Specification 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | OID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Req | Length |Flags|R| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Bits Description ----- ------------------------------------------------------------- 0-31 - OID - the object ID (0 if not relevant) 32-35 - Request type - this is the request type (CRUD_REQUEST_TYPES) 36-58 - Length - this is the size of the object in bytes 60-62 - Flags - these are flags for commands (UNUSED) 63 - R - this is the result bit (0 success, 1 is failure) */ // // CRUD interface CrudResponse crud_bus_request( CrudRequest request, void *buf ); // This is the interface to the CRUD interfaces // // Unit testing for the module int crud_unit_test( void ); // This is a function used to test the CRUD interfaces and code. #endif