s3-messages: only include messages.h where needed.
[kai/samba.git] / source3 / utils / dbwrap_tool.c
1 /*
2    Samba Unix/Linux CIFS implementation
3
4    low level TDB/CTDB tool using the dbwrap interface
5
6    Copyright (C) 2009 Michael Adam <obnox@samba.org>
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "system/filesys.h"
24 #include "dbwrap.h"
25 #include "messages.h"
26
27 typedef enum { OP_FETCH, OP_STORE, OP_DELETE, OP_ERASE, OP_LISTKEYS } dbwrap_op;
28
29 typedef enum { TYPE_INT32, TYPE_UINT32 } dbwrap_type;
30
31 static int dbwrap_tool_fetch_int32(struct db_context *db,
32                                    const char *keyname,
33                                    void *data)
34 {
35         int32_t value;
36
37         value = dbwrap_fetch_int32(db, keyname);
38         d_printf("%d\n", value);
39
40         return 0;
41 }
42
43 static int dbwrap_tool_fetch_uint32(struct db_context *db,
44                                     const char *keyname,
45                                     void *data)
46 {
47         uint32_t value;
48         bool ret;
49
50         ret = dbwrap_fetch_uint32(db, keyname, &value);
51         if (ret) {
52                 d_printf("%u\n", value);
53                 return 0;
54         } else {
55                 d_fprintf(stderr, "ERROR: could not fetch uint32 key '%s'\n",
56                           keyname);
57                 return -1;
58         }
59 }
60
61 static int dbwrap_tool_store_int32(struct db_context *db,
62                                    const char *keyname,
63                                    void *data)
64 {
65         NTSTATUS status;
66         int32_t value = *((int32_t *)data);
67
68         status = dbwrap_trans_store_int32(db, keyname, value);
69
70         if (!NT_STATUS_IS_OK(status)) {
71                 d_fprintf(stderr, "ERROR: could not store int32 key '%s': %s\n",
72                           keyname, nt_errstr(status));
73                 return -1;
74         }
75
76         return 0;
77 }
78
79 static int dbwrap_tool_store_uint32(struct db_context *db,
80                                     const char *keyname,
81                                     void *data)
82 {
83         NTSTATUS status;
84         uint32_t value = *((uint32_t *)data);
85
86         status = dbwrap_trans_store_uint32(db, keyname, value);
87
88         if (!NT_STATUS_IS_OK(status)) {
89                 d_fprintf(stderr,
90                           "ERROR: could not store uint32 key '%s': %s\n",
91                           keyname, nt_errstr(status));
92                 return -1;
93         }
94
95         return 0;
96 }
97
98 static int dbwrap_tool_delete(struct db_context *db,
99                               const char *keyname,
100                               void *data)
101 {
102         NTSTATUS status;
103
104         status = dbwrap_trans_delete_bystring(db, keyname);
105
106         if (!NT_STATUS_IS_OK(status)) {
107                 d_fprintf(stderr, "ERROR deleting record %s : %s\n",
108                           keyname, nt_errstr(status));
109                 return -1;
110         }
111
112         return 0;
113 }
114
115 static int delete_fn(struct db_record *rec, void *priv)
116 {
117         rec->delete_rec(rec);
118         return 0;
119 }
120
121 /**
122  * dbwrap_tool_erase: erase the whole data base
123  * the keyname argument is not used.
124  */
125 static int dbwrap_tool_erase(struct db_context *db,
126                              const char *keyname,
127                              void *data)
128 {
129         int ret;
130
131         ret = db->traverse(db, delete_fn, NULL);
132
133         if (ret < 0) {
134                 d_fprintf(stderr, "ERROR erasing the database\n");
135                 return -1;
136         }
137
138         return 0;
139 }
140
141 static int listkey_fn(struct db_record *rec, void *private_data)
142 {
143         int length = rec->key.dsize;
144         unsigned char *p = (unsigned char *)rec->key.dptr;
145
146         while (length--) {
147                 if (isprint(*p) && !strchr("\"\\", *p)) {
148                         d_printf("%c", *p);
149                 } else {
150                         d_printf("\\%02X", *p);
151                 }
152                 p++;
153         }
154
155         d_printf("\n");
156
157         return 0;
158 }
159
160 static int dbwrap_tool_listkeys(struct db_context *db,
161                                 const char *keyname,
162                                 void *data)
163 {
164         int ret;
165
166         ret = db->traverse_read(db, listkey_fn, NULL);
167
168         if (ret < 0) {
169                 d_fprintf(stderr, "ERROR listing db keys\n");
170                 return -1;
171         }
172
173         return 0;
174 }
175
176 struct dbwrap_op_dispatch_table {
177         dbwrap_op op;
178         dbwrap_type type;
179         int (*cmd)(struct db_context *db,
180                    const char *keyname,
181                    void *data);
182 };
183
184 struct dbwrap_op_dispatch_table dispatch_table[] = {
185         { OP_FETCH,  TYPE_INT32,  dbwrap_tool_fetch_int32 },
186         { OP_FETCH,  TYPE_UINT32, dbwrap_tool_fetch_uint32 },
187         { OP_STORE,  TYPE_INT32,  dbwrap_tool_store_int32 },
188         { OP_STORE,  TYPE_UINT32, dbwrap_tool_store_uint32 },
189         { OP_DELETE, TYPE_INT32,  dbwrap_tool_delete },
190         { OP_ERASE,  TYPE_INT32,  dbwrap_tool_erase },
191         { OP_LISTKEYS, TYPE_INT32, dbwrap_tool_listkeys },
192         { 0, 0, NULL },
193 };
194
195 int main(int argc, const char **argv)
196 {
197         struct tevent_context *evt_ctx;
198         struct messaging_context *msg_ctx;
199         struct db_context *db;
200
201         uint16_t count;
202
203         const char *dbname;
204         const char *opname;
205         dbwrap_op op;
206         const char *keyname = "";
207         const char *keytype = "int32";
208         dbwrap_type type;
209         const char *valuestr = "0";
210         int32_t value = 0;
211
212         TALLOC_CTX *mem_ctx = talloc_stackframe();
213
214         int ret = 1;
215
216         load_case_tables();
217         lp_set_cmdline("log level", "0");
218         setup_logging(argv[0], DEBUG_STDERR);
219         lp_load(get_dyn_CONFIGFILE(), true, false, false, true);
220
221         if ((argc < 3) || (argc > 6)) {
222                 d_fprintf(stderr,
223                           "USAGE: %s <database> <op> [<key> [<type> [<value>]]]\n"
224                           "       ops: fetch, store, delete, erase, listkeys\n"
225                           "       types: int32, uint32\n",
226                          argv[0]);
227                 goto done;
228         }
229
230         dbname = argv[1];
231         opname = argv[2];
232
233         if (strcmp(opname, "store") == 0) {
234                 if (argc != 6) {
235                         d_fprintf(stderr, "ERROR: operation 'store' requires "
236                                   "value argument\n");
237                         goto done;
238                 }
239                 valuestr = argv[5];
240                 keytype = argv[4];
241                 keyname = argv[3];
242                 op = OP_STORE;
243         } else if (strcmp(opname, "fetch") == 0) {
244                 if (argc != 5) {
245                         d_fprintf(stderr, "ERROR: operation 'fetch' requires "
246                                   "type but not value argument\n");
247                         goto done;
248                 }
249                 op = OP_FETCH;
250                 keytype = argv[4];
251                 keyname = argv[3];
252         } else if (strcmp(opname, "delete") == 0) {
253                 if (argc != 4) {
254                         d_fprintf(stderr, "ERROR: operation 'delete' does "
255                                   "not allow type nor value argument\n");
256                         goto done;
257                 }
258                 keyname = argv[3];
259                 op = OP_DELETE;
260         } else if (strcmp(opname, "erase") == 0) {
261                 if (argc != 3) {
262                         d_fprintf(stderr, "ERROR: operation 'erase' does "
263                                   "not take a key argument\n");
264                         goto done;
265                 }
266                 op = OP_ERASE;
267         } else if (strcmp(opname, "listkeys") == 0) {
268                 if (argc != 3) {
269                         d_fprintf(stderr, "ERROR: operation 'listkeys' does "
270                                   "not take a key argument\n");
271                         goto done;
272                 }
273                 op = OP_LISTKEYS;
274         } else {
275                 d_fprintf(stderr,
276                           "ERROR: invalid op '%s' specified\n"
277                           "       supported ops: fetch, store, delete\n",
278                           opname);
279                 goto done;
280         }
281
282         if (strcmp(keytype, "int32") == 0) {
283                 type = TYPE_INT32;
284                 value = (int32_t)strtol(valuestr, NULL, 10);
285         } else if (strcmp(keytype, "uint32") == 0) {
286                 type = TYPE_UINT32;
287                 value = (int32_t)strtoul(valuestr, NULL, 10);
288         } else {
289                 d_fprintf(stderr, "ERROR: invalid type '%s' specified.\n"
290                                   "       supported types: int32, uint32\n",
291                                   keytype);
292                 goto done;
293         }
294
295         evt_ctx = tevent_context_init(mem_ctx);
296         if (evt_ctx == NULL) {
297                 d_fprintf(stderr, "ERROR: could not init event context\n");
298                 goto done;
299         }
300
301         msg_ctx = messaging_init(mem_ctx, procid_self(), evt_ctx);
302         if (msg_ctx == NULL) {
303                 d_fprintf(stderr, "ERROR: could not init messaging context\n");
304                 goto done;
305         }
306
307         db = db_open(mem_ctx, dbname, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
308         if (db == NULL) {
309                 d_fprintf(stderr, "ERROR: could not open dbname\n");
310                 goto done;
311         }
312
313         for (count = 0; dispatch_table[count].cmd != NULL; count++) {
314                 if ((op == dispatch_table[count].op) &&
315                     (type == dispatch_table[count].type))
316                 {
317                         ret = dispatch_table[count].cmd(db, keyname, &value);
318                         break;
319                 }
320         }
321
322 done:
323         TALLOC_FREE(mem_ctx);
324         return ret;
325 }