-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdb.c
More file actions
117 lines (107 loc) · 2.62 KB
/
db.c
File metadata and controls
117 lines (107 loc) · 2.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <stdio.h>
#include <limits.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <xxhash.h>
#include "estd.h"
#include "db.h"
#define HASH_LEN 16
#define HASH_BASE 16
#define PROG_LEN 11
#define PROG_BASE 10
static XXH64_hash_t
get_file_hash(const char *path) {
char *buffer;
size_t size;
XXH64_hash_t hash;
FILE *f;
f = efopen(path, "r");
fseek(f, 0, SEEK_END);
size = (size_t)ftello(f);
fseek(f, 0, SEEK_SET);
buffer = (char*)emalloc(size);
fread(buffer, size, 1, f);
hash = XXH64(buffer, size, 0);
fclose(f);
return hash;
}
DB *
db_init(const char *dir, const char *file) {
char *sdir, *share = "/.local/share/";
const char *home;
size_t dir_len, path_len;
DB *db;
db = emalloc(sizeof(DB));
home = egetenv("HOME");
dir_len = strlen(home) + strlen(share) + strlen(dir);
path_len = dir_len+1+strlen(file);
sdir = emalloc(path_len+1);
sprintf(sdir, "%s%s%s/%s", home, share, dir, file);
if(access(sdir, F_OK)) {
sdir[dir_len] = '\0';
mkdir(sdir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
sdir[dir_len] = '/';
creat(sdir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
}
db->path = sdir;
return db;
}
int
db_add(DB *db, const char *path, int prog) {
char buf[PATH_MAX+8];
char hbuf[17];
XXH64_hash_t check_hash;
XXH64_hash_t hash;
FILE *f;
hash = get_file_hash(path);
f = efopen(db->path, "r+");
for(;;) {
if(fread(hbuf, 16, 1, f) == 0)
break;
hbuf[16] = '\0';
check_hash = strtoul(hbuf, NULL, 16);
if(check_hash == hash) {
fflush(f);
fprintf(f, " %10d", prog);
fclose(f);
return 0;
}
fgets(buf, sizeof(buf), f);
}
fseek(f, 0, SEEK_END);
fprintf(f, "%016lx %10d %s\n", hash, prog, path);
fclose(f);
return 0;
}
int
db_read(DB *db, const char *path) {
int prog;
XXH64_hash_t check_hash, hash;
char buf[PATH_MAX+8], hbuf[HASH_LEN+1];
FILE *f;
hash = get_file_hash(path);
f = fopen(db->path, "r");
if(!f)
return 0;
while(fread(hbuf, HASH_LEN, 1, f)) {
hbuf[HASH_LEN] = '\0';
check_hash = strtoul(hbuf, NULL, HASH_BASE);
if(check_hash == hash) {
fread(hbuf, PROG_LEN, 1, f);
hbuf[PROG_LEN] = '\0';
prog = (int)strtol(hbuf+1, NULL, PROG_BASE);
fclose(f);
return prog;
}
fgets(buf, sizeof(buf), f);
}
fclose(f);
return 0;
}
void
db_free(DB *db) {
free(db->path);
free(db);
}