Alex 'AdUser' Z
11 years ago
8 changed files with 271 additions and 52 deletions
@ -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; |
||||||
|
} |
@ -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 |
@ -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 <gdbm.h> |
|
||||||
|
|
||||||
#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; |
|
||||||
} |
|
@ -1,13 +1,14 @@ |
|||||||
all: test-bitmap |
TESTS=test-bitmap test-database
|
||||||
|
|
||||||
|
all: $(TESTS) |
||||||
|
|
||||||
CFLAGS=-Wall -Wextra -O0 -g -ggdb -pedantic
|
CFLAGS=-Wall -Wextra -O0 -g -ggdb -pedantic
|
||||||
|
|
||||||
%.o: %.c |
%.o: %.c |
||||||
gcc $(CFLAGS) $< -o $@
|
gcc $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
SRC=../src/bitmap.c bitmap.c
|
test-%: ../src/%.c %.c |
||||||
test-bitmap: |
gcc $(CFLAGS) $(SRC) -o $@ $^
|
||||||
gcc $(CFLAGS) $(SRC) -o $@
|
|
||||||
|
|
||||||
clean: |
clean: |
||||||
rm -f test-bitmap
|
rm -f $(TESTS)
|
||||||
|
@ -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; |
||||||
|
} |
Loading…
Reference in new issue