Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <errno.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- static const char *dpath = "db.db";
- static int db_fd;
- static char *db_buf;
- static size_t db_len;
- static int keys(void);
- static int get(const char *key);
- static int set(const char *key, const char *value);
- static int delete(const char *key);
- static int readdb(void);
- static int openerr(void);
- static void setval(const char *value);
- int main(int argc, const char **argv) {
- if(argc >= 2) goto nousage;
- usage:
- fprintf(stderr,
- "usage: %s\n"
- " get <key>\n"
- " set <key> <value>\n"
- " delete <key>\n"
- " keys\n",
- argv[0]);
- return 1;
- nousage:
- if(!strcmp(argv[1], "keys")) return keys();
- if(argc < 3) goto usage;
- if(!strcmp(argv[1], "get")) return get(argv[2]);
- if(!strcmp(argv[1], "set")) return set(argv[2], argc >= 4 ? argv[3] : NULL);
- if(!strcmp(argv[1], "delete")) return delete(argv[2]);
- goto usage;
- }
- static int keys(void) {
- int ret;
- if(ret = readdb()) return ret;
- char *pos = db_buf;
- char *end = db_buf + db_len;
- loop:;
- if(pos >= end) goto end;
- size_t keylen = *(size_t *)pos;
- pos += 8;
- fwrite(pos, keylen, 1, stdout);
- putchar('\n');
- pos += keylen;
- size_t vallen = *(size_t *)pos;
- pos += 8 + vallen;
- goto loop;
- end:;
- return 0;
- }
- static int get(const char *key) {
- int ret;
- if(ret = readdb()) return ret;
- char *pos = db_buf;
- char *end = db_buf + db_len;
- size_t keylen, vallen;
- loop:;
- if(pos >= end) goto end;
- keylen = *(size_t *)pos;
- if(keylen != strlen(key)) goto next;
- pos += 8;
- if(memcmp(key, pos, keylen)) goto next2;
- pos += keylen;
- vallen = *(size_t *)pos;
- pos += 8;
- fwrite(pos, vallen, 1, stdout);
- return 0;
- next:;
- pos += 8;
- next2:;
- pos += keylen;
- vallen = *(size_t *)pos;
- pos += 8 + vallen;
- goto loop;
- end:;
- fprintf(stderr, "no such key\n");
- return 1;
- }
- static int set(const char *key, const char *value) {
- int ret;
- if(ret = readdb()) return ret;
- char *pos = db_buf;
- char *end = db_buf + db_len;
- char *last;
- size_t keylen, vallen;
- loop:;
- if(pos >= end) goto new;
- last = pos;
- keylen = *(size_t *)pos;
- if(keylen != strlen(key)) goto next;
- pos += 8;
- if(memcmp(key, pos, keylen)) goto next2;
- pos += keylen;
- ftruncate(db_fd, pos - db_buf);
- lseek(db_fd, 0, SEEK_END);
- setval(value);
- vallen = *(size_t *)pos;
- pos += 8 + vallen;
- write(db_fd, pos, end - pos);
- return 0;
- next:;
- pos += 8;
- next2:;
- pos += keylen;
- vallen = *(size_t *)pos;
- pos += 8 + vallen;
- goto loop;
- new:;
- keylen = strlen(key);
- write(db_fd, &keylen, 8);
- write(db_fd, key, keylen);
- setval(value);
- return 0;
- }
- static int delete(const char *key) {
- int ret;
- if(ret = readdb()) return ret;
- char *pos = db_buf;
- char *end = db_buf + db_len;
- char *last;
- size_t keylen, vallen;
- loop:;
- if(pos >= end) goto end;
- last = pos;
- keylen = *(size_t *)pos;
- if(keylen != strlen(key)) goto next;
- pos += 8;
- if(memcmp(key, pos, keylen)) goto next2;
- pos += keylen;
- ftruncate(db_fd, last - db_buf);
- lseek(db_fd, 0, SEEK_END);
- vallen = *(size_t *)pos;
- pos += 8 + vallen;
- write(db_fd, pos, end - pos);
- return 0;
- next:;
- pos += 8;
- next2:;
- pos += keylen;
- vallen = *(size_t *)pos;
- pos += 8 + vallen;
- goto loop;
- end:;
- fprintf(stderr, "no such key\n");
- return 1;
- }
- static int readdb(void) {
- db_fd = open(dpath, O_RDWR | O_CREAT, 0644);
- if(db_fd < 0) return openerr();
- db_len = lseek(db_fd, 0, SEEK_END);
- lseek(db_fd, 0, SEEK_SET);
- db_buf = malloc(db_len);
- if(!db_buf) return openerr();
- read(db_fd, db_buf, db_len);
- return 0;
- }
- static int openerr(void) {
- fputs(strerror(errno), stderr);
- putc('\n', stderr);
- return 2;
- }
- static void setval(const char *value) {
- size_t vallen;
- if(!value) goto fromstdin;
- vallen = strlen(value);
- write(db_fd, &vallen, 8);
- write(db_fd, value, vallen);
- return;
- fromstdin:;
- vallen = 0;
- char buf[512];
- size_t n;
- write(db_fd, &vallen, 8);
- off_t pos = lseek(db_fd, 0, SEEK_CUR);
- loop:;
- n = fread(buf, 1, 512, stdin);
- if(!n) goto end;
- write(db_fd, buf, n);
- goto loop;
- end:;
- off_t end = lseek(db_fd, 0, SEEK_CUR);
- lseek(db_fd, pos - 8, SEEK_SET);
- vallen = end - pos;
- write(db_fd, &vallen, 8);
- lseek(db_fd, end, SEEK_SET);
- }
Advertisement
Add Comment
Please, Sign In to add comment