mirror of
https://github.com/samba-team/samba.git
synced 2024-12-24 21:34:56 +03:00
s3:first cut at dbwrap_tool - a tdb tool that is CTDB-aware.
This tool (in contrast to tdbtool) reads Samba's configuration and if clustering = yes, it talks to CTDB instead of accessing the TDB data bases directly. This is done by simply using the dbwrap mechanim, just like the Samba daemons. This first version can read and write int32 and uint32 values and delete records from a (c)tdb database. More operations will follow. This tool can already be useful in CTDB environments, e.g. when "net idmap restore" fails to set the USER and GROUP HWM keys, because the methods are deliberately not implemented in idmap_tdb2.c. You can manually set the high water marks with "dbwrap_tool store idmap_tdb2.tdb 'USER HWM' int32 12345" and "dbwrap_tool store idmap_tdb2.tdb 'GROUP HWM' int32 67890" Michael
This commit is contained in:
parent
4dce2dfb5b
commit
6d82b59755
@ -1217,6 +1217,10 @@ RPC_OPEN_TCP_OBJ = torture/rpc_open_tcp.o \
|
||||
../librpc/rpc/binding.o \
|
||||
$(LIBMSRPC_GEN_OBJ)
|
||||
|
||||
DBWRAP_STORE_INT32_OBJ = utils/dbwrap_tool.o \
|
||||
$(PARAM_OBJ) \
|
||||
$(LIB_NONSMBD_OBJ) \
|
||||
$(LIBSAMBA_OBJ)
|
||||
|
||||
######################################################################
|
||||
# now the rules...
|
||||
@ -2866,6 +2870,13 @@ bin/test_lp_load@EXEEXT@: $(BINARY_PREREQS) $(TEST_LP_LOAD_OBJ) @BUILD_POPT@ @LI
|
||||
$(LDAP_LIBS) \
|
||||
$(POPT_LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS)
|
||||
|
||||
bin/dbwrap_tool@EXEEXT@: $(DBWRAP_STORE_INT32_OBJ) @LIBTALLOC_TARGET@ @LIBTDB_TARGET@
|
||||
@echo "Linking $@"
|
||||
@$(CC) -o $@ $(DBWRAP_STORE_INT32_OBJ)\
|
||||
$(LDFLAGS) $(DYNEEXP) $(LIBS) \
|
||||
$(LDAP_LIBS) \
|
||||
$(LIBTALLOC_LIBS) $(LIBTDB_LIBS)
|
||||
|
||||
install:: installservers installbin @INSTALL_CIFSMOUNT@ @INSTALL_CIFSUPCALL@ installman \
|
||||
installscripts installdat installmodules @SWAT_INSTALL_TARGETS@ \
|
||||
@INSTALL_PAM_MODULES@ installlibs installmo
|
||||
|
247
source3/utils/dbwrap_tool.c
Normal file
247
source3/utils/dbwrap_tool.c
Normal file
@ -0,0 +1,247 @@
|
||||
/*
|
||||
Samba Unix/Linux CIFS implementation
|
||||
|
||||
low level TDB/CTDB tool using the dbwrap interface
|
||||
|
||||
Copyright (C) 2009 Michael Adam <obnox@samba.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
extern bool AllowDebugChange;
|
||||
|
||||
typedef enum { OP_FETCH, OP_STORE, OP_DELETE } dbwrap_op;
|
||||
|
||||
typedef enum { TYPE_INT32, TYPE_UINT32 } dbwrap_type;
|
||||
|
||||
static int dbwrap_tool_fetch_int32(struct db_context *db,
|
||||
const char *keyname,
|
||||
void *data)
|
||||
{
|
||||
int32_t value;
|
||||
|
||||
value = dbwrap_fetch_int32(db, keyname);
|
||||
d_printf("%d\n", value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dbwrap_tool_fetch_uint32(struct db_context *db,
|
||||
const char *keyname,
|
||||
void *data)
|
||||
{
|
||||
uint32_t value;
|
||||
bool ret;
|
||||
|
||||
ret = dbwrap_fetch_uint32(db, keyname, &value);
|
||||
if (ret) {
|
||||
d_printf("%u\n", value);
|
||||
return 0;
|
||||
} else {
|
||||
d_fprintf(stderr, "ERROR: could not fetch uint32 key '%s'\n",
|
||||
keyname);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int dbwrap_tool_store_int32(struct db_context *db,
|
||||
const char *keyname,
|
||||
void *data)
|
||||
{
|
||||
NTSTATUS status;
|
||||
int32_t value = *((int32_t *)data);
|
||||
|
||||
status = dbwrap_trans_store_int32(db, keyname, value);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
d_fprintf(stderr, "ERROR: could not store int32 key '%s': %s\n",
|
||||
keyname, nt_errstr(status));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dbwrap_tool_store_uint32(struct db_context *db,
|
||||
const char *keyname,
|
||||
void *data)
|
||||
{
|
||||
NTSTATUS status;
|
||||
uint32_t value = *((uint32_t *)data);
|
||||
|
||||
status = dbwrap_trans_store_uint32(db, keyname, value);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
d_fprintf(stderr,
|
||||
"ERROR: could not store uint32 key '%s': %s\n",
|
||||
keyname, nt_errstr(status));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dbwrap_tool_delete(struct db_context *db,
|
||||
const char *keyname,
|
||||
void *data)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
status = dbwrap_trans_delete_bystring(db, keyname);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
d_fprintf(stderr, "ERROR deleting record %s : %s\n",
|
||||
keyname, nt_errstr(status));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dbwrap_op_dispatch_table {
|
||||
dbwrap_op op;
|
||||
dbwrap_type type;
|
||||
int (*cmd)(struct db_context *db,
|
||||
const char *keyname,
|
||||
void *data);
|
||||
};
|
||||
|
||||
struct dbwrap_op_dispatch_table dispatch_table[] = {
|
||||
{ OP_FETCH, TYPE_INT32, dbwrap_tool_fetch_int32 },
|
||||
{ OP_FETCH, TYPE_UINT32, dbwrap_tool_fetch_uint32 },
|
||||
{ OP_STORE, TYPE_INT32, dbwrap_tool_store_int32 },
|
||||
{ OP_STORE, TYPE_UINT32, dbwrap_tool_store_uint32 },
|
||||
{ OP_DELETE, TYPE_INT32, dbwrap_tool_delete },
|
||||
{ OP_DELETE, TYPE_UINT32, dbwrap_tool_delete },
|
||||
{ 0, 0, NULL },
|
||||
};
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
struct tevent_context *evt_ctx;
|
||||
struct messaging_context *msg_ctx;
|
||||
struct db_context *db;
|
||||
|
||||
uint16_t count;
|
||||
|
||||
const char *dbname;
|
||||
const char *opname;
|
||||
dbwrap_op op;
|
||||
const char *keyname;
|
||||
const char *keytype = "int32";
|
||||
dbwrap_type type;
|
||||
const char *valuestr = "0";
|
||||
int32_t value = 0;
|
||||
|
||||
TALLOC_CTX *mem_ctx = talloc_stackframe();
|
||||
|
||||
int ret = 1;
|
||||
|
||||
load_case_tables();
|
||||
DEBUGLEVEL_CLASS[DBGC_ALL] = 0;
|
||||
dbf = x_stderr;
|
||||
AllowDebugChange = false;
|
||||
lp_load(get_dyn_CONFIGFILE(), true, false, false, true);
|
||||
|
||||
if ((argc != 4) && (argc != 5) && (argc != 6)) {
|
||||
d_fprintf(stderr,
|
||||
"USAGE: %s <database> <op> <key> [<type> [<value>]]\n"
|
||||
" ops: fetch, store, delete\n"
|
||||
" types: int32, uint32\n",
|
||||
argv[0]);
|
||||
goto done;
|
||||
}
|
||||
|
||||
dbname = argv[1];
|
||||
opname = argv[2];
|
||||
keyname = argv[3];
|
||||
|
||||
if (strcmp(opname, "store") == 0) {
|
||||
if (argc != 6) {
|
||||
d_fprintf(stderr, "ERROR: operation 'store' requires "
|
||||
"value argument\n");
|
||||
goto done;
|
||||
}
|
||||
valuestr = argv[5];
|
||||
keytype = argv[4];
|
||||
op = OP_STORE;
|
||||
} else if (strcmp(opname, "fetch") == 0) {
|
||||
if (argc != 5) {
|
||||
d_fprintf(stderr, "ERROR: operation 'fetch' requires "
|
||||
"type but not value argument\n");
|
||||
goto done;
|
||||
}
|
||||
op = OP_FETCH;
|
||||
keytype = argv[4];
|
||||
} else if (strcmp(opname, "delete") == 0) {
|
||||
if (argc != 4) {
|
||||
d_fprintf(stderr, "ERROR: operation 'delete' does "
|
||||
"not allow type nor value argument\n");
|
||||
goto done;
|
||||
}
|
||||
op = OP_DELETE;
|
||||
} else {
|
||||
d_fprintf(stderr,
|
||||
"ERROR: invalid op '%s' specified\n"
|
||||
" supported ops: fetch, store, delete\n",
|
||||
opname);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (strcmp(keytype, "int32") == 0) {
|
||||
type = TYPE_INT32;
|
||||
value = (int32_t)strtol(valuestr, NULL, 10);
|
||||
} else if (strcmp(keytype, "uint32") == 0) {
|
||||
type = TYPE_UINT32;
|
||||
value = (int32_t)strtoul(valuestr, NULL, 10);
|
||||
} else {
|
||||
d_fprintf(stderr, "ERROR: invalid type '%s' specified.\n"
|
||||
" supported types: int32, uint32\n",
|
||||
keytype);
|
||||
goto done;
|
||||
}
|
||||
|
||||
evt_ctx = tevent_context_init(mem_ctx);
|
||||
if (evt_ctx == NULL) {
|
||||
d_fprintf(stderr, "ERROR: could not init event context\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
msg_ctx = messaging_init(mem_ctx, server_id_self(), evt_ctx);
|
||||
if (msg_ctx == NULL) {
|
||||
d_fprintf(stderr, "ERROR: could not init messaging context\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
db = db_open(mem_ctx, dbname, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
|
||||
if (db == NULL) {
|
||||
d_fprintf(stderr, "ERROR: could not open dbname\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (count = 0; dispatch_table[count].cmd != NULL; count++) {
|
||||
if ((op == dispatch_table[count].op) &&
|
||||
(type == dispatch_table[count].type))
|
||||
{
|
||||
ret = dispatch_table[count].cmd(db, keyname, &value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
TALLOC_FREE(mem_ctx);
|
||||
return ret;
|
||||
}
|
Loading…
Reference in New Issue
Block a user