int DbWrapper::load(std::istream *in, unsigned long *lineno) { int version, ret, t_ret; DBTYPE dbtype; char *subdb = 0; u_int32_t read_flags, tflags; DBT key, data; db_recno_t recno, datarecno; DB_ENV *dbenv = environment_; memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); if ((ret = __db_rheader(dbenv, db_, &dbtype, &subdb, &version, &read_flags, read_callback, in, lineno)) != 0) goto err; /* We always print with keys */ if (!(read_flags & DB_READ_HASKEYS)) { db_->errx(db_, "Invalid DbXml dump: keys missing"); ret = EINVAL; goto err; } if ((ret = open(NULL, dbtype, DB_CREATE|DB_EXCL)) != 0) goto err; /* Initialize the key/data pair. */ if (dbtype == DB_RECNO || dbtype == DB_QUEUE) { key.size = sizeof(recno); key.data = &datarecno; } else { key.ulen = 1024; key.data = (void *)malloc(key.ulen); } data.ulen = 1024; data.data = (void *)malloc(data.ulen); if (key.data == NULL || data.data == NULL) { db_->err(db_, ENOMEM, NULL); goto err; } // work around gcc optimizer issue that seems to modify // read_flags (4.1.1 on 64-bit linux) tflags = read_flags; /* Get each key/data pair and add them to the database. */ for (recno = 1;; ++recno) { if ((ret = __db_rdbt(dbenv, &key, &data, tflags, read_callback, in, lineno)) != 0) { if (ret == EOF) ret = 0; break; } switch (ret = db_->put(db_, NULL, &key, &data, 0)) { case 0: break; case DB_KEYEXIST: db_->errx(db_, "line %d: key already exists, not loaded:", *lineno); dbenv->prdbt(&key, tflags & DB_READ_PRINTABLE, 0, &std::cerr, pr_callback, 0); break; default: db_->err(db_, ret, NULL); goto err; } } err: /* Close the database. */ if ((t_ret = close(0)) != 0 && ret == 0) ret = t_ret; /* Free allocated memory. */ if (subdb != NULL) free(subdb); if (key.data != NULL && dbtype != DB_RECNO && dbtype != DB_QUEUE) free(key.data); if (data.data != NULL) free(data.data); return (ret); }