Guest User

Untitled

a guest
Feb 18th, 2013
297
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.20 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <assert.h>
  3. #include <stdlib.h>
  4. #include <errno.h>
  5. #include <string.h>
  6.  
  7. //#define MAX_DATA 512
  8. //#define MAX_ROWS 100
  9.  
  10. struct Address {
  11.     int id;
  12.     int set;
  13.     char *name;
  14.     char *email;
  15. };
  16.  
  17. struct Database {
  18.     struct Address *rows;
  19.     int MAX_DATA;
  20.     int MAX_ROWS;
  21. };
  22.  
  23. struct Connection {
  24.     FILE *file;
  25.     struct Database *db;
  26. };
  27.  
  28. void die(const char *message)
  29. {
  30.     if(errno) {
  31.         perror(message);
  32.     } else {
  33.         printf("ERROR: %s\n", message);
  34.     }
  35.  
  36.     exit(1);
  37. }
  38.  
  39. void Address_print(struct Address *addr)
  40. {
  41.     printf("%d %s %s\n",
  42.             addr->id, addr->name, addr->email);
  43. }
  44.  
  45. void Database_load(struct Connection *conn)
  46. {
  47.     int rc = fread(conn->db, sizeof(struct Database), 1, conn->file);
  48.     if(rc != 1) die("Failed to load database. First round.");
  49.  
  50. //    printf("Max data : %d, max rows: %d\n", conn->db->MAX_DATA, conn->db->MAX_ROWS);
  51.     rewind(conn->file);
  52.     conn->db->rows = malloc(sizeof(struct Address) * conn->db->MAX_ROWS);
  53.     if(conn->db->rows == NULL) die("Failed to allocate memory for rows");
  54.     int rc1 = fread(conn->db, sizeof(struct Database), 1, conn->file);
  55.     if(rc1 != 1) die("Failed to load database. Second round.");
  56. }
  57.  
  58. struct Connection *Database_open(const char *filename, char mode)
  59. {
  60.     struct Connection *conn = malloc(sizeof(struct Connection));
  61.     if(!conn) die("Memory error");
  62.  
  63.     conn->db = malloc(sizeof(struct Database));
  64.     if(!conn->db) die("Memory error");
  65.    
  66.     if(mode == 'c') {
  67.         conn->file = fopen(filename, "w");
  68.     } else {
  69.         conn->file = fopen(filename, "r+");
  70.  
  71.         if(conn->file) {
  72.             Database_load(conn);
  73.         }
  74.     }
  75.  
  76.     if(!conn->file) die("Failed to open the file");
  77.  
  78.     return conn;
  79. }
  80.  
  81. void Database_close(struct Connection *conn)
  82. {
  83.     if(conn) {
  84.         if(conn->file) fclose(conn->file);
  85.         if(conn->db) free(conn->db);
  86.         free(conn);
  87.     }
  88. }
  89.  
  90. void Database_write(struct Connection *conn)
  91. {
  92.     rewind(conn->file);
  93.  
  94.     int rc = fwrite(conn->db, sizeof(struct Database), 1, conn->file);
  95.     if(rc != 1) die("Failed to write database.");
  96.  
  97.     rc = fflush(conn->file);
  98.     if(rc == -1) die("Cannot flush database.");
  99. }
  100.  
  101. void Database_create(struct Connection *conn, int MAX_DATA, int MAX_ROWS)
  102. {
  103.     int i = 0;
  104.     conn->db->MAX_DATA = MAX_DATA;
  105.     conn->db->MAX_ROWS = MAX_ROWS;
  106.     conn->db->rows = malloc(sizeof(struct Address) * MAX_ROWS);
  107.     for(i = 0; i < MAX_ROWS; i++) {
  108.         struct Address addr = {.id = i, .set = 0};
  109.         conn->db->rows[i] = addr;
  110.     struct Address *addr1 = &conn->db->rows[i];
  111.     printf("set = %d\n", addr1->set);
  112.     }
  113. }
  114.  
  115. void Database_set(struct Connection *conn, int id, const char *name, const char *email)
  116. {
  117.     struct Address *addr = &conn->db->rows[id];
  118.     int MAX_DATA = conn->db->MAX_DATA;
  119.     if(addr->set) die("Already set, delete it first");
  120.  
  121.     addr->set = 1;
  122.     addr->name = malloc(sizeof(char) * MAX_DATA);
  123.     addr->email = malloc(sizeof(char) * MAX_DATA);
  124.     // WARNING: bug, read the "How To Break It" and fix this
  125.     char *res = strncpy(addr->name, name, MAX_DATA);
  126.     // demonstrate the strncpy bug
  127.     if(!res) die("Name copy failed");
  128.  
  129.     res = strncpy(addr->email, email, MAX_DATA);
  130.     if(!res) die("Email copy failed");
  131. }
  132.  
  133. void Database_get(struct Connection *conn, int id)
  134. {
  135.     struct Address *addr = &conn->db->rows[id];
  136.  
  137.     if(addr->set) {
  138.         Address_print(addr);
  139.     } else {
  140.         die("ID is not set");
  141.     }
  142. }
  143.  
  144. void Database_delete(struct Connection *conn, int id)
  145. {
  146.     struct Address addr = {.id = id, .set = 0};
  147.     conn->db->rows[id] = addr;
  148. }
  149.  
  150. void Database_list(struct Connection *conn)
  151. {
  152.     int i = 0;
  153.     struct Database *db = conn->db;
  154.     int MAX_ROWS = conn->db->MAX_ROWS;
  155.     for(i = 0; i < MAX_ROWS; i++) {
  156.         struct Address *cur = &db->rows[i];
  157.  
  158.         if(cur->set) {
  159.             Address_print(cur);
  160.         }
  161.     }
  162. }
  163.  
  164. int main(int argc, char *argv[])
  165. {
  166.     if(argc < 3) die("USAGE: ex17 <dbfile> <action> [action params]");
  167.  
  168.     char *filename = argv[1];
  169.     char action = argv[2][0];
  170.     struct Connection *conn = Database_open(filename, action);
  171.     int id = 0;
  172.  
  173. //    if(argc > 3) id = atoi(argv[3]);
  174.  //   if(id >= MAX_ROWS) die("There's not that many records.");
  175.  
  176.     switch(action) {
  177.         case 'c':
  178.         if(argc < 5) die("Required: MAX_DATA, MAX_ROWS");
  179.             Database_create(conn, atoi(argv[3]), atoi(argv[4]));
  180.             Database_write(conn);
  181.             break;
  182.  
  183.         case 'g':
  184.             if(argc != 4) die("Need an id to get");
  185.  
  186.             Database_get(conn, id);
  187.             break;
  188.  
  189.         case 's':
  190.             if(argc != 6) die("Need id, name, email to set");
  191.             Database_set(conn, id, argv[4], argv[5]);
  192.             Database_write(conn);
  193.             break;
  194.  
  195.         case 'd':
  196.             if(argc != 4) die("Need id to delete");
  197.  
  198.             Database_delete(conn, id);
  199.             Database_write(conn);
  200.             break;
  201.  
  202.         case 'l':
  203.             Database_list(conn);
  204.             break;
  205.         default:
  206.             die("Invalid action, only: c=create, g=get, s=set, d=del, l=list");
  207.     }
  208.  
  209.     Database_close(conn);
  210.  
  211.     return 0;
  212. }
Advertisement
Add Comment
Please, Sign In to add comment