From 1ef515e77a7ff3da20bcae9097741cd19e2ac31f Mon Sep 17 00:00:00 2001 From: Alex 'AdUser' Z Date: Wed, 2 Apr 2014 15:41:13 +1100 Subject: [PATCH] * database.[ch] --- src/Makefile | 8 +- src/database.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++ src/database.h | 31 ++++++++ src/main.c | 34 --------- src/main.h | 10 ++- src/test-image.c | 3 +- tests/Makefile | 13 ++-- tests/database.c | 31 ++++++++ 8 files changed, 271 insertions(+), 52 deletions(-) create mode 100644 src/database.c create mode 100644 src/database.h delete mode 100644 src/main.c create mode 100644 tests/database.c diff --git a/src/Makefile b/src/Makefile index 3dc7abd..355ed17 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,15 +1,9 @@ CFLAGS=-Wall -Wextra -O0 -g -ggdb -pedantic -all: test-image - -%.c: %.h +all: *.o %.o: %.c gcc -O0 -Wall -Wextra -pedantic -ggdb $< -o $@ clean: rm -f *.o - rm -f test-image - -test-image: image.c test-image.c - gcc $(CFLAGS) -lmagic -lgd image.c test-image.c -o $@ diff --git a/src/database.c b/src/database.c new file mode 100644 index 0000000..e4414c2 --- /dev/null +++ b/src/database.c @@ -0,0 +1,193 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301, USA + */ + +#include "main.h" +#include "database.h" + +#define DB_SEEK(db, offset) \ + errno = 0; \ + if (lseek((db)->fd, (offset), SEEK_SET) == -1) { \ + (db)->errstr = strerror(errno); \ + return -1; \ + } + +#define DB_READ(db, buf, len) \ + errno = 0; \ + memset((buf), 0x0, (len)); \ + bytes = read((db)->fd, (buf), (len)); \ + if (errno) { \ + (db)->errstr = strerror(errno); \ + return -1; \ + } + +#define DB_WRITE(db, buf, len) \ + errno = 0; \ + bytes = write((db)->fd, (buf), (len)); \ + if (errno) { \ + (db)->errstr = strerror(errno); \ + return -1; \ + } + +int db_open(db_t *db, const char *path) +{ + int init = 0; + ssize_t bytes = 0; + struct stat st; + char buf[REC_LEN] = "\0"; + + assert(db != NULL); + assert(path != NULL); + + memset(db, 0x0, sizeof(db_t)); + db->fd = -1; + + errno = 0; + if (stat(path, &st) == -1 && errno == ENOENT) { + init = 1; + } + + errno = 0; + if ((db->fd = open(path, OPEN_FLAGS, 0644)) == -1) { + db->errstr = strerror(errno); + return -1; + } + + db->path = path; + + if (init) { + memset(buf, 0x0, REC_LEN); + snprintf((char *) buf, REC_LEN, "DB of image fingerprints (vers %d)", DB_VERSION); + DB_SEEK(db, 0); + DB_WRITE(db, buf, REC_LEN); + + return bytes / REC_LEN; + } + + return 0; +} + +int db_close(db_t *db) +{ + assert(db != NULL); + + errno = 0; + if (close(db->fd) != 0) { + db->errstr = strerror(errno); + return -1; + } + db->fd = -1; + + return 0; +} + +int db_rd_rec(db_t *db, rec_t *rec) +{ + ssize_t bytes = 0; + + assert(db != NULL); + assert(rec != NULL); + assert(rec->num > 0); + + DB_SEEK(db, rec->num * REC_LEN); + DB_READ(db, rec->data, REC_LEN); + + return bytes / REC_LEN; +} + +int db_wr_rec(db_t *db, rec_t *rec) +{ + ssize_t bytes = 0; + + assert(db != NULL); + assert(rec != NULL); + assert(rec->num > 0); + + DB_SEEK(db, rec->num * REC_LEN); + DB_WRITE(db, rec->data, REC_LEN); + + return bytes / REC_LEN; +} + +int db_rd_blk(db_t *db, uint64_t start, size_t len, rec_t *list) +{ + rec_t *r = NULL; + ssize_t bytes = 0; + unsigned int i = 0; + unsigned char *buf; + unsigned char *p = NULL; + + assert(db != NULL); + assert(list != NULL); + assert(len > 0); + + CALLOC(buf, len, REC_LEN); + DB_SEEK(db, start * REC_LEN); + DB_READ(db, buf, len * REC_LEN); + + p = buf; + r = list; + len = bytes / REC_LEN; + for (i = 0; i < len; i++, r++, p += REC_LEN) { + r->num = start + i; + memcpy(r->data, p, REC_LEN); + } + + FREE(buf); + + return len; +} + +int db_rd_list(db_t *db, rec_t *list, size_t list_len) +{ + rec_t *r = NULL; + ssize_t bytes; + unsigned int i = 0; + unsigned int processed = 0; + + assert(db != NULL); + assert(list != NULL); + assert(list_len > 0); + + r = list; + for (i = 0; i < list_len; i++, r++) { + DB_SEEK(db, r->num * REC_LEN); + DB_READ(db, r->data, REC_LEN); + if (bytes == REC_LEN) { processed++; } + } + + return processed; +} + +int db_wr_list(db_t *db, rec_t *list, size_t list_len) +{ + rec_t *r = NULL; + ssize_t bytes; + unsigned int i = 0; + unsigned int processed = 0; + + assert(db != NULL); + assert(list != NULL); + assert(list_len > 0); + + r = list; + for (i = 0; i < list_len; i++, r++) { + DB_SEEK(db, r->num * REC_LEN); + DB_WRITE(db, r->data, REC_LEN); + if (bytes == REC_LEN) { processed++; } + } + + return processed; +} diff --git a/src/database.h b/src/database.h new file mode 100644 index 0000000..70f2ec3 --- /dev/null +++ b/src/database.h @@ -0,0 +1,31 @@ +#ifndef HAS_DATABASE_H + +#define REC_LEN 48 +#define DB_VERSION 1 +#define OPEN_FLAGS O_CREAT | O_RDWR + +typedef struct { + int fd; + const char *path; + const char *errstr; +} db_t; + +typedef struct { + uint64_t num; + unsigned char data[REC_LEN]; +} rec_t; + +extern int db_open(db_t *db, const char *path); +extern int db_close(db_t *db); + +extern int db_rd_rec(db_t *db, rec_t *rec); +extern int db_wr_rec(db_t *db, rec_t *rec); + +extern int db_rd_blk(db_t *db, uint64_t start, size_t len, rec_t *list); +extern int db_wr_blk(db_t *db, uint64_t start, size_t len, rec_t *list); + +extern int db_rd_list(db_t *db, rec_t *list, size_t list_len); +extern int db_wr_list(db_t *db, rec_t *list, size_t list_len); + +#endif +#define HAS_DATABASE_H 1 diff --git a/src/main.c b/src/main.c deleted file mode 100644 index 34e2956..0000000 --- a/src/main.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301, USA - */ - -#include "main.h" -#include - -#define DB_BLOCKSIZE 256 * 1024 - -GDBM_FILE dbf; - -int db_open(char *samples, char *files) -{ - dbf = gdbm_open(samples, DB_BLOCKSIZE, GDBM_WRCREAT, 0644, 0); - - if (!dbf) { - printf("Can't open database: %s\n", gdbm_strerror(gdbm_errno)); - return 0; - } - - return 1; -} diff --git a/src/main.h b/src/main.h index 5f94255..72093b3 100644 --- a/src/main.h +++ b/src/main.h @@ -7,10 +7,13 @@ #include #include #include +#include +#include #include #include #include #include +#include #define FREE(ptr) \ free((ptr)); (ptr) = NULL; @@ -21,10 +24,9 @@ #define STRNDUP(ptr, str, len) \ assert(((ptr) = strndup((str), (len))) != NULL); -extern int db_open(char *samples, char *files); -extern int db_close(void); - extern int image_add(uint64_t, char *path); extern int image_del(uint64_t); extern int image_exists(uint64_t); -/*extern int image_find(uint64_t, rec_t **data, size_t limit);*/ +/* +extern int image_search(uint64_t, rec_t **data, size_t limit); +*/ diff --git a/src/test-image.c b/src/test-image.c index 365cd7a..8ad9d46 100644 --- a/src/test-image.c +++ b/src/test-image.c @@ -4,7 +4,8 @@ #include "bitmap.h" #include "image.h" -int main(int argc, char **argv) { +int main(int argc, char **argv) +{ image_t *img = NULL; const char *err = NULL; diff --git a/tests/Makefile b/tests/Makefile index 78ea1c4..342db17 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,13 +1,14 @@ -all: test-bitmap +TESTS=test-bitmap test-database + +all: $(TESTS) CFLAGS=-Wall -Wextra -O0 -g -ggdb -pedantic %.o: %.c - gcc $(CFLAGS) $< -o $@ + gcc $(CFLAGS) -o $@ $< -SRC=../src/bitmap.c bitmap.c -test-bitmap: - gcc $(CFLAGS) $(SRC) -o $@ +test-%: ../src/%.c %.c + gcc $(CFLAGS) $(SRC) -o $@ $^ clean: - rm -f test-bitmap + rm -f $(TESTS) diff --git a/tests/database.c b/tests/database.c new file mode 100644 index 0000000..b7f41ee --- /dev/null +++ b/tests/database.c @@ -0,0 +1,31 @@ +#include "../src/main.h" +#include "../src/database.h" + +int main(int argc, char **argv) +{ + db_t db; + rec_t rec[2]; + char *path = "test.db"; + + unlink(path); + assert(db_open(&db, path) == 1); + + rec[0].num = 1; + assert(db_rd_rec(&db, rec) == 0); + + memset(rec[0].data, 0xAA, REC_LEN); + assert(db_wr_rec(&db, rec) == 1); + + assert(db_rd_rec(&db, rec) == 1); + + assert(db_rd_blk(&db, 1, 1, rec) == 1); + assert(db_rd_blk(&db, 1, 2, rec) == 1); + + rec[0].num = 1; + rec[1].num = 3; + assert(db_rd_list(&db, rec, 2) == 1); + + assert(db_close(&db) == 0); + + return 0; +}