1 #define _LARGEFILE64_SOURCE
2 #define _XOPEN_SOURCE 500
18 #define LOGMAGIC "Dolda/Venti-1"
19 #define IDXMAGIC "Dolda/Index-1"
20 #define LOGENTMAGIC "\xca\xe5\x7a\x93"
25 char magic[sizeof(LOGMAGIC)];
29 char magic[sizeof(IDXMAGIC)];
53 static int release(struct fstore *fst)
67 static int releaseg(struct store *st)
69 return(release(st->pdata));
72 static void hash(const void *buf, size_t len, struct addr *a)
74 gcry_md_hash_buffer(GCRY_MD_SHA256, a->hash, buf, len);
77 static int getidx(struct fstore *fst, idx_t i, struct idxent *ie)
79 return(readall(fst->idxfd, ie, sizeof(*ie), sizeof(struct idxhdr) + i * sizeof(struct idxent)));
82 static int putidx(struct fstore *fst, idx_t i, struct idxent *ie)
84 return(writeall(fst->idxfd, ie, sizeof(*ie), sizeof(struct idxhdr) + i * sizeof(struct idxent)));
87 static idx_t lookup(struct fstore *fst, struct addr *a, idx_t *parent)
93 if(fst->idxsize == 0) {
100 assert(!getidx(fst, i, &ie));
101 c = addrcmp(a, &ie.addr);
122 static idx_t newindex(struct fstore *fst)
129 /* XXX: Thread safety */
131 newsize = sizeof(struct idxhdr) + fst->idxsize * sizeof(struct idxent);
132 if(ftruncate(fst->idxfd, newsize))
135 assert(!putidx(fst, ni, &ne));
136 assert(!readall(fst->idxfd, &ih, sizeof(ih), 0));
137 ih.size = fst->idxsize;
138 assert(!writeall(fst->idxfd, &ih, sizeof(ih), 0));
142 static int put(struct store *st, const void *buf, size_t len, struct addr *at)
152 if(len > STORE_MAXBLSZ) {
160 memcpy(at->hash, pa.hash, 32);
162 if(lookup(fst, &pa, &pi) != -1)
165 memcpy(le.magic, LOGENTMAGIC, 4);
169 /* XXX: Thread safety { */
170 leoff = fst->logsize;
171 fst->logsize += sizeof(le) + len;
173 /* XXX: Handle data with embedded LOGENTMAGIC */
174 writeall(fst->logfd, &le, sizeof(le), leoff);
175 writeall(fst->logfd, buf, len, leoff + sizeof(le));
178 assert(!getidx(fst, i, &ie));
181 assert(!putidx(fst, i, &ie));
183 assert(!getidx(fst, pi, &ie));
184 c = addrcmp(&pa, &ie.addr);
189 assert(!putidx(fst, pi, &ie));
195 #define min(a, b) (((b) < (a))?(b):(a))
197 static ssize_t get(struct store *st, void *buf, size_t len, struct addr *at)
204 char tmpbuf[STORE_MAXBLSZ];
207 if((i = lookup(fst, at, NULL)) == -1) {
211 assert(!getidx(fst, i, &ie));
213 if(readall(fst->logfd, &le, sizeof(le), ie.off)) {
214 flog(LOG_CRIT, "could not read log entry: %s", strerror(errno));
218 if(memcmp(le.magic, LOGENTMAGIC, 4)) {
219 flog(LOG_CRIT, "invalid magic in log");
223 if(addrcmp(&le.name, at)) {
224 flog(LOG_CRIT, "did not receive correct block from log");
228 if(readall(fst->logfd, tmpbuf, le.len, ie.off + sizeof(le))) {
229 flog(LOG_CRIT, "could not read log data: %s", strerror(errno));
233 hash(tmpbuf, le.len, &v);
234 if(addrcmp(&v, &le.name)) {
235 flog(LOG_CRIT, "log data did not verify against hash");
240 memcpy(buf, tmpbuf, min(len, le.len));
244 static struct storeops fstops = {
250 struct store *newfstore(char *dir)
259 fst = calloc(1, sizeof(*fst));
263 snprintf(tbuf, sizeof(tbuf), "%s/log", dir);
264 if((fst->logfd = open(tbuf, O_RDWR | O_LARGEFILE)) < 0) {
265 flog(LOG_ERR, "could not open log %s: %s", tbuf, strerror(errno));
269 if(fstat64(fst->logfd, &sb)) {
270 flog(LOG_ERR, "could not stat log: %s", strerror(errno));
274 fst->logsize = sb.st_size;
275 if(readall(fst->logfd, &lh, sizeof(lh), 0)) {
276 flog(LOG_ERR, "could not read log header: %s", strerror(errno));
280 if(memcmp(lh.magic, LOGMAGIC, sizeof(LOGMAGIC))) {
281 flog(LOG_ERR, "invalid log magic");
286 snprintf(tbuf, sizeof(tbuf), "%s/index", dir);
287 if((fst->idxfd = open(tbuf, O_RDWR | O_LARGEFILE)) < 0) {
288 flog(LOG_ERR, "could not open index %s: %s", tbuf, strerror(errno));
292 if(fstat64(fst->idxfd, &sb)) {
293 flog(LOG_ERR, "could not stat index: %s", strerror(errno));
297 if(readall(fst->idxfd, &ih, sizeof(ih), 0)) {
298 flog(LOG_ERR, "could not read index header: %s", strerror(errno));
302 if(memcmp(ih.magic, IDXMAGIC, sizeof(IDXMAGIC))) {
303 flog(LOG_ERR, "invalid index magic");
307 if(sb.st_size != (sizeof(struct idxhdr) + ih.size * sizeof(struct idxent))) {
308 flog(LOG_ERR, "invalid index size");
312 fst->idxsize = ih.size;
314 st = newstore(&fstops);
319 int mkfstore(char *dir)
326 if(access(dir, F_OK)) {
327 if(mkdir(dir, 0700)) {
328 flog(LOG_ERR, "could not create %s: %s", dir, strerror(errno));
333 snprintf(tbuf, sizeof(tbuf), "%s/log", dir);
334 if((fd = open(tbuf, O_WRONLY | O_CREAT | O_EXCL, 0600)) < 0) {
335 flog(LOG_ERR, "could not create log %s: %s", tbuf, strerror(errno));
338 memcpy(lh.magic, LOGMAGIC, sizeof(LOGMAGIC));
339 if(writeall(fd, &lh, sizeof(lh), 0)) {
340 flog(LOG_ERR, "could not write log header: %s", strerror(errno));
346 snprintf(tbuf, sizeof(tbuf), "%s/index", dir);
347 if((fd = open(tbuf, O_WRONLY | O_CREAT | O_EXCL, 0600)) < 0) {
348 flog(LOG_ERR, "could not create index %s: %s", tbuf, strerror(errno));
351 memcpy(ih.magic, IDXMAGIC, sizeof(IDXMAGIC));
353 if(writeall(fd, &ih, sizeof(ih), 0)) {
354 flog(LOG_ERR, "could not write index header: %s", strerror(errno));