7 Commits

Author SHA1 Message Date
3dba3473f8 fix license badge 2025-11-25 22:11:53 +01:00
T. von Dein
3d0ec6bfbc fix release building (#4) 2025-11-23 18:23:49 +01:00
b836a4e75d add dist to clean 2025-11-23 18:01:14 +01:00
a4a3cd470f fix db uri 2025-11-21 22:30:17 +01:00
T. von Dein
f2137627d7 unitfixes (#3)
- fix regex match padding
- fix key copying
- add more unit tests
2025-11-21 22:10:52 +01:00
bb967c68c6 upd version 2025-11-21 14:09:38 +01:00
T. von Dein
ab0d3f8268 fix compileerrors, add tests (#2) 2025-11-21 14:06:32 +01:00
11 changed files with 164 additions and 49 deletions

View File

@@ -12,12 +12,50 @@ steps:
image: alpine:latest image: alpine:latest
commands: commands:
- apk update - apk update
- apk add --no-cache bash build-base words-en gdb perl pcre2 pcre2-dev db db-dev pkgconfig meson ninja - apk add --no-cache bash build-base gdb perl pcre2 pcre2-dev db db-dev pkgconfig meson ninja
- meson setup --reconfigure build - meson setup --reconfigure build
- ninja -C build - ninja -C build
test-berkeley:
when:
event: [push]
image: alpine:latest
commands:
- apk update
- apk add --no-cache bash build-base pcre2 pcre2-dev db db-dev
- rm -f test.db - rm -f test.db
- build/dbtool -d test.db -i -k "test" -v "blah blah blah" # insert keys
- build/dbtool -d test.db -i -k test -v blah
- build/dbtool -d test.db -i -k foo -v bar
# look if the appear in the dump
- build/dbtool -d test.db -D | grep blah - build/dbtool -d test.db -D | grep blah
# count 'em
- build/dbtool -d test.db -D | wc -l | grep 2
# search for key
- build/dbtool -d test.db -s -k test
# search for key regex
- build/dbtool -d test.db -S -k 't$'
# remove key
- build/dbtool -d test.db -r -k foo
# count must match
- build/dbtool -d test.db -D | wc -l | grep 1
# modify a key
- build/dbtool -d test.db -u -k test -v modified
# check modified key
- build/dbtool -d test.db -s -k test | grep modified
# use splitting with regex
- echo today:100 | build/dbtool -d test.db -i -f -t '^([^:]*):([^:]*)'
# check if it works
- build/dbtool -d test.db -s -k today | grep 100
# use splitting with regex reverse
- echo today:cold | build/dbtool -d test.db -R -i -f -t '^([^:]*):([^:]*)'
# check if it works
- build/dbtool -d test.db -s -k cold | grep today
# check encryption
- build/dbtool -d test.db -i -k borg -v sevenofnine -p -P foobar
- build/dbtool -d test.db -s -k borg -p -P foobar | grep sevenofnine
build-gdbm: build-gdbm:
when: when:
@@ -25,9 +63,49 @@ steps:
image: alpine:latest image: alpine:latest
commands: commands:
- apk update - apk update
- apk add --no-cache bash build-base words-en gdb perl pcre2 pcre2-dev gdbm gdbm-dev pkgconfig meson ninja - apk add --no-cache bash build-base perl pcre2 pcre2-dev gdbm gdbm-dev pkgconfig meson ninja
- meson setup --reconfigure build - meson setup --reconfigure build
- ninja -C build - ninja -C build
- rm -f test.db - rm -f test.db
- build/dbtool -d test.db -i -k "test" -v "blah blah blah" - build/dbtool -d test.db -i -k "test" -v "blah blah blah"
- build/dbtool -d test.db -D | grep blah - build/dbtool -d test.db -D | grep blah
test-gdbm:
when:
event: [push]
image: alpine:latest
commands:
- apk update
- apk add --no-cache bash build-base pcre2 pcre2-dev gdbm gdbm-dev
- rm -f test.db
# insert keys
- build/dbtool -d test.db -i -k test -v blah
- build/dbtool -d test.db -i -k foo -v bar
# look if the appear in the dump
- build/dbtool -d test.db -D | grep blah
# count 'em
- build/dbtool -d test.db -D | wc -l | grep 2
# search for key
- build/dbtool -d test.db -s -k test
# search for key regex
- build/dbtool -d test.db -S -k 't$'
# remove key
- build/dbtool -d test.db -r -k foo
# count must match
- build/dbtool -d test.db -D | wc -l | grep 1
# modify a key
- build/dbtool -d test.db -u -k test -v modified
# check modified key
- build/dbtool -d test.db -s -k test | grep modified
# use splitting with regex
- echo today:100 | build/dbtool -d test.db -i -f -t '^([^:]*):([^:]*)'
# check if it works
- build/dbtool -d test.db -s -k today | grep 100
# use splitting with regex reverse
- echo today:cold | build/dbtool -d test.db -R -i -f -t '^([^:]*):([^:]*)'
# check if it works
- build/dbtool -d test.db -s -k cold | grep today
# check encryption
- build/dbtool -d test.db -i -k borg -v sevenofnine -p -P foobar
- build/dbtool -d test.db -s -k borg -p -P foobar | grep sevenofnine

View File

@@ -50,5 +50,5 @@ fi
for file in "$@"; do for file in "$@"; do
https --ignore-stdin --check-status -A bearer -a "$DEPLOY_TOKEN" -f POST \ https --ignore-stdin --check-status -A bearer -a "$DEPLOY_TOKEN" -f POST \
"https://codeberg.org/api/v1/repos/${CI_REPO_OWNER}/${CI_REPO_NAME}/releases/$ID/assets" \ "https://codeberg.org/api/v1/repos/${CI_REPO_OWNER}/${CI_REPO_NAME}/releases/$ID/assets" \
"name=${file}-${version}" "attachment@${file}" "name=${file}" "attachment@${file}"
done done

View File

@@ -6,24 +6,26 @@ labels:
steps: steps:
compile: compile:
when: when:
event: [manual] event: [tag,manual]
image: alpine:latest image: alpine:latest
commands: commands:
- apk update - apk update
- apk add --no-cache bash build-base words-en gdb perl pcre2 pcre2-dev gdbm gdbm-dev pkgconfig meson ninja - apk add --no-cache bash build-base words-en gdb perl pcre2-static pcre2-dev gdbm gdbm-dev pkgconfig meson ninja git
- meson setup --reconfigure --prefer-static build - meson setup --reconfigure --prefer-static -Dcpp_link_args="-static" --buildtype=release build
- ninja -C build - ninja -C build
- meson dist -C build --formats xztar,gztar,zip
- file build/dbtool - file build/dbtool
- mv build/dbtool dbtool-linux-amd64 - mv build/dbtool dbtool-linux-amd64-$CI_COMMIT_TAG
- mv build/meson-dist/* .
release: release:
image: alpine:latest image: alpine:latest
when: when:
event: [manual] event: [tag,manual]
environment: environment:
DEPLOY_TOKEN: DEPLOY_TOKEN:
from_secret: DEPLOY_TOKEN from_secret: DEPLOY_TOKEN
commands: commands:
- apk update - apk update
- apk add --no-cache bash httpie jq git - apk add --no-cache bash httpie jq git
- .woodpecker/release.sh dbtool-linux-amd64 - .woodpecker/release.sh dbtool-*

19
.woodpecker/test.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/bash
yq '.steps.test-gdbm.commands' < .woodpecker/build.yaml \
| grep -- - | grep -v apk | sed 's/^\- //' \
| while read COMMAND; do
echo "$COMMAND" | bash -e > debug.log 2>&1
if test $? -ne 0; then
echo "fail - $COMMAND"
if test -s debug.log; then
cat debug.log
else
echo exit 1
fi
else
echo "ok - $COMMAND"
fi
done
rm -f debug.log

22
Makefile Normal file
View File

@@ -0,0 +1,22 @@
#
# convenience wrapper around meson and ninja. Forgive me, I'm old :
.PHONY: all static install test clean debug
all:
meson setup --reconfigure build
ninja -C build
install: all
sudo ninja -C install
clean:
rm -rf build dbtool*core* dbtool.1 test.db clean
test:
@.woodpecker/test.sh
debug: all
rm -f test.db
build/dbtool -d test.db -i -k borg -v sevenofnine -p -P foobar
build/dbtool -d test.db -s -k borg -p -P foobar

View File

@@ -1,7 +1,7 @@
[![status-badge](https://ci.codeberg.org/api/badges/15585/status.svg)](https://ci.codeberg.org/repos/15585) [![status-badge](https://ci.codeberg.org/api/badges/15585/status.svg)](https://ci.codeberg.org/repos/15585)
[![License](https://img.shields.io/badge/license-GPL-blue.svg)](https://codeberg.org/scip/dbtool/blob/master/LICENSE) [![License](https://img.shields.io/badge/license-GPL-blue.svg)](https://codeberg.org/scip/dbtool/raw/branch/main/LICENSE)
# README for dbtool 1.9.1 (21/11/2025) # README for dbtool 1.9.2 (21/11/2025)
dbtool can be used to store and retrieve data in a key/value dbtool can be used to store and retrieve data in a key/value
format in a hash database. Perl compatible regular expressions format in a hash database. Perl compatible regular expressions
@@ -17,7 +17,7 @@ data and speed.
You need either the GNU gdbm library or the Berkeley database You need either the GNU gdbm library or the Berkeley database
system. You can find gdbm at: system. You can find gdbm at:
http://www.gnu.org/software/gdbm/gdbm.html http://www.gnu.org/software/gdbm/gdbm.html
And the berkeley library at: http://www.sleepycat.com. And the berkeley library at: https://libdb.org/.
You will also need `meson` and `ninja`: https://mesonbuild.com/. You will also need `meson` and `ninja`: https://mesonbuild.com/.

View File

@@ -56,11 +56,8 @@ void cipher::init(const string& phrase) {
dig.initDigest(); dig.initDigest();
dig.putDigest( (unsigned char *)phrase.c_str(), phrase.length() ); dig.putDigest( (unsigned char *)phrase.c_str(), phrase.length() );
__key = dig.stringDigest(); // this is a 32 byte long string, as Rijndael:: expects __key = dig.stringDigest(); // this is a 32 byte long string, as Rijndael:: expects
/* convert the key to unsigned char[] */ memcpy(key, __key, 32);
for(int i=0; i<32; i++) {
key[i] = __key[i];
}
} }

View File

@@ -61,7 +61,6 @@ class cipher {
Rijndael rijn; Rijndael rijn;
MD5Digest dig; MD5Digest dig;
unsigned char key[32]; unsigned char key[32];
string blah;
const char* error(int num); const char* error(int num);
public: public:

View File

@@ -67,8 +67,8 @@ int main(int argc, char *argv[]) {
case 'i': case 'i':
/* insert */ /* insert */
if(config.key == "") { if(config.key == "") {
cerr << pkg << ": key required\n"; cerr << pkg << ": key required\n";
exit(1); exit(1);
} }
engine.insert(); engine.insert();
break; break;
@@ -82,32 +82,32 @@ int main(int argc, char *argv[]) {
case 's': case 's':
/* select */ /* select */
if(config.key == "") { if(config.key == "") {
cerr << pkg << ": key required\n"; cerr << pkg << ": key required\n";
exit(1); exit(1);
} }
engine.select(); engine.select();
break; break;
case 'S': case 'S':
/* regexp select */ /* regexp select */
if(config.key == "") { if(config.key == "") {
cerr << pkg << ": key (regexp) required\n"; cerr << pkg << ": key (regexp) required\n";
exit(1); exit(1);
} }
engine.regexp(); engine.regexp();
break; break;
case 'r': case 'r':
/* remove */ /* remove */
if(config.key == "") { if(config.key == "") {
cerr << pkg << ": key required\n"; cerr << pkg << ": key required\n";
exit(1); exit(1);
} }
engine.remove(); engine.remove();
break; break;
case 'u': case 'u':
/* update */ /* update */
if(config.key == "") { if(config.key == "") {
cerr << pkg << ": key required\n"; cerr << pkg << ": key required\n";
exit(1); exit(1);
} }
engine.update(); engine.update();
break; break;
@@ -125,7 +125,6 @@ int main(int argc, char *argv[]) {
} }
string readpass() { string readpass() {
char *envpass; char *envpass;
envpass = getenv(PW_VARNAME); envpass = getenv(PW_VARNAME);
@@ -146,5 +145,3 @@ string readpass() {
return password; return password;
} }
} }

View File

@@ -315,8 +315,7 @@ void Engine::regexp() {
// record end // record end
mode = "key"; mode = "key";
if(config.token != "") { if(config.token != "") {
//char **subs = new char*[2]; string *subs = new string[2];
char *subs[2];
num = pcre2_match(p_pcre, (PCRE2_SPTR)line.c_str(), (PCRE2_SIZE)line.length(), 0, 0, match_data, NULL); num = pcre2_match(p_pcre, (PCRE2_SPTR)line.c_str(), (PCRE2_SIZE)line.length(), 0, 0, match_data, NULL);
@@ -326,19 +325,21 @@ void Engine::regexp() {
cerr << "Token " << config.token << " did not produce sub strings!\n"; cerr << "Token " << config.token << " did not produce sub strings!\n";
else { else {
ovector = pcre2_get_ovector_pointer(match_data); ovector = pcre2_get_ovector_pointer(match_data);
const char *constline = const_cast<char*>(line.c_str());
for (int i = 0; i < num; i++) { for (int i = 1; i < num; i++) {
char * substring_start = const_cast<char*>(line.c_str()) + ovector[2*i]; PCRE2_SPTR substring_start = (PCRE2_SPTR8)constline + ovector[2*i];
PCRE2_SIZE substring_length = ovector[2*i+1] - ovector[2*i];
if (i == 2) { char *part = (char *)malloc(substring_length+1);
break; part = strncpy(part, (char *)substring_start, substring_length);
} part[substring_length] = '\0';
subs[i] = substring_start; subs[i-1] = part;
free(part);
} }
free(ovector);
if(config.reverse) { if(config.reverse) {
value = subs[0]; value = subs[0];
key = subs[1]; key = subs[1];
@@ -349,9 +350,8 @@ void Engine::regexp() {
} }
} }
//delete(subs); delete[] subs;
line = ""; line = "";
} }
value = encode(value); value = encode(value);
@@ -563,8 +563,9 @@ void Engine::regexp() {
*/ */
void Engine::remove() { void Engine::remove() {
init(); init();
#ifdef HAVE_BERKELEY #ifdef HAVE_BERKELEY
Dbt key((char *)config.key.c_str(), config.key.length() + 1); char *k = (char *)config.key.c_str();
Dbt key(k, strlen(k));
int ret; int ret;
if((ret = db->del(NULL, &key, 0)) != 0) { if((ret = db->del(NULL, &key, 0)) != 0) {
cerr << "Database error" << "(" << strerror(ret) << ")" << endl; cerr << "Database error" << "(" << strerror(ret) << ")" << endl;

View File

@@ -2,7 +2,7 @@ project(
'dbtool', 'dbtool',
'cpp', 'cpp',
license: 'GPL', license: 'GPL',
version: '1.9.1', version: '1.9.3',
meson_version: '>=1.3', meson_version: '>=1.3',
default_options: [ default_options: [
'warning_level=2', 'warning_level=2',