// This is going to be slow since it is a search by value. I.e. it // walks through the entire CDB sequentially trying to map a value // back to its key. Therefore it should only be used in debug or // error scenarios. static CCS _shop_find_cmdline(shopping_state_s *ssp, CCS cmdix) { unsigned loc = 0; cdb_seqinit(&loc, ssp->cdbp); while (cdb_seqnext(&loc, ssp->cdbp) > 0) { unsigned len; CS cmdstate, ix; len = cdb_datalen(ssp->cdbp); cmdstate = (CS)alloca(len + 1); cdb_read(ssp->cdbp, cmdstate, len, cdb_datapos(ssp->cdbp)); cmdstate[len] = '\0'; if ((ix = util_strsep(&cmdstate, FS1)) && !strcmp(cmdix, ix)) { CS line; len = cdb_keylen(ssp->cdbp); line = (CS)putil_malloc(len + 1); cdb_read(ssp->cdbp, line, len, cdb_keypos(ssp->cdbp)); line[len] = '\0'; return line; } } return NULL; }
int main(int argc, char **argv) { int c, fd, fdtemp; size_t klen, len = 0; char *dbfile, *dbnewfile, *dbtemp, *dirname = NULL; char *key; unsigned cpos; struct cdb cdbm; struct cdb_make cdbn; struct record rec; progname = basename(argv[0]); struct option long_options[] = { { "help", no_argument, 0, 'h' }, { "dbpath", required_argument, 0, 'D' }, { 0, 0, 0, 0 } }; if (argc == 1) print_help(EXIT_SUCCESS); while ((c = getopt_long (argc, argv, "hD:", long_options, NULL)) != -1) { switch (c) { case 'D': db_path = optarg; break; default: case 'h': print_help(EXIT_SUCCESS); break; } } if (db_path == NULL) db_path = def_db_path; if (optind == argc) print_help(EXIT_FAILURE); dbfile = argv[optind]; // Open old database if ((fd = open(dbfile, O_RDONLY | O_NOFOLLOW | O_NOCTTY)) == -1) osec_fatal(EXIT_FAILURE, errno, "%s: open", dbfile); if (compat_db_version(fd)) { printf("%s: Database already in new format\n", dbfile); return EXIT_SUCCESS; } if (cdb_init(&cdbm, fd) < 0) osec_fatal(EXIT_FAILURE, errno, "cdb_init(cdbm)"); // Generate new state database len = strlen(dbfile) + 11; dbtemp = (char *) xmalloc(sizeof(char) * len); sprintf(dbtemp, "%s.XXXXXXXXX", dbfile); // Open new database if ((fdtemp = mkstemp(dbtemp)) == -1) osec_fatal(EXIT_FAILURE, errno, "%s: mkstemp", dbtemp); if (cdb_make_start(&cdbn, fdtemp) < 0) osec_fatal(EXIT_FAILURE, errno, "cdb_make_start"); // Allocate buffer for reading files. read_bufsize = (size_t) (sysconf(_SC_PAGE_SIZE) - 1); read_buf = xmalloc(read_bufsize); /* * Set default data buffer. This value will increase in the process of * creating a database. */ rec.len = 1024; rec.data = xmalloc(rec.len); cdb_seqinit(&cpos, &cdbm); while(cdb_seqnext(&cpos, &cdbm) > 0) { char *type; klen = cdb_keylen(&cdbm); key = (char *) xmalloc((size_t) (klen + 1)); if (cdb_read(&cdbm, key, (unsigned) klen, cdb_keypos(&cdbm)) < 0) osec_fatal(EXIT_FAILURE, errno, "cdb_read"); key[klen] = '\0'; if ((type = strchr(key, '\0')) == (key + klen)) osec_fatal(EXIT_FAILURE, errno, "strchr: Cant find type\n"); klen = strlen(key); type += 1; if (strcmp(type, "stat") == 0) { struct stat st; rec.offset = 0; if (cdb_read(&cdbm, &st, (unsigned) sizeof(st), cdb_datapos(&cdbm)) < 0) osec_fatal(EXIT_FAILURE, errno, "cdb_read"); osec_empty_digest(&rec); osec_empty_symlink(&rec); osec_state(&rec, &st); if (cdb_make_add(&cdbn, key, (unsigned) klen+1, rec.data, (unsigned) rec.offset) != 0) osec_fatal(EXIT_FAILURE, errno, "%s: cdb_make_add", key); } xfree(key); } write_db_version(&cdbn); xfree(rec.data); if (cdb_make_finish(&cdbn) < 0) osec_fatal(EXIT_FAILURE, errno, "cdb_make_finish"); if (close(fdtemp) == -1) osec_fatal(EXIT_FAILURE, errno, "%s: close", dbtemp); if (close(fd) == -1) osec_fatal(EXIT_FAILURE, errno, "%s: close", dbfile); dirname = decode_dirname(dbfile); gen_db_name(dirname, &dbnewfile); rename(dbtemp, dbnewfile); remove(dbfile); xfree(dbtemp); xfree(dirname); xfree(dbnewfile); return EXIT_SUCCESS; }