10 #include <ashd/utils.h>
15 static struct charvbuf files;
16 static int verbose = 0;
18 static void opendb(char *path, int pagesize)
23 envpath = strdup(path);
24 if((p = strrchr(envpath, '/')) == NULL) {
26 envpath = strdup(".");
30 if((ret = db_env_create(&env, 0)) != 0) {
31 fprintf(stderr, "statdbput: could not create db environment handle: %s\n", db_strerror(ret));
34 if((ret = env->open(env, envpath, DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN, 0666)) != 0) {
35 fprintf(stderr, "statdbput: environment %s: %s\n", envpath, db_strerror(ret));
38 env->set_lk_detect(env, DB_LOCK_RANDOM);
39 if((ret = db_create(&db, env, 0)) != 0) {
40 fprintf(stderr, "statdbput: could not create db handle: %s\n", db_strerror(ret));
44 if((ret = db->set_pagesize(db, pagesize)) != 0) {
45 fprintf(stderr, "statdbput: could not set db page size (to %i): %s", pagesize, db_strerror(ret));
49 if((ret = db->open(db, NULL, path, NULL, DB_HASH, DB_AUTO_COMMIT | DB_CREATE, 0666)) != 0) {
50 fprintf(stderr, "statdbput: %s: %s\n", path, db_strerror(ret));
55 static void bufcatbe(struct charbuf *buf, intmax_t num, int nb)
59 bufcatbe(buf, num >> 8, nb - 1);
60 bufadd(*buf, (uint8_t)(num & 0xff));
63 static int dofile2(int fd, char *name, time_t mtime, char *ctype)
71 bufcatbe(&buf, mtime, 8);
72 bufcatstr2(buf, ctype);
74 sizebuf(buf, buf.d + 4096);
75 if((ret = read(fd, buf.b + buf.d, buf.s - buf.d)) < 0) {
76 fprintf(stderr, "statdbput: %s: %s\n", name, strerror(errno));
84 k = (DBT){.data = name, .size = strlen(name)};
85 v = (DBT){.data = buf.b, .size = buf.d};
86 ret = db->put(db, txn, &k, &v, 0);
89 if(ret == DB_LOCK_DEADLOCK)
91 fprintf(stderr, "statdbput: %s: %s\n", name, db_strerror(ret));
95 fprintf(stderr, "put: %s\n", name);
100 static int dofile(char *path, char *name, char *ctype)
106 if((fd = open(path, O_RDONLY)) < 0) {
107 fprintf(stderr, "statdbput: %s: %s\n", path, strerror(errno));
111 fprintf(stderr, "statdbput: %s: %s\n", path, strerror(errno));
116 if((p = strrchr(path, '/')) != NULL)
121 ret = dofile2(fd, name, sb.st_mtime, ctype);
124 bufadd(files, sstrdup(path));
128 static int dodir(char *path, char *ctype)
134 struct charbuf fnbuf;
136 if((dir = opendir(path)) == NULL) {
137 fprintf(stderr, "statdbput: %s: %s\n", path, strerror(errno));
142 while((dent = readdir(dir)) != NULL) {
144 bprintf(&fnbuf, "%s/%s", path, dent->d_name);
146 if(stat(fnbuf.b, &sb)) {
147 fprintf(stderr, "statdbput: %s: %s\n", fnbuf.b, strerror(errno));
151 if(S_ISREG(sb.st_mode)) {
152 ret = dofile(fnbuf.b, NULL, ctype);
164 static void usage(FILE *out)
166 fprintf(out, "usage: statdbput [-hvD] [-P PAGESIZE] [-n NAME] DB CONTENT-TYPE {FILE|-}...\n");
167 fprintf(out, " statdbput [-hvD] [-P PAGESIZE] [-d] DB CONTENT-TYPE DIR...\n");
170 int main(int argc, char **argv)
174 char *name, *ctype, *dbpath;
180 while((c = getopt(argc, argv, "+hvDdn:P:")) >= 0) {
195 pagesize = atoi(optarg);
205 if(optind > argc - 3) {
209 dbpath = argv[optind++];
210 ctype = argv[optind++];
211 opendb(dbpath, pagesize);
213 if((ret = env->txn_begin(env, NULL, &txn, 0)) != 0) {
214 fprintf(stderr, "statdbput: could not begin transaction in %s: %s\n", dbpath, db_strerror(ret));
222 for(a = optind; a < argc; a++) {
223 ret = dodir(argv[a], ctype);
230 for(a = optind; a < argc; a++) {
231 if(!strcmp(argv[a], "-")) {
233 fprintf(stderr, "statdbput: must give -n when putting stdin\n");
236 ret = dofile2(0, name, time(NULL), ctype);
239 ret = dofile(argv[a], name, ctype);
249 fprintf(stderr, "deadlocked, restarting and trying again\n");
250 for(i = 0; i < files.d; i++)
258 if((ret = txn->commit(txn, 0)) != 0) {
259 fprintf(stderr, "statdbput: could not commit transaction in %s: %s\n", dbpath, db_strerror(ret));
267 for(i = 0; i < files.d; i++) {
269 fprintf(stderr, "unlink %s\n", files.b[i]);
270 if(unlink(files.b[i]))
271 fprintf(stderr, "statdbput: unlink %s: %s\n", files.b[i], strerror(errno));