Skip to content

Commit

Permalink
ex17 initial
Browse files Browse the repository at this point in the history
  • Loading branch information
jessewmc committed Aug 11, 2014
1 parent d55473f commit fb162bd
Show file tree
Hide file tree
Showing 3 changed files with 186 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
CFLAGS=-Wall -g

all: ex1 ex3 ex4 ex5 ex6 ex7 ex8 ex9 ex10 ex11 ex12 ex13 ex14 ex15 ex16
all: ex1 ex3 ex4 ex5 ex6 ex7 ex8 ex9 ex10 ex11 ex12 ex13 ex14 ex15 ex16 ex17


clean:
Expand Down
Binary file added ex17
Binary file not shown.
185 changes: 185 additions & 0 deletions ex17.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

#define MAX_DATA 512
#define MAX_ROWS 100

struct Address{
int id;
int set;
char name[MAX_DATA];
char email[MAX_DATA];
};

struct Database{
struct Address rows[MAX_ROWS];
};

struct Connection{
FILE* file;
struct Database* db;
};

void die(const char* message){
if(errno){
perror(message);
} else {
printf("ERROR: %s\n", message);
}
exit(1);
}

void Address_print(struct Address* addr){
printf("%d %s %s\n", addr->id, addr->name, addr->email);
}

void Database_load(struct Connection* conn){
//I don't like this magic number 1
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){
struct Connection* conn = malloc(sizeof(struct Connection));
if(!conn) die("Memory error");

conn->db = malloc(sizeof(struct Database));
if(!conn->db) die("Memory error");

if(mode == 'c'){
conn->file = fopen(filename, "w");
} else {
conn->file = fopen(filename, "r+");

if(conn->file){
Database_load(conn);
}
}

if(!conn->file) die("Failed to open the file");

return conn;
}

void Database_close(struct Connection* conn){
if(conn){
if(conn->file) fclose(conn->file);
if(conn->db) free(conn->db);
free(conn);
}
}

void Database_write(struct Connection* conn){
rewind(conn->file);

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.");
}

void Database_create(struct Connection* conn){
int i = 0;

for(i = 0; i < MAX_ROWS; i++){
struct Address addr = {.id = i, .set = 0};
//why on stack?
conn->db->rows[i] = addr;
}
}

void Database_set(struct Connection *conn, int id, const char* name, const char* email){
struct Address* addr = &conn->db->rows[id];
if(addr->set) die("Already set, delete it first");

addr->set = 1;
//bug here
char* res = strncpy(addr->name, name, MAX_DATA);
//demonstrate bug?
if(!res) die("Name copy failed");

res = strncpy(addr->email, email, MAX_DATA);
if(!res) die("Email copy failed");
}

void Database_get(struct Connection* conn, int id){
struct Address* addr = &conn->db->rows[id];

if(addr->set){
Address_print(addr);
} else{
die("ID is not set");
}
}

void Database_delete(struct Connection* conn, int id){
struct Address addr= {.id = id, .set = 0};
conn->db->rows[id] = addr;
}

void Database_list(struct Connection* conn){
int i = 0;
struct Database* db = conn->db;

for(i = 0; i < MAX_ROWS; i++){
struct Address* cur = &db->rows[i];

if(cur->set){
Address_print(cur);
}
}
}

int main(int argc, char* argv[]){
if(argc < 3) die("USAGE: ex17 <dbfile> <action> [action params]");

char* filename = argv[1];
char action = argv[2][0];
struct Connection* conn = Database_open(filename, action);
int id = 0;

if(argc > 3) id = atoi(argv[3]);
if(id >= MAX_ROWS) die("There aren't that many recoreds.");

switch(action){
case 'c':
Database_create(conn);
Database_write(conn);
break;

case 'g':
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");

Database_set(conn, id, argv[4], argv[5]);
Database_write(conn);
break;

case 'd':
if(argc != 4) die("Need id to delete");

Database_delete(conn, id);
Database_write(conn);
break;

case 'l':
Database_list(conn);
break;
default:
die("Invalid action, only c=create g=get s=set d=del l=list");
}

Database_close(conn);

return 0;
}

0 comments on commit fb162bd

Please sign in to comment.