TDB_FIRSTKEY(3)
π TDB_FIRSTKEY β okay bestie, let's talk database keys π
This is the tdb_firstkey and tdb_nextkey page from the Linux Programmer's Manual, and no cap, it's shorter than you think but there's lore. Sit down, hydrate, we're traversing a tdb database together. π¦
β¨ NAME β¨
tdb_firstkey β gives you the key of the first record in a tdb database
tdb_nextkey β gives you the key of the next record in the tdb database
πΈ SYNOPSIS πΈ
#include <tdb.h>
TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb);
TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA prev_key);
π DESCRIPTION π
Okay so here's the vibe. tdb_firstkey fetches the key of the very first entry in the tdb database. Then tdb_nextkey fetches the key of the entry that comes immediately after prev_key in the database. It's giving "start here, then keep going." π₯
The TDB_DATA structure that both of these functions hand back is defined like this:
typedef struct {
char *dptr;
size_t dsize;
} TDB_DATA;
Now the part that trips people up, bestie: the order it walks the database in is its own internal hash order. Do not expect the keys to come out in any recognizably sorted order. They will not. It's not sorted, it was never sorted, and it's not going to start being sorted for you. π
Here's the good news though: these functions are reliable even if other writers are hitting the database β or even if you're replacing or deleting elements while you traverse. Iconic. Resilient. We love that.
EXCEPT. And this is the big one. They are not safe when you nest tdb_firstkey or tdb_nextkey calls inside each other. Like, at all. Check out this outer traversal β it may fail to traverse all the elements, or it may even traverse some elements twice, if other processes are manipulating the database at the same time:
TDB_DATA i, j;
for (i = tdb_firstkey(tdb); i.dptr; i = tdb_nextkey(tdb, i)) {
for (j = tdb_firstkey(tdb); j.dptr; j = tdb_nextkey(tdb, j)) {
...
}
}
π¨ Nested traversal = chaos. You might miss entries, you might see entries twice. Do not do this and then act surprised.
If that nested behaviour is actually what you want, use tdb_traverse instead. That's the one that's built for it. Periodt. π
π RETURN VALUE π
If the call succeeds, you get a TDB_DATA structure back with the dptr field filled in. If the call fails, or you've hit the end of the database, then dptr gets set to NULL.
β οΈ NOTE: the caller is responsible for freeing the data pointed to by dptr
That means you. You are the caller. Free it. π«Ά
π AUTHORS π
- Software: Andrew Tridgell
<tridge@linuxcare.com>and Luke Kenneth Casson Leighton - Man page: Ben Woodard
<ben@valinux.com>
π SEE ALSO π
And that's the whole page, bestie! This came to you courtesy of Samba, dated Aug 16, 2000 β yes, the man page is older than most of us, and it's still out here working. Respect the elders. πβ¨π
π¦ where this page comes from
- debian trixie: libtdb-dev 2:1.4.13+samba4.22.10+dfsg-0+deb13u2 Β· GPL-3.0-or-later
- debian trixie: libtdb-dev 2:1.4.13+samba4.22.11+dfsg-0+deb13u1 Β· GPL-3.0-or-later
- ubuntu questing: libtdb-dev 2:1.4.13+samba4.22.3+dfsg-4ubuntu2
- ubuntu questing: libtdb-dev 2:1.4.13+samba4.22.3+dfsg-4ubuntu2.4
- ubuntu resolute: libtdb-dev 2:1.4.14+samba4.23.6+dfsg-1ubuntu2 Β· GPL-3.0-or-later
- ubuntu resolute: libtdb-dev 2:1.4.14+samba4.23.6+dfsg-1ubuntu2.2 Β· GPL-3.0-or-later
- ubuntu stonking: libtdb-dev 2:1.4.15+samba4.24.7+dfsg-1ubuntu1 Β· GPL-3.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms