I/O · Classes and OO

dbmopen#

Bind a DBM file on disk to a hash so hash reads and writes become lookups and stores in the database.

dbmopen is the old-style way to tie a hash to a dbm, ndbm, sdbm, gdbm, or Berkeley DB file. It has been largely superseded by tie with an explicit DBM backend module (DB_File, GDBM_File, SDBM_File, NDBM_File, AnyDBM_File), which gives you control over which implementation is used and over per-backend options. Reach for dbmopen when you are reading legacy code or when the one-liner brevity matters more than backend choice.

Unlike open, the first argument is not a filehandle — it is the hash that will be bound. HASH is written with the % sigil.

Synopsis#

dbmopen %HASH, $DBNAME, $MASK
dbmopen(%HASH, $DBNAME, 0)       # open existing only; never create
dbmclose %HASH                   # or: untie %HASH

What you get back#

A true value on success, a false value on failure. On failure $! is set to the system error that prevented the bind. The common failure cases are “database does not exist and MASK is 0” and permission errors on the backing files.

dbmopen(%cache, $path, 0)
    or die "cache $path missing or unreadable: $!";

After a successful call, %HASH behaves like any other hash: $HASH{key} = $value writes to the database, $HASH{key} reads from it, delete removes an entry, exists tests membership, and each / keys / values iterate. The data lives on disk; the hash is only a view.

Arguments#

  • HASH — the hash variable to bind. Must be written with %. Any existing contents are discarded. The hash stays bound until dbmclose or untie is called on it, or until it goes out of scope.

  • DBNAME — the database pathname without the backend’s file extension. Traditional dbm / sdbm stores use two files named `DBNAME.dir` and `DBNAME.pag`; gdbm and Berkeley DB use a single file. Passing "/var/lib/app/cache" opens /var/lib/app/cache.dir + /var/lib/app/cache.pag under sdbm, or /var/lib/app/cache under gdbm.

  • MASK — creation mode for any files that have to be created, in the same form as the third argument to chmod (typically an octal literal like 0666 or 0644). The active umask is applied to MASK, so real on-disk permissions are MASK & ~umask. A MASK of 0 suppresses creation: if the database does not already exist, dbmopen returns false and $! is set.

Global state it touches#

  • $! — set on failure (database missing, permission denied, backing store corrupt).

  • The active umask — masks MASK when new backing files are created.

Examples#

Open a history database, iterate with each, then close:

dbmopen(%HIST, '/usr/lib/news/history', 0666)
    or die "open history: $!";
while (my ($key, $val) = each %HIST) {
    print $key, ' = ', unpack('L', $val), "\n";
}
dbmclose %HIST;

Open read-only, refusing to create the database:

dbmopen(%cache, "$ENV{HOME}/.app/cache", 0)
    or die "no cache at $ENV{HOME}/.app/cache: $!";
my $hit = $cache{$key};
dbmclose %cache;

Pick a specific backend by loading its module before calling dbmopen. AnyDBM_File consults @AnyDBM_File::ISA to decide which implementation dbmopen uses:

use DB_File;
dbmopen(%NS_Hist, "$ENV{HOME}/.netscape/history.db", 0644)
    or die "open netscape history: $!";

Write-protected database — assignment silently fails (or croaks depending on the backend); guard with eval when you need to probe:

dbmopen(%db, $path, 0) or die $!;
my $writable = eval { $db{__probe__} = 1; delete $db{__probe__}; 1 };
warn "read-only\n" unless $writable;

Large database — avoid keys / values, which materialise the whole list in memory. Use each instead:

dbmopen(%big, $path, 0) or die $!;
while (my ($k, $v) = each %big) {
    process($k, $v);
}
dbmclose %big;

Edge cases#

  • Hash sigil is required. dbmopen %h, $name, 0666 — writing $h or \%h does not work. The first slot is the hash’s name as a hash, not a reference.

  • MASK = 0 is the “open existing only” idiom. A plausible-looking 0666 silently creates a fresh empty database if the file is missing, which is almost never what a reader wants on a cache lookup path.

  • Extensions are managed by the backend. Do not pass "cache.dir" or "cache.pag" — pass "cache". sdbm appends .dir / .pag; gdbm writes to the bare name.

  • One open per process for older DBM. If the backend is the traditional dbm(3) library (rare today), a process may only have a single DBM open at a time. sdbm and gdbm do not have this limit.

  • Value size limits. sdbm caps keys + values at roughly 1008 bytes per record; oversize writes are truncated or rejected. gdbm and Berkeley DB have much higher limits. When in doubt, use tie with DB_File and check the backend’s own limits.

  • Numeric values are bytes on disk. Storing $h{k} = 42 writes the string "42", not an integer. Pack explicitly with pack / unpack when the field needs a fixed binary layout (as in the news-history example above).

  • Closing is optional but recommended. The bind is released when the hash goes out of scope, but explicit dbmclose or untie flushes pending writes and surfaces close-time errors.

  • Re-binding an already-bound hash. Calling dbmopen on a hash that is already bound closes the previous binding first.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • dbmclose — release a dbmopen binding and flush pending writes

  • tie — the modern replacement; pair with DB_File, GDBM_File, SDBM_File, or AnyDBM_File to pick a backend explicitly

  • untie — release a binding made with either dbmopen or tie

  • each — stream entries without materialising the whole database in memory

  • umask — masks the MASK argument when backing files are created

  • open — the ordinary file-open built-in, which takes a filehandle and not a hash