-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathsimpledb.c
More file actions
146 lines (129 loc) · 3.72 KB
/
Copy pathsimpledb.c
File metadata and controls
146 lines (129 loc) · 3.72 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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include "simpledb.h"
#include <zlib.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
static const size_t HASH_SIZE = sizeof(uLong);
enum err item_read_f(FILE *fp, struct dbitem *item)
{
uint8_t buffer[sizeof(*item) + HASH_SIZE];
if (sizeof(buffer) != fread(buffer, 1, sizeof(buffer), fp))
return E_FREAD;
uLong crc_file = *(uLong *)buffer;
uLong crc_calc = crc32(0, buffer + HASH_SIZE, sizeof(*item));
dbg("CRC calc=0x%lX file=0x%lX", crc_calc, crc_file);
if (crc_file != crc_calc)
return E_WRONGCRC;
memcpy(item, buffer + HASH_SIZE, sizeof(*item)); /* ! buffer[] won't exist after exit */
return E_OK;
}
enum err item_write_f(FILE *fp, struct dbitem *item)
{
uint8_t buffer[sizeof(*item)];
memcpy(buffer, item, sizeof(*item));
uLong crc_calc = crc32(0, buffer, sizeof(*item));
if (sizeof crc_calc != fwrite(&crc_calc, 1, sizeof crc_calc, fp))
return E_FWRITE;
if (sizeof *item != fwrite(item, 1, sizeof *item, fp))
return E_FWRITE;
return E_OK;
}
/* Here function pointer is utilized for code reuse */
static inline enum err _item_do(enum err (*func)(FILE *, struct dbitem *),
const char *pathname, struct dbitem *item)
{
enum err retcode = E_OK;
FILE *fp = xopen(pathname, "r+");
if (fp == NULL)
return E_FOPEN;
retcode = (*func)(fp, item);
fclose(fp);
return retcode;
}
/* No need for copy-paste. Code is reused */
enum err item_read(const char *pathname, struct dbitem *item)
{
return _item_do(&item_read_f, pathname, item);
}
/* Read kernel CodingStyle, ch. 12 for inline caveats */
enum err item_write(const char *pathname, struct dbitem *item)
{
return _item_do(&item_write_f, pathname, item);
}
char *m_strjoin(const char *delimeter, const char *str1, const char *str2)
{
unsigned long len = strlen(delimeter)+strlen(str1)+strlen(str2)+1;
char *res = malloc(MB_CUR_MAX * len * sizeof(*res));
if (NULL != res) {
strcpy(res, str1);
strcat(res, delimeter);
strcat(res, str2);
}
dbg("Generated path %s", res);
return res;
}
enum err item_remove_bykey(const char *key, const char *dir)
{
enum err errlevel = E_OK;
char *path = m_strjoin("/", dir, key);
if (NULL == path) {
errlevel = E_OSERR;
goto cleanup_item_remove;
};
if (remove(path) < 0)
errlevel = (EPERM == errno || ENOENT == errno) ? E_FNAME : E_OSERR;
/* We need to free memory allocated. That's why it's so nasty. */
/* In the end, that is the way of working with strings in C */
cleanup_item_remove:
free(path);
return errlevel;
}
/* A filter function to leave only the files in resulting directory list
* used in item_listdir below */
inline static int _onlyfiles_filter(const struct dirent * dir)
{
return DT_REG == (dir->d_type);
}
/* see man man 3 scandir, man dirent.h, man 3 readdir */
enum err listdir(const char *dirname, struct strvec *vector)
{
enum err errlevel = E_OK;
struct dirent **namelist;
int n = scandir(dirname, &namelist, &_onlyfiles_filter, alphasort);
if (n < 0) {
errlevel = E_OSERR;
goto cleanup_item_listdir;
}
vector->vec = malloc(n * sizeof *vector->vec);
if(NULL == vector->vec) {
errlevel = E_OSERR;
goto namelist_dealloc;
}
/* Copy contents to vec. If error occurs, stop copy and stick with what we have */
int i;
for (i = 0; i < n; i++) {
vector->vec[i] = strdup(namelist[i]->d_name);
if (NULL == vector->vec[i]) break;
}
vector->n = i;
if (i != n)
errlevel = E_OSERR;
cleanup_item_listdir:
while (n--)
free(namelist[n]);
namelist_dealloc:
free(namelist);
return errlevel;
}
FILE *xopen(const char *pathname, const char *mode)
{
int fd = open(pathname, O_RDWR | O_CREAT, 0666); /* "a+" + creation */
if (fd < 0)
return NULL;
return fdopen(fd, mode);
}