perlgdbm

GDBM_File interoperability issue transitioning from older 32-bit Perl to 64-bit Perl


I have some GDBM files created using an old 32-bit (i686) version of Perl (5.8.6) that I want to use with an x86_64 Perl 5.28.0, but it doesn't work. Here's my test code:

use strict;
use warnings;
use GDBM_File;

my $dbmfile = "/path/to/gdbm_test_file";
my %DBM;

eval {
    my $ok = tie(%DBM, 'GDBM_File', $dbmfile, &GDBM_WRCREAT, 0664);
    die "Error: Bad status!\n" unless $ok;
};
die "Error: Could not open $dbmfile.\n" if $@;

foreach my $key (sort(keys(%DBM))) {
    print "$key :: $DBM{$key}\n";
}
untie %DBM;

If I run this code with the older i686 Perl and $dbmfile pointing to a GDBM file recently created by the same i686 Perl, it correctly reads the GDBM file and prints out its contents.

If I run this code with x86_64 Perl 5.28.0, however, it just silently fails. No error. No output at all.

If I run this code with x86_64 Perl 5.10.1, the eval catches the "Bad status" error, and I get Error: Could not open /path/to/gdbm_test_file.

If I create a new GDBM file using x86_64 Perl 5.28.0 and try to read it with the old i686 Perl, i686 Perl dies with read error on the foreach line.

Platform: CentOS 6.8

gdbm.i686 and gdbm.x86_64 packages are both installed and both are the same version: 1.8.0-39

Any suggestions? Is this not possible?


Solution

  • Given your comment about how 32-bit gdbm databases and 64-bit gdbm databases aren't compatible, I'd use a 32-bit version of the gdbm_dump utility to dump the database to a flat file, and then feed it to a 64-bit version of gdbm_load to re-create the database so it can be read by the 64-bit perl gdbm library.

    You might have to build these from source to get the appropriate versions depending on what packages CentOS provides - I'm not familiar with it.


    Alternatively, write a quick tool using the 32-bit version of perl to read the 32-bit gdbm database and convert it to a different dbm that doesn't suffer from the same problem so both 32-bit and 64-bit programs can use the same file.

    Psuedocode:

    tie my %gdbm, 'GDBM_File', 'olddb.gdbm', read-only options;
    tie my %other, 'Other_DBM', 'newdb.whatever', write/create options;
    while (my ($key, $value) = each %gdbm) {
        $other{$key} = $value;
    }
    untie %gdbm;
    untie %other;