From b70415e2c0da00ebbdc6a17867e04757107ba04c Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Fri, 2 Mar 2012 22:14:13 -0500 Subject: [PATCH] Reverting ex17 to a state that should be pretty close to the book source ... still need to check --- ex17.c | 110 ++++++++++++++++++--------------------------------------- 1 file changed, 35 insertions(+), 75 deletions(-) diff --git a/ex17.c b/ex17.c index 1eaece1..493d9a1 100644 --- a/ex17.c +++ b/ex17.c @@ -4,21 +4,18 @@ #include #include -#define DEFAULT_MAX_DATA 512 -#define DEFAULT_MAX_ROWS 100 +#define MAX_DATA 512 +#define MAX_ROWS 100 struct Address { int id; int set; - char *name; - char *email; + char name[MAX_DATA]; + char email[MAX_DATA]; }; struct Database { - size_t size; - int max_data; - int max_rows; - struct Address *rows; + struct Address rows[MAX_ROWS]; }; struct Connection { @@ -26,9 +23,7 @@ struct Connection { struct Database *db; }; -void Database_close(struct Connection *conn); - -void die(const char *message, struct Connection *conn) +void die(const char *message) { if(errno) { perror(message); @@ -36,8 +31,6 @@ void die(const char *message, struct Connection *conn) printf("ERROR: %s\n", message); } - Database_close(conn); - exit(1); } @@ -49,30 +42,17 @@ void Address_print(struct Address *addr) void Database_load(struct Connection *conn) { - rewind(conn->file); - - int rc = fread(&conn->db->max_rows, sizeof(int), 1, conn->file); - if(rc != 1) die("Failed to load database max_rows.", conn); - - rc = fread(&conn->db->max_data, sizeof(int), 1, conn->file); - if(rc != 1) die("Failed to load database max_data.", conn); - - rc = fread(conn->db->rows, sizeof(struct Address), conn->db->max_rows, conn->file); - if(rc != 1) die("Failed to load database rows.", conn); + int rc = fread(conn->db, sizeof(struct Database), 1, conn->file); + if(rc != 1) die("Failed to load database."); } -struct Connection* Database_open(const char *filename, char mode, int max_rows) +struct Connection* Database_open(const char *filename, char mode) { struct Connection *conn = malloc(sizeof(struct Connection)); - if(!conn) die("Memory error", conn); + if(!conn) die("Memory error"); conn->db = malloc(sizeof(struct Database)); - if(!conn->db) die("Memory error", conn); - - size_t rowsize = max_rows * sizeof(struct Address); - conn->db->size = rowsize; - conn->db->rows = malloc(rowsize); - if(!conn->db->rows) die("Memory error", conn); + if(!conn->db) die("Memory error"); if(mode == 'c') { conn->file = fopen(filename, "w"); @@ -84,14 +64,14 @@ struct Connection* Database_open(const char *filename, char mode, int max_rows) } } - if(!conn->file) die("Failed to open the file", conn); + if(!conn->file) die("Failed to open the file"); return conn; } void Database_close(struct Connection *conn) { - if(conn != NULL) { + if(conn) { if(conn->file) fclose(conn->file); if(conn->db) free(conn->db); free(conn); @@ -102,29 +82,18 @@ void Database_write(struct Connection *conn) { rewind(conn->file); - int rc = fwrite(&conn->db->size, sizeof(size_t), 1, conn->file); - if(rc != 1) die("Failed to write database size.", conn); - - rc = fwrite(&conn->db->max_rows, sizeof(int), 1, conn->file); - if(rc != 1) die("Failed to write database max_rows.", conn); - - rc = fwrite(&conn->db->max_data, sizeof(int), 1, conn->file); - if(rc != 1) die("Failed to write database max_data.", conn); - - rc = fwrite(conn->db->rows, conn->db->size, 1, conn->file); - if(rc != 1) die("Failed to write database rows.", conn); + int rc = fwrite(conn->db, sizeof(struct Database), 1, conn->file); + if(rc != 1) die("Failed to write database."); rc = fflush(conn->file); - if(rc == -1) die("Cannot flush database.", conn); + if(rc == -1) die("Cannot flush database."); } -void Database_create(struct Connection *conn, int max_rows, int max_data) +void Database_create(struct Connection *conn) { int i = 0; - conn->db->max_rows = max_rows; - conn->db->max_data = max_data; - for(i = 0; i < conn->db->max_rows; i++) { + for(i = 0; i < MAX_ROWS; i++) { // make a prototype to initialize it struct Address addr = {.id = i, .set = 0}; // then just assign it @@ -134,18 +103,17 @@ void Database_create(struct Connection *conn, int max_rows, int max_data) void Database_set(struct Connection *conn, int id, const char *name, const char *email) { - int max_data = conn->db->max_data; struct Address *addr = &conn->db->rows[id]; - if(addr->set) die("Already set, delete it first", conn); + if(addr->set) die("Already set, delete it first"); addr->set = 1; - char *res = strncpy(addr->name, name, max_data); - if(!res) die("Name copy failed", conn); - addr->name[max_data - 1] = '\0'; + // WARNING: bug, read the "How To Break It" and fix this + char *res = strncpy(addr->name, name, MAX_DATA); + // demonstrate the strncpy bug + if(!res) die("Name copy failed"); - res = strncpy(addr->email, email, max_data); - if(!res) die("Email copy failed", conn); - addr->email[max_data - 1] = '\0'; + res = strncpy(addr->email, email, MAX_DATA); + if(!res) die("Email copy failed"); } void Database_get(struct Connection *conn, int id) @@ -155,7 +123,7 @@ void Database_get(struct Connection *conn, int id) if(addr->set) { Address_print(addr); } else { - die("ID is not set", conn); + die("ID is not set"); } } @@ -170,7 +138,7 @@ void Database_list(struct Connection *conn) int i = 0; struct Database *db = conn->db; - for(i = 0; i < conn->db->max_rows; i++) { + for(i = 0; i < MAX_ROWS; i++) { struct Address *cur = &db->rows[i]; if(cur->set) { @@ -181,45 +149,37 @@ void Database_list(struct Connection *conn) int main(int argc, char *argv[]) { - if(argc < 3) die("USAGE: ex17 [:max_data,max_rows] [action params]", NULL); + if(argc < 3) die("USAGE: ex17 [action params]"); char *filename = argv[1]; - - int max_data = DEFAULT_MAX_DATA; - int max_rows = DEFAULT_MAX_ROWS; - char action = argv[2][0]; - if(':' == argv[2][1]) { - sscanf(argv[2], "%c:%d,%d", &action, &max_data, &max_rows); - } - - struct Connection *conn = Database_open(filename, action, max_rows); + struct Connection *conn = Database_open(filename, action); int id = 0; if(argc > 3) id = atoi(argv[3]); - if(id >= max_rows) die("There's not that many records.", conn); + if(id >= MAX_ROWS) die("There's not that many records."); switch(action) { case 'c': - Database_create(conn, max_rows, max_data); + Database_create(conn); Database_write(conn); break; case 'g': - if(argc != 4) die("Need an id to get", conn); + if(argc != 4) die("Need an id to get"); Database_get(conn, id); break; case 's': - if(argc != 6) die("Need id, name, email to set", conn); + if(argc != 6) die("Need id, name, email to set"); Database_set(conn, id, argv[4], argv[5]); Database_write(conn); break; case 'd': - if(argc != 4) die("Need id to delete", conn); + if(argc != 4) die("Need id to delete"); Database_delete(conn, id); Database_write(conn); @@ -229,7 +189,7 @@ int main(int argc, char *argv[]) Database_list(conn); break; default: - die("Invalid action, only: c=create, g=get, s=set, d=del, l=list", conn); + die("Invalid action, only: c=create, g=get, s=set, d=del, l=list"); } Database_close(conn);